White Box技術部

WEB開発のあれこれ(と何か)

GitHub Actionsのテストをactを使って行う

GitHub Actionsのトリガーと分岐条件のテストにactを使ったので、そのときの知見です。

  • act version 0.2.55

M1 Macなので以下のaliasを設定して作業しました。

alias act='act --container-architecture linux/amd64'

書いていること

  • トリガーしたいブランチの指定方法
  • github.event_nameでworkflow_dispatchが返ってくる方法
  • false == ''がtrueの話(なんちゃって三項演算だと困るという話)

指定のブランチへのpushを検証する

  • act pushだけ行うとデフォルトブランチへのpushトリガーが発火するので、対象ブランチを変えたい場合は--defaultbranchオプションでブランチを指定します
  • ワークフローのファイルを指定しなかった場合、.github/workflowsディレクトリ配下の全ファイルがチェック対象になるので、 特定のファイルを指定したい場合は-Wオプションでファイルを指定します
stagingブランチへのpush確認
$ act push --defaultbranch staging
$ act push --defaultbranch staging -W .github/workflows/cd-staging.yml

手動実行ワークフローの検証をする

  • ワークフローに渡すパラメータは。JSONファイルに定義して-eオプションで指定します
  • 実行させたいワークフローは、実行したいジョブ名でも限定できます(--jobオプション)
手動実行の確認
$ act workflow_dispatch --job action-test -e act_cd.json -W .github/workflows/cd-staging.yml
$ act workflow_dispatch --job build-test -e act_build.json -W .github/workflows/build.yml

 ハマったところ

  • act workflow_dispatch 〜というようにworkflow_dispatchを入れないと、github.event_nameがworkflow_dispatchになりませんでした
  • act 〜だとinputのJSONファイルにactionをworkflow_dispatchで定義していても、github.event_nameはpushになっていました
    • そもそもJSONファイルにactionは記載しなくても動作しました
  • また通常はinputs.XXXXでとれるinputsの値が、actを利用した場合はgithub.event.inputs.XXXXと書かないと取れませんでした

ここまでのサンプルファイル

.github/workflows/cd-staging.yml

name: TEST Deploy
on:
  push:
    branches:
      - staging
  workflow_dispatch:
    inputs:
      deploy-app:
        description: "deploy app"
        type: boolean
        default: true
      migration:
        description: "migration"
        type: boolean
        default: false
jobs:
  build-images:
    uses: ./.github/workflows/build.yml
    with:
      build-app: true
      environment: "stg"
    if: ${{ github.event_name == 'push' }}
  action-test:
    runs-on: ubuntu-latest
    needs: build-images
    if: always()
    steps:
      - name: Check
        run: echo "${{ github.event.inputs }},${{ github.event_name }} deploy!"
      - name: Check deploy app Image
        if: ${{ github.event_name == 'push' || github.event.inputs.deploy-app }}
        run: echo "deploy-app true"
      - name: Check deploy migration Image
        if: ${{ github.event_name == 'push' || github.event.inputs.migration }}
        run: echo "deploy-migration true"

act_cd.json

{
  "action": "workflow_dispatch",
  "inputs": {
    "deploy-app": true,
    "migration": false
  }
}

.github/workflows/build.yml

name: TEST Build
on:
  workflow_call:
    inputs:
      build-app:
        required: true
        type: boolean
      environment:
        required: true
        type: string
  workflow_dispatch:
    inputs:
      build-app:
        description: "appのimage作成"
        type: boolean
        default: true
      environment:
        description: "environment"
        type: choice
        required: true
        options:
          - prd
          - stg
          - dev
jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Check
        run: echo "${{ inputs }},${{ github.event_name }} build!"
      - name: Check build app
        if: ${{ github.event_name == 'push' || github.event.inputs.build-app }}
        run: echo "build-app true"
      - name: Check build environment
        if: ${{ github.event_name == 'push' || github.event.inputs.environment }}
        run: echo "${{ github.event.inputs.environment }}"

act_build.json

{
  "action": "workflow_dispatch",
  "inputs": {
    "build-app": true,
    "environment": "stg"
  }
}

false == ''がtrueの話

最後にちょっと困った話を書いておきます。

GitHub Actionsのドキュメントなどには、$$||を使って、疑似的に三項演算子のような書き方をしているときがあります。

env:
  MY_ENV_VAR: ${{ github.ref == 'refs/heads/main' && 'value_for_main_branch' || 'value_for_other_branches' }}

説明のために解説すると、式A && 式B || 式Cという式があった場合、式Aがtrueであれば式Bの結果が、式Aがfalseであれば式Cの結果が返ってくるのですが、 これだと式Aで左辺の値が未定義ではなくfalseとして定義されているかをチェックすることができません。

というのもGitHub ActionsにはJavaScriptでいうところの厳密比較がないので、'' == falsenull == falseはtrueになり、チェックしたい値 == falseとした場合、 チェックしたい値がfalseでも未定義でも結果がtrueになるからです。

なんでこんなことでハマったのかというと、最初はgithub.event_nameのことを忘却しており、 ワークフローのトリガーがworkflow_callかworkflow_dispatchかをinputsの値の有無で判定しようとしたのですが、 inputsの変数にfalseが入ってきたときににっちもさっちもいかなくなったからでした。

前半の解説にちょいちょいgithub.event_nameやinputsの話が出てきているのはこれが理由です

まとめ

act自体はGitHubにymlファイルをpushすることなくワークフローが試せるのでおすすめです。
今回はやらなかったのですが、actでGITHUB_TOKENを利用したワークフローを試す場合は、自身のGitHub個人トークンを発行し、.secretsファイルから読み込ませるとできるはずです。

2024/01/18追記

inputsとGITHUB_TOKENの話はこちらに補足があります。

seri.hatenablog.com

あとがき

この記事を最近買ったNuPhy Air60 V2をMacBookの上に置いてBluetoothで繋いで書いたのですが、Discordのコミュニティで提供されていたQMK_firmware_nuphy_air60_v2_ansi_v1.1.1.binを適用した後も3回ほどBluetooth接続が切れてしまいました。 キーボード自体は思っていた以上に打ち心地が良かったので、改善されたfirmwareが出ることを期待しています。