Github Actionsでワークフロー内からpushしたあとに再度ワークフローを実行する

Github Actionsのワークフロー内でgit pushを行う際のメモ。

やりたいこと

Github Actionsのワークフロー内でPR作成時にファイルのdumpを行い、差分があった場合はそれをcommitしてpushしたい。 更に、pushしたあとも再度ワークフローが回るようにしたい。

ポイント

checkoutする際にbranchを指定する

以下のようにcheckout時にrefを指定しないと、pushした際にHEADがdetachedになってしまい、pushができない。

jobs:
  dump:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4 # <-- ここ
fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)

これを回避するためには、以下のようにrefを指定する。 ${{ github.head_ref }}でワークフローが走っているbranch名を取得できる。

jobs:
  dump:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }} # <-- これを追加

pushする際にPersonal Access Tokenを使う

上記の設定でpushすると、以下のようなエラーが出る。

remote: Write access to repository not granted.

これは、Github ActionsのデフォルトのトークンであるGITHUB_TOKENにwrite権限がないため。

回避するためにはcontentwrite権限を付けてあげれば良い。

permissions:
  contents: write

これでワークフロー内からpushできるようになるが、公式ドキュメントに記載がある通り、GITHUB_TOKENを使ってpushされば場合は、ワークフローがトリガーされない。(これはワークフロー実行が無限ループするのを防ぐため)

push後にワークフローが回るようにするためには、Personal Access Tokenを使う必要がある。

Personal Access Tokenにはrepoworkflowの権限をつけて作成し、リポジトリのSecretsに登録しておく。

以下のようにActions内でTokenを指定することで、push時にワークフローが回るようになる。

jobs:
  dump:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.head_ref }}
          token: ${{ secrets.MY_TOKEN }}

pushする部分

ワークフロー内からpushする部分は以下のように書ける。

jobs:
  dump:
    steps:
      ...
      - name: Push changes
        run: |
          if [ -n "$(git diff src/hello.wasm)" ]; then  # <-- ここは差分をチェックしたいファイルに合わせる
            git config --local user.email "github-actions[bot]@users.noreply.github.com"
            git config --local user.name "github-actions[bot]"
            git add src/hello.wasm
            git commit -m "chore: dump wasm file" --author=.  # <-- `author`に`.`を指定することで、直前のcommitのauthorを引き継げる
            git push
          fi