この記事は?
- すごく久々にGitHub Actionsを触った
- Actionsを流している中で、「変更差分が生まれたものをリポジトリに保存したい」となった
- その中で The requested URL returned error: 403 で引っかかった
- あれこれ引っかかったので自分用のメモとしても残すことにした
ちょっとだけ経緯説明
なぜ、Actionsの中でgit pushしたかったか?
元々やりたかったこと
JavaのプログラムをGitHub Actionsでビルドして、そのビルド結果を特定の場所に置く。
置いたファイルを別のツールが取得し、そのツールがAWSにデプロイする... ということがやりたかった。
要はCI/CDである。
正攻法を取ると
公式ドキュメントのワークフロー データを成果物として保存するに沿って成果物を格納し、ワークフローの成果物をダウンロードする に沿って、GitHub CLIで落とすのが良いと思います。
じゃあなんで正攻法にしなかったの?
利用するCDのツールが GitHub のWebhookで飛ばされてくるイベントを解釈してから動き出すのですが、このツールでは残念ながら「GitHub Actionsの処理が完了したこと」をトリガーにすることができなかったのです。
そのためやや美しくはないのですが、「GitHub Actionsでビルドした成果物を再度、リポジトリの特定のディレクトリに格納することでpushのイベントを起こし、それをトリガーとしてファイル取得をする」とすることにしました。
で、結局どんな設定をすればいいの?
まずはActions全体で書き込み権限をもらえ
リポジトリの設定で、 [Settings]>[Actions]> [General] に遷移すると一般設定があるので、ここで一番上を選んで読み書きの権限をActionsに付与してあげてください。
画像中では一番下のチェックボックスにチェックが入っていますが、pull requestに関わる処理を行う時に必要となるだけで、今回の話題としてはチェック外れていても大丈夫です。
pushするユーザを設定せよ
yamlの中で、git pushするためのgitのユーザ指定を行います。
ユーザ名、メールアドレスはenvとしてまとめるのが綺麗だと思いました。
その際、好みにもよりますが、調べる限り、次の設定が良さそうです。
env:
GITHUB_MAIL: 41898282+github-actions[bot]@users.noreply.github.com
GITHUB_NAME: github-actions[bot]
実際に自身のユーザアカウントを使うこともできますが、この設定だとGitHub Actionsで動いたものとして区別出来るので視認性という意味で良さそうです。
pushするための書き込み権限を付与せよ
Actionsでの動作にはワークフロー実行時に発行されるアクセストークン(GITHUB_TOKEN)が使用されます。
GITHUB_TOKENについての公式ドキュメント にもあるように、権限は狭いものになっています。
もっと言えば、2023年2月以降に作成されたリポジトリではデフォルトのパーミッションが読み取りのみに設定されているようです。
See: GitHub Actions - Updating the default GITHUB_TOKEN permissions to read-only | GitHub Changelog
GITHUB_TOKENはジョブが失敗するタイミング、または最大24時間でその権限は失効するとのことですが、その権限は利用するAPIに紐づいて設定する必要があるようです。
つまり。こちらのAPI一覧を見つつ、必要なものに対して権限をwriteにしてあげることになります。
https://docs.github.com/en/rest/overview/permissions-required-for-github-apps?apiVersion=2022-11-28#contents
今回の記事目的からはpushに関するものなので、contentsですが、場合によってはそれ以外の設定も必要になるかと思います。
permissions:
contents: write
こちらの記事のように、えいやっと全部writeにしてしまうのも良いのですが、使うものに合わせて権限付与する方が望ましいです。
pushのjobを書け
あとはjobを書くだけです。
次の誰かのために書き方サンプル置いておきます。このサンプルはmainにpushするものになっているので、ブランチ戦略に合わせて書き換えが必要なことにご注意ください。
name: Java build with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: write
env:
OUTPUT_WAR_FILE: output.war
GITHUB_MAIL: 41898282+github-actions[bot]@users.noreply.github.com
GITHUB_NAME: github-actions[bot]
jobs:
build:
runs-on: ubuntu
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
- name: Setup and execute Gradle 'clean' and 'build' task
uses: gradle/gradle-build-action@v2
with:
arguments: clean build
- name: Set current datetime as env variable
env:
TZ: 'Asia/Tokyo'
run: echo "CURRENT_DATETIME=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV
- name: Commit artifact
run: |
git remote set-url origin https://github-actions:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git config --local user.email ${{ env.GITHUB_MAIL }}
git config --local user.name ${{ env.GITHUB_NAME }}
cp -p build/libs/${{ env.OUTPUT_WAR_FILE }} output/${{ env.OUTPUT_WAR_FILE }}
echo -e ${{ env.CURRENT_DATETIME }} > ${{ env.DELIVERY_DIR }}/build_date.txt
git add output/${{ env.OUTPUT_WAR_FILE }}
git add output/build_date.txt
git commit -m ":robot: GitHub Actionsによるビルド結果格納:${{ env.CURRENT_DATETIME }}"
git push origin main
こんな感じのcommitが増えます。commit message に :robot:
を入れておくと絵文字でメッセージ送れるので、自動化されてる感がちょっと増す気がします。
TIPS
APIからいちいち権限探すのめんどくせーな、と思っていたら、わりかし最近に「権限を教えてくれる仕組み」ができたpublic betaで公開された様子。
See: https://developer.mamezou-tech.com/blogs/2023/06/28/set-minimum-permissions-to-github-actions-workflow/