GitHub Actionsを使い始めて、Stepsの共通化で詰まった話

## はじめに
最近、仕事で初めてGitHub Actionsを触らせてもらったので、
GitHub Actionsについて本記事で共有し、複数WorkflowでStepの共通化で詰まった話を記載します。

## GitHub Actionsについて
GitHub Actionsは、GitHub上でPR(Pull Request)の作成やマージをトリガーにしてビルドやテスト、デプロイ等を自動で実行できるツールです。

GitHubレポジトリでどんなイベントをトリガーにして、ワークフローを実行するかはYAMLファイル(`.gitHub/workflows/`配下に配置)で定義します。
ワークフローファイルと呼びます。

```yaml:.github/wrokflows/learn-github-actions.yml(公式より)
name: learn-github-actions
on: [push]
jobs:
  check-bats-version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '14'
      - run: npm install -g bats
      - run: bats -v
```

https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions

## ワークフローファイルについて
上記のワークフローファイルを例にどんなワークフローになっているか見ていきます。

### name
ワークフローの名称です。
GitHubリポジトリのActionsタブ内で表示されます。
上記の例だと、`learn-github-actions`という名称で表示されます。

```yaml
name: learn-github-actions
```

### on
ワークフローを実行するためのトリガーを設定することができます。
上記の例だと、リポジトリに対してpushをトリガーにしてワークフローを実行しています。

また、ワークフローファイルのpushアクションの配下に`branches: - master`のように記述すると、どのブランチに対してpushするとワークフローを実行するかを指定できます。

```yaml
on: [push]
```

### jobs
ワークフロー内の一連のステップ(後述)を集めたものがjobsです。
jobs内に実行するstepsを記述していきます。
また、上記の例ではjobs配下に`check-bats-version`とありますが、これは実行するジョブの名称を示しています。

```yaml
jobs:
  check-bats-version:
```

必要に応じて、jobs間で依存関係を指定し、実行順序を設定できます。
以下の例では、job1が正常に完了後、job2を実行し、job2が正常に完了したらjob3が動作するようになっています。

```yaml
jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]
```

https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#

### steps
stepsでは、実行したいコマンドを設定することができます。
ソースコードのチェックアウトを行う`actions/checkout`やnode環境のセットアップを行う`actions/setup-node`を以下の様に記述することができます。

```yaml
steps:
  - uses: actions/checkout@v3
  - uses: actions/setup-node@v3
    with:
      node-version: '14'
```

## 複数ワークフローの共通化で詰まった話
### 動作環境
当社のプロダクトが動作する環境として、`本番・デモ・ステージング`の３つがあります。

デモ環境へのデプロイ反映は当社のCTOに属人化している課題があったため、
GitHub Actionsを使用してデモ環境デプロイを非属人化するタスクが起案され、CI/CDを初めて触れる機会をいただきました。

### エラー発生
まず対応として、ステージング環境は既にワークフローファイルが存在していたので、それを参考にしながらデモ環境用のワークフローファイルを作成していました。

作成していくうちに、ステージングのワークフローファイルと重複するstepsが多くなりました。
別ファイルへ切り出して動作確認したところ、下記のエラーが発生し、切り出したファイルに`actions/checkout`を記述等して動作確認しても、なかなか解消することができずにいました。

```
Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '/home/runner/work/xxxx/xxxx/.github/workflows/deploy.yml'. Did you forget to run actions/checkout before running your local action?
```

### 解消方法: Composite Run Step
上記エラーの解消方法として使ったのが、**Composite Run Step**です。
リポジトリがパブリック・プライベートのいずれでも使うことができます。

同一リポジトリで管理したい場合は下記の構成となり、Composite Run Stepはactionsディレクトリ配下になり、ファイル名もaction.ymlに指定します。

|Type|Path|
|---|---|
|Workflow|.github/workflow/TEMPLATE.yml|
|Composite Run Step|.github/actions/TEMPLATE/action.yml|

### action.ymlの書き方
ワークフローファイルとさほど変わりませんが、下記の違いがあります。

- runs配下に`using: "composite"`を指定
- runs:steps以降にワークフローの重複stepを持ってくる
- 他のアクションをuseできない(ので、複数のstepをまとめてCompositeに持ってくる場合は事前に順番の整理したほうがいい)

```yaml
name: Build
inputs:
  environment: 
    description: "deploy environment"
    required: true
runs:
  using: "composite"
  steps:
    - uses: actions/setup-node@v3
      with:
        node-version: "14"
```

### ワークフローファイルでの書き方
下記のsteps内の様に、`actions/checkout@v3`でソースコードのチェックアウトとactionsファイルの相対指定が必要になります。

チェックアウトしないと、共通化したaction.ymlを見つけられず、相対指定にしなかった場合、外部リポジトリを探しにいってしまうため、上記の指定が必要になります。

```yml
name: Deploy

on:
  push:
    branches:
      - demonstration

env: ...

jobs:
  deploy:
  runs-on: ubuntu-latest
  ...

  steps:
    - name: Checkout
      uses: actions/checkout@v3
    - name: Build
      uses: ./.github/actions/build
```

こちらの記事を参考にさせていただきました。

https://dev.classmethod.jp/articles/composite-run-step-with-private-repos/

## おわりに
GitHub Actions触ってみたら面白かったです（多少詰まりましたが笑）。
terraformも一緒にいじってたので、次はterraformの記事書こうかなと思います。


## 参考記事
以下の記事を参考にさせていただきました！
ありがとうございます。

https://qiita.com/M-Yamashii/items/44d32586a498ffced3aa

https://qiita.com/HeRo/items/935d5e268208d411ab5a

https://dev.classmethod.jp/articles/composite-run-step-with-private-repos/

https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions