くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

GitHub ActionsのComposite Actionで処理を分割する

GitHub ActinonsにComposite Actionというのがあったので、
いろいろ試してみたときの備忘録(*´ω`*)

dorny/paths-filterを使ってたけど、
ワークフローファイルの変更時に無駄な処理を抑制できたり、
再利用以外も改善できて便利。。(*´ω`*)

Composite Action

複数を1つのアクションとして定義できる機能。
他のアクションと同様に、uses: ./.github/action/myactionなどで指定できる。

使い方

ディレクトリ構成はこんな感じ。

.github/
  actions/
    sample/
      action.yml ... 自作のComposite Action
  workflows/
    myworkflow.yml ... いつものワークフローファイル

Composite Action

.github/actions/sample/action.ymlは、こんな感じ。

name: "composite sample"
description: "composite action sample"
runs:
  # Composite Actionであることを指定
  using: "composite"
  steps:
    # 元のワークフローで定義したenv
    - run: echo "env.GLOBAL_ENV=${{ env.GLOBAL_ENV }}"
      shell: bash
    # アクションを指定した際に定義したenv
    - run: echo "local.env.LOCAL_ENV=${{ env.LOCAL_ENV }}"
      shell: bash
    - run: pwd
      shell: bash
    - run: node -v
      shell: bash

ファイル名はaction.ymlaction.yamlじゃないといけない。

Workflowファイル

.github/workflows/myworkflow.ymlは、こんな感じ。

name: workflow sample
on:
  push:
    branches:
      - main
env:
  GLOBAL_ENV: global
  
jobs:
  my_job:
    runs-on: ubuntu-latest
    steps:
      # リポジトリ内のActionを使うのでcheckoutが必要
      - uses: actions/checkout@v3
      # node.jsのインストール
      - uses: actions/setup-node@v3
      # Composite Actionを実行
      # action.ymlがあるディレクトリを指定
      - uses: "./.github/actions/sample"
        env:
          LOCAL_ENV: "local"

実行するとこんな感じ。

> Run ./.github/actions/sample
> Run echo "evn.GLOBAL_ENV=global"
evn.GLOBAL_ENV=global
> Run echo "evn.LOCAL_ENV=local"
evn.LOCAL_ENV=local
> Run pwd
/home/runner/work/my-org/my-repo
> Run node -v
v20.8.0
  • 環境変数は使い回せるし、追加で設定できる
  • checkoutやsetupなども利用できる

試してはいないけど、inputs/outputsも指定できる。
詳しくはこのあたり。

こんな感じのactions.ymlだと

name: 'Hello World'
description: 'Greet someone'
inputs:
  who-to-greet:  # id of input
    description: 'Who to greet'
    required: true
    default: 'World'
outputs:
  random-number:
    description: "Random number"
    value: ${{ steps.random-number-generator.outputs.random-number }}
runs:
  using: "composite"
  steps:
    - run: echo Hello ${{ inputs.who-to-greet }}.
      shell: bash
    - id: random-number-generator
      run: echo "random-number=$(echo $RANDOM)" >> $GITHUB_OUTPUT
      shell: bash
    - run: echo "${{ github.action_path }}" >> $GITHUB_PATH
      shell: bash
    - run: goodbye.sh
      shell: bash

こんな感じでワークフローファイルから利用できる。

on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
      - uses: actions/checkout@v4
      - id: foo
        uses: actions/hello-world-composite-action@v1
        with:
          who-to-greet: 'Mona the Octocat'
      - run: echo random-number ${{ steps.foo.outputs.random-number }}
        shell: bash

public repositoryでの公開/共有

inputs/outputsの例にあるように、 publicなリポジトリの直下にactions.ymlを配置しておくと、
他のリポジトリからも利用できる。

actions/hello-world-composite-action@v1の場合は、
actions/hello-world-composite-actionリポジトリ
v1タグの内容を参照している。

branchやコミットSHAを指定することもできるっぽい。

dorny/paths-filterとの併用

再利用しやすくなるのもあるけど、monorepoでのビルドやデプロイもよさそう。

こんな感じでワークフローファイルを修正したとにも、
それぞれがビルドされるようにしていたけど、
serverだけに関係するymlファイルの変更時にも、
webの処理が走ってしまって悩んでいた。。

shared: &shared
  - ".github/workflows/**"
  - "packages/commons/**"
web:
  - *shared
  - "packages/web/**"
server:
  - *shared
  - "packages/server/**"

Composite Actionを使えば、
それぞれのactionを分離できるので、
無駄に処理を省くことができる。

  shared: &shared
    - ".github/workflows/**"
    - "packages/commons/**"
  web:
    - *shared
+   - ".github/actions/web/**"
    - "packages/web/**"
  server:
    - *shared
+   - ".github/actions/server/**"
    - "packages/server/**"

CD/CI構築時とかは、無駄にデプロイされたくないので、
それ自体を分けられのは便利。。

workflow_callとかを使おうかと思ったら、
便利なのが見つかってよかった(*´ω`*)

参考にしたサイトさま