😽

[GitHub Actions] Composite Actionを使って再利用可能なActionを作ろう

2021/10/05に公開
3

GitHub Actionsで複数のWorkflowを追加していくと、Workflow間で同一のStepが増えてくることはないでしょうか?
開発用、ステージング用、本番用と似たような処理が集まっているにも関わらず同じ記述を何度もしていることはないでしょうか?
本記事では、Composite Actionを使って再利用可能なActionを作成し、上記の課題を解決したいと思います。

Composite Actionについて

まず、Composite Actionについて簡単に解説します。
ここでは、再利用可能なActionを定義しています。
ファイル名は、action.yaml or action.ymlが使用できます。

.github/actions/test/action.yaml
name: "Composite Action"
description: "[Test] Composite Action"

runs:
  using: "composite"
  steps:
    - name: "Checkout"
      uses: actions/checkout@v2

    - name: "Hello World"
      shell: bash
      run: echo 'Hello World'

次に上で定義したActionを呼び出してみます。

.github/workflows/main.yaml
name: "Main Step"
on:
  pull_request:
    branches:
      - master
    types: [opened, synchronize, closed]

jobs:
  composite_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./.github/actions/test

ここでは最低限の記述のみ行なっていますが、inputを使った値の取得なども行うことができます。
このように、Composite Actionを使うことで再利用可能なActionを作成することができました。

uses:を使ってActionを使えるようになったのも割と最近の話。
GitHub Actions: Reduce duplication with action composition

inputを使った例

inputを使った例も載せときます。
先程同様、Actionから定義します。

.github/actions/test/action.yaml
name: "Test Composite Action"
description: "Test Composite Action"
inputs:
  python-version:
    default: '3.8'
    required: false

runs:
  using: "composite"
  steps:
    - name: "Checkout"
      uses: actions/checkout@v2

    - name: "Setup Python"
      uses: actions/setup-python@v2
      with:
        python-version: ${{ inputs.python-version }}

requiredより必須かどうかを定義できます。
また、defaultにより値が渡されなかった場合のDefault値を指定することも可能です。
次に、Actionを呼び出してみます。

.github/workflows/main.yaml
name: "Use composite action test"

on:
  pull_request:
    branches:
      - master
    types: [opened, synchronize, closed]

jobs:
  composite_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./.github/actions/test
        with:
          python-version: '3.9.1'

このようにinputを使ってActionに値を渡してあげることができました。

Composite Actionでできないこと

ifが使えない

現状、Composite Actionではif:を使うことができません。
そのため、以下のようにmergeした時のみ実行したい処理などをif:を使って書く事が出来ません。

- name: "if statement test"
  shell: bash
  if: github.event.pull_request.merged == true
  run: echo 'use if statement'

対処方法としては、以下のようにシェルスクリプトのstepでif文を使う方法があります。

- name: "if statement test"
  shell: bash
  run: |
    if ${{ github.event.pull_request.merged }} = 'true'; then
      echo "use if statement"
    fi

Logが見づらい

Composite Actionにて実行したWorkflowのログを見てみます。

Composite Actionを使わなかった場合を見てみましょう。

当たり前と言えば当たり前ですが、Composite Actionも1つのActionなので1つのstepにLogがまとめられます。
そのため、Composite Actionを使う前に比べて少し見辛くなるなと感じました。

まとめ

Composite Actionを使って再利用可能なActionを作ることができました。
ただ、if:が使えなかったり、Composite Actionのログの出力が見辛かったりする部分もあるので今後のUpdateに期待です。

しかし、これまで同様の処理を複数のWorkflowで何度も書いていたものが一箇所にまとまり、保守も容易になる事が期待されます。
皆さんもぜひ、試してください!

本記事では、同一リポジトリにて再利用可能なActionを定義しましたが、異なるリポジトリにてworkflow_callを使った再利用可能なActionの作成方法もあるのでこちらも併せてご覧ください。
Reusing workflows

Discussion

kinjo yuyakinjo yuya

compositeの記述参考にさせていただきました。

最後のほうのLogがみずらい件ですが、見出しがファイルパスになるから見えにくいのですかね?
nameプロパティを使用すると見えやすくなるかなと思いました!

action.yml
jobs:
  composite_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./.github/actions/test
        with:
          python-version: '3.9.1'

jobs:
  composite_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
+     - name: Test
        uses: ./.github/actions/test
        with:
          python-version: '3.9.1'
ksudateksudate

コメントありがとうございます!

見出しがファイルパスになるから見えにくいのですかね

なるほどです!情報ありがとうございます!

pepnovapepnova

参考になる記事書いてくださりありがとうございます。大変参考になりました。

ifが使えない

Composite Actionでもif: が使えるようになったようです。
もしお時間あれば本文に追記していただけると幸いです。🙏

https://github.blog/changelog/2021-11-09-github-actions-conditional-execution-of-steps-in-actions/
https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif