俺のブログ

学習メモや日記をつらつらと書きます。

GitHub Actions 条件式の罠

GitHub Actionsの条件式でハマった話

こんにちは。今回は、GitHub ActionsでCI/CDを実装する際に、特定のブランチにマージしたときにだけ実行したいコマンドがあり、その条件式の設定で少しハマったので共有します。

発生した問題

GitHub Actionsの条件式にブランチ名を設定しようとしたところ、意図しない動作となってしまいました。 具体的には、以下のようにpush先のブランチがmainブランチの時に真になるようにと条件式を記述したのですが、この書き方ではどのブランチ名に対しても真になってしまいました。

if: ${{ github.ref_name }} == "main"

github.ref_name などのGitHubコンテキストについてはこちらを参照してください。

docs.github.com

解決方法

すべてのブランチ名が真になってしまう理由は、次の公式ドキュメントに記載の通りでした。

式構文 ${{ }} を使用すると、内容が文字列に変わり、文字列は真値です。 たとえば、if: true && ${{ false }} は true に評価されます。 GitHub Actions のワークフロー構文 - GitHub Docs

正しくは、以下のように ${{ }} を外して記述する必要があるようです。

if: github.ref_name == "main"

この記述方法であれば、意図通りmainブランチにマージされたときだけ、条件式が真となり、コマンドが実行されます。

実験

この仕様を踏まえて少し実験をしてみました。 次の、3種類の条件式でPush先のブランチ名がmainブランチかどうかの条件式を記述しました。

  1. if ${{ github.ref_name }} == 'main'
    すべてのブランチに対して真になる
  2. if github.ref_name == 'main'
    mainブランチにpushした時にのみ真になる
  3. 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の条件式でブランチ名を指定する際は、${{ }} を外して記述しましょう。 もしデプロイするコマンドが入っていたら想定外の本番デプロイが発生するかもしれません。