GitHub Actionsの条件式でハマった話
こんにちは。今回は、GitHub ActionsでCI/CDを実装する際に、特定のブランチにマージしたときにだけ実行したいコマンドがあり、その条件式の設定で少しハマったので共有します。
発生した問題
GitHub Actionsの条件式にブランチ名を設定しようとしたところ、意図しない動作となってしまいました。 具体的には、以下のようにpush先のブランチがmainブランチの時に真になるようにと条件式を記述したのですが、この書き方ではどのブランチ名に対しても真になってしまいました。
if: ${{ github.ref_name }} == "main"
github.ref_name
などのGitHubコンテキストについてはこちらを参照してください。
解決方法
すべてのブランチ名が真になってしまう理由は、次の公式ドキュメントに記載の通りでした。
式構文 ${{ }} を使用すると、内容が文字列に変わり、文字列は真値です。 たとえば、if: true && ${{ false }} は true に評価されます。 GitHub Actions のワークフロー構文 - GitHub Docs
正しくは、以下のように ${{ }}
を外して記述する必要があるようです。
if: github.ref_name == "main"
この記述方法であれば、意図通りmainブランチにマージされたときだけ、条件式が真となり、コマンドが実行されます。
実験
この仕様を踏まえて少し実験をしてみました。 次の、3種類の条件式でPush先のブランチ名がmainブランチかどうかの条件式を記述しました。
if ${{ github.ref_name }} == 'main'
すべてのブランチに対して真になるif github.ref_name == 'main'
mainブランチにpushした時にのみ真になるcontains(github.ref_name, 'main')
mainという文字列を含むブランチにpushした時に真になる
実験で使用したコード
name: Test CI on: push: branches: - main - release jobs: build-pipeline: runs-on: ubuntu-latest environment: ${{ github.ref_name }} steps: - uses: actions/checkout@v4 - name: always run run: echo ${{ github.ref_name }} - name: condition with $ and {} if: ${{ github.ref_name }} == 'main' # Pushされたブランチがmainの時は実行する run: | echo "Done" - name: condition without $ and {} if: github.ref_name == 'main' # Pushされたブランチがmainの時は実行する run: | echo "Done" - name: condition with contains if: contains(github.ref_name, 'main') # Pushされたブランチがmainの時は実行する run: | echo "Done"
実験コード github.com
実験結果
上記のコードを利用して、mainブランチからreleaseブランチにマージを行いました。実験で使用したGitHub Actions( Merge pull request #4 from takeru1205/main · takeru1205/ci-test@e6fc87f · GitHub)
その結果、つぎの画像のように1つ目の ${{}}
を利用した条件式だけは条件式が真となってしまいコマンドが実行されてしまいました。
まとめ
GitHub Actionsの条件式でブランチ名を指定する際は、${{ }}
を外して記述しましょう。
もしデプロイするコマンドが入っていたら想定外の本番デプロイが発生するかもしれません。