【GitHub Actions】Composite Actionを初めて使ってみたので軽くまとめてみる

最近業務において、CircleCI→GitHub Actionsへ移行する作業の一部をやっている。
ただ知見がないため、調べて知ったこと&実際に業務中に発生した超基本的なエラー内容と解決を残しておく

# 概要
- 今回やっていたこと
    - 1つのワークフロー内に複数ジョブを定義するコードを書いていた
- 発生した問題
    - 各ジョブのステップ内に**重複する同一内容のコマンド**が散見され、非常に冗長なワークフローファイルとなってまっていた
- 今回とった解決策
    - `Composite Action`という、ワークフローと同一リポジトリ内で独自のアクションを作成する手法で、重複しているステップ処理を切り出して利用できるようにした


# Composite Actionとは？
- 公式: [複合アクションを作成する - GitHub Docs](https://docs.github.com/ja/actions/creating-actions/creating-a-composite-action)
- `composite`とは直訳すると「複合の」「混成の」といった意味
    - 直訳すると`複合アクション`
        - 直訳だけだとよくわからないかもだが、以下にわかりやすく書かれている
        - [重複の回避 - GitHub Docs](https://docs.github.com/ja/actions/using-workflows/avoiding-duplication)
:::note info
※抜粋した内容
複合アクション を使用すると、複数のステップを 1 つのアクションにまとめることができます。 その後、このステップのバンドルをワークフロー内のシングル ステップとして実行できます。 これは、複数のワークフローで使用される一連の手順がある場合に便利です。 複合アクションを使用すると、長い YAML ワークフロー ファイルを大幅に縮小されたファイルにリファクタリングし、ワークフロー ファイル間でのコピーとペーストを回避することができます。
:::

→要するに、**複数ステップを一つのアクション(ファイル)としてまとめていろんなとこで利用できるよ！** という解釈

## Composite Actionのファイルやディレクトリの置き場所

- Composite Actionのファイルを置くディレクトリは任意の場所で大丈夫だが、わかりやすさの観点からワークフローファイルの近くに置くのが望ましい
    - **ファイル名は`action.yml`か`action.yaml`という名称しか付けられないので注意**
    - `.github`以下に`actions`というディレクトリを切り、その下にさらにアクションごとの名称が付いたディレクトリを切っていくと良いかもしれない
```例
.github/
   ├ actions
     ├ {{用途ごとに分けたディレクトリ}}
            ├ action.yml
     ├ {{用途ごとに分けたディレクトリ}}
            ├ action.yml
```

## `action.yml`の記法(メタデータ構文の記法)
`action.yml`は通常のワークフロー構文と書き方が似ているが、少々異なる **メタデータ構文(Metadate Syntax)** で書く必要がある
公式： [GitHub Actions のメタデータ構文 - GitHub Docs](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions)

主なもの
- [`name`(アクション名)](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#name)
    - **必須項目**
    - ワークフローのstepと同じく`name`を使ってアクションの名前をつける
```yaml
name: SampleName
```

- [`description`（アクションの説明）](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#description)
    - **必須項目**
    - アクションに関する説明を記入する
    - アクションの概要がわかるように少し長くなってもいいのでわかりやすく書いたほうが良い
```yaml
description: |
  ここにアクションに関する説明を書きます
  ちょっと長いくらいがわかりやすくてよい？
```

- [`inputs`（アクションへの入力値）](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#inputs)
    - 任意項目
    - アクションに対して入力パラメータを送信できる
```yaml
inputs:
  sample-input-value:                         # 入力ID
    default: 'true'                       # 入力パラメータのデフォルト値
    required: false                       # 入力パラメータの必須フラグ
    description: ここに入力パラメータの概要を書きます    # 入力パラメータの概要
```

- [`outputs`(アクションの出力値)](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-composite-actions)
    - アクションの値を、ワークフロー（アクション呼び出し側）へ出力したいときに使用
    - `value`キーを指定して、その値を渡す
    - stepsコンテキスト経由で値を渡すことが多い
```yaml
outputs:
  sample-output-value:                               # 出力ID
    value: ${{ steps.current.outputs.date }} # 出力する値
    description: ダンプ日時                       # 出力値の概要
```


- アクションのメインロジック(`runs`)
    - `runs`キー以下に記述していく
    - 公式: [GitHub Actions のメタデータ構文 - GitHub Docs](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions)
- composition actionの場合は、`using`キーの値に`composite`を指定
- 具体的なアクションはワークフローと同じように`steps`以下に書いていく
```yaml
runs:
  using: composite         # compositeを指定する
  steps:                   # メインロジックを書いていく
    - run: printenv | sort
      shell: bash # runを使用する場合には必ずシェル指定が必要
```

メインロジックの注意点
- ワークフロー構文での`run`キーではシェル指定(`shell: bash`など)を省略できるが、メタデータ構文ではできない
    - 省略するとアクションが起動せずエラーになる
    - 各ステップに必ず指定する必要があり忘れやすいため注意
- stepは基本`run`か`uses`のどちらかが必須
```yaml
steps:
  - run: echo "aciton!"
    shell: bash # これ指定しないとメタデータ構文ではエラー（ワークフローでは省略可）
```



- アクション呼び出し側（ワークフロー側）
    1. **アクションを呼び出す前にソースコードをチェックアウトする**
    1. **`uses`キーには`./`で始まるパスを指定**して、`uses`キーで呼び出し
この２つは忘れやすいので注意
```yaml
jobs:
  test-workflow-job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4     # アクション呼び出し前にチェックアウト
      - uses: ./.github/actions/{{アクションのディレクトリ}}/ # アクションの呼び出し
```


# 発生したエラー 
実際にComposite Actioを実装していたときに発生したエラー（超基本的なものしかないです）

## Error: Can’t find ‘action.yml’, ‘action.yaml’ or ‘Dockerfile’ under ‘’hoge/fuga/aaa’. Did you forget to run actions/checkout before running your local action?

原因: 新規ファイルがステージングできてないだけだった（大爆笑そして即死）
解決： ちゃんとaddしましょう

## ./.github/actions/tests/action.yml (Line: 28, Col: 7): Required property is missing: shell

原因： `run`キーに`shell: bash`が抜けていた
解決： 忘れずに入れましょう

## GitHub.DistributedTask.ObjectTemplating.TemplateValidationException: The template is not valid

原因：　自分の場合は`uses`を2つ続けて書いてしまっていた
```yaml
uses: aaa
uses: bbb
```
解決: usesは各ステップで1つずつ使用しましょう
```yaml
- uses: aaa
- uses: bbb
```
（nameつけたほうが良いとは思うが、、、↑でもOK）