先日、 GitHub Actions で遭遇した問題について。
main ブランチに入っている workflow にて他のブランチを checkout して CI/CD 関連の処理をしたいことがありました。
通常は他のブランチに main ブランチを merge すればよいのですが、並行で開発ラインが走っていて main ブランチの workflow に修正が入ったときに古い workflow を他のブランチで実行してほしくないという背景があり、このような方法を採用することになりました。
やったこと
GitHub Actions を手動実行します。ただし、「Use workflow form」を常に main ブランチで実行するようにし、${{ github.ref }}
で main ブランチでの実行になっているか判定します。
「Use workflow form」というのはブランチが選べるプルダウンのことです。
workflow_dispatch で手動実行する場合、ここでどのブランチに入っている workflow のバージョンで実施するかを選択できます。当然、main ブランチには入っているけど、feature/A ブランチには入っていない workflow がある場合、feature/A ブランチはここでは指定できません。
main ブランチで実施したかどうかを以下のように判定していました。
name: ブランチ名の表示
on:
workflow_dispatch:
jobs:
show-branch:
runs-on: ubuntu-latest
steps:
- name: main ブランチの workflow かを検証する
run: |
BRANCH_NAME="${{ github.ref_name }}"
if [ "$BRANCH_NAME" != "main" ]; then
echo "::error::この workflow は main ブランチで実行する必要があります。現在のブランチ: $BRANCH_NAME"
exit 1
fi
echo "ブランチの検証結果: main ブランチで実施されています。"
- name: チェックアウト
uses: actions/checkout@v4
with:
# main ブランチ以外のブランチを checkout したいが、
# default は直前のコミット 1 件のみ fetch するので、 0 (全ての履歴)と指定
fetch-depth: 0
ref: feature/not-main-branch
そして、この処理の後の step にて、ブランチ名の命名規則で、処理を分けたい箇所があり、再び ${{ github.ref_name }}
で参照することに。
ただ、${{ github.ref_name }}
は依然として main ブランチのままでした。あれ?
原因
${{ github.ref_name }}
は workflow 実行時に一度だけ自動で設定される環境変数でしかなく、checkout しているブランチが都度反映されるわけではありません。
公式ドキュメントにはそういった記載はありませんが、逆に step ごとで値が更新されるような自動環境変数には「ジョブのステップごとに変更されます。」などの注意書きが入っています。
そのため、ブランチ名を取得する際は BRANCH_NAME=$(git branch --show-current)
などで取得するのが好ましいようです。
既に記載した workflow の続きに、エビデンスとして以下を実行しました。
- name: ブランチ名を表示
run: |
# GitHub Actions の自動変数にて表示
echo "現在のブランチ名を表示(github.ref_name): ${{ github.ref_name }}"
echo "現在のブランチ名を表示(github.ref): ${{ github.ref }}"
# git コマンドにて表示
echo "現在のブランチ名を表示(git branch --show-current): $(git branch --show-current)"
確かに、feature/not-main-branch が checkout された後でも ${{ github.ref_name }}
は main のままになっていることがわかります。${{ github.ref }}
も同様です。
教訓
actions/checkout で ref で別ブランチを checkout するときは、以降のブランチ名は git コマンドから取得するようにします。