リポジトリから main ブランチをチェックアウトして、一部のファイルを書き換えてコミット&プッシュするワークフロー。
main へのプッシュをトリガーに別のワークフローが起動し、良い感じに CI/CD が動いているかと思った矢先の出来事でした。
なぜか main ブランチに対する push に反応しないワークフローが出てきてしまったのです。
今回はこの問題に取り組んだので解決までの道のりを紹介します。
ワークフローが起動しない状況
起動しないワークフローには「paths-ignore」を指定していたので、最初はそれを疑いました。
全てのコミットファイルが ignore の条件にマッチしてしまっているのではないかと。
しかし、ignore の条件を削っても発動しない。
もしかして、署名付きコミットじゃなく Verified が付いていないプッシュだから?
っと思いましたが、こちらもどうやら関係がなさそうです。
(公式のドキュメントに記載が見当たらなかった)
ここで再度、以下の 2 つのワークフローを整理してみます。
・main ブランチにプッシュしているワークフロー
・main ブランチの push をトリガーとするワークフロー
プッシュしているワークフロー
プッシュしているワークフローを見直してみましょう。
ファイル書き換えの部分は、シンプルなサンプルに置き換えています。
1 2 3 4 5 6 7 8 9 10 | steps: - name: Checkout uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Replace run: | echo "${{ github.sha }}" > test.txt - name: Commit & Push (省略) |
チェックアウトしてきて、test.txt の中身を書き換える。
最後にコミット&プッシュという流れですね。
このコミット&プッシュはサードパーティのアクションを使っていますが、自前の git コマンドに書き換えても挙動は変わらず。
まあサードパーティのアクションの方も、シェルの中で同じようなことをしているだけなんですけどね。
プッシュをトリガーとするワークフロー
こちらは paths-ignore を削ったので以下のようにログ出力するだけのシンプルな状態にしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | name: Continue on: push: branches: - main jobs: continue: name: Log runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Log run: | echo "Run." |
ただ、このワークフローが起動しないのですよね。
main ブランチに git クライアントなどから直接プッシュする時は動き出すのですが・・・。
せめて、ワークフローが起動しない場合のログがどこかに出力されていればヒントになるのに。
今回のケースは別として、paths や paths-ignore などの条件マッチの結果は知りたいケースが多いですよね。
ワークフローが発動しない原因が判明
以下の検索キーワードを組み合わせつつ情報を探したものの、有益な情報になかなか辿り着かず。
・github
・actions
・on
・push
・hook
・verified
ようやく見つけたのが下記のサイトでした。
これらの情報を総合すると、以下が原因ということがわかります。
たとえば、ワークフローの実行によってリポジトリのGITHUB_TOKENを使ったコードのプッシュが行われた場合、そのリポジトリにpushイベントが生じた際に実行されるよう設定されたワークフローが含まれていても、新しいワークフローの実行は行われません。
公式ドキュメント内のセキュリティガイドに書かれていましたが、最初から「GITHUB_TOKEN」を疑わないと辿り着かない。
ワークフローを書き始めた当初は、自分でパーソナルアクセストークンを設定したシークレット(secret)の名前を使っていたのですよね。
そのシークレットの名前を思い出すより、GitHub Actions が提供してくれる代理認証の GITHUB_TOKEN が使えるなら楽かと思って書き換えたのが失敗・・・。
まさか、そこに罠があるとは思ってもみませんでした。
この罠に引っかかって勉強できたこともあったので良しとしましょう。
解決方法
ということで、この問題の解決方法は 2 つあります。
checkout 時に GITHUB_TOKEN ではなく、パーソナルアクセストークンを指定する
冒頭のサンプルを書き換えてみます。
PERSONAL_ACCESS_TOKEN という名前のシークレットをリポジトリに登録して、それを token に指定するだけ。
1 2 3 4 5 6 7 8 9 10 | steps: - name: Checkout uses: actions/checkout@v3 with: token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - name: Replace run: | echo "${{ github.sha }}" > test.txt - name: Commit & Push (省略) |
checkout 時に persist-credentials のオプションを false で指定する
こちらは、token はそのままに checkout のオプションに persist-credentials を追加します。
1 2 3 4 5 6 7 8 9 10 11 | steps: - name: Checkout uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} persist-credentials: false - name: Replace run: | echo "${{ github.sha }}" > test.txt - name: Commit & Push (省略) |
特にこだわりがなければ、個人的には前者を選択でいいのかなと思っています。
そもそも GITHUB_TOKEN の存在なんて最近まで知りませんでしたから・・・。
まとめ
GitHub Action で、ワークフロー内の push から後続のワークフローが動作しない件について調べてみました。
結果的に、checkout 時に secrets.GITHUB_TOKEN を使ったのが原因というオチ。
自分の知らないものを利用する時は、しっかりと調べてから使わないとダメですね。
ただ、ノウハウが少ないものはブログネタになってありがたいところです。