GitHub Actions でカスタムアクションを作りたい
まず、前提として、GitHub Actions のカスタムアクションの定義はそこまで難しくなく、
- Actions の name, description, branding などのメタ情報
- inputs の入力値
- outputs の出力値
- runs で実際に動作するコマンド
の定義ができていれば簡単につくれてしまう。
この中で、outputs の仕様がやや複雑なのだが、Metadata syntax for GitHub Actions - GitHub Docs のとおり、GITHUB_OUTPUT 環境変数に定義されているファイルへ所定のフォーマットで文字列を書き込めば、次の step に outputs の内容を引き渡すことができる。
# 下記は image の情報などを省略している
runs:
steps:
- id: rand-gen
run: echo "random-id=$(echo $RANDOM)" >> $GITHUB_OUTPUT
shell: bash
# ${{ steps.<step id>.outputs.<output id> }} で前 step で出力された値がアクセスできる
- run: echo "${{ steps.rand-gen.outputs.random-id }}"
シンプルな例であれば、上記のように簡単な記載で完了するのだが、カスタムアクションで outputs に書き込みたい場合は、$GITHUB_OUTPUT
のファイルパスにカスタムのアクションから output_id=...
のフォーマットで追記する必要がある。
余談だが、outputs の内容が複数行になる場合は、下記のようなヒアドキュメントのような書き方で出力できる。
output_id<<ANY_UNIQUE_PLACE_HOLDER
...
ANY_UNIQUE_PLACE_HOLDER
ここで、$GITHUB_OUTPUT
は、/github/file_commands/set_output_<guid>
のような値になっている。
カスタムのアクションで $GITHUB_OUTPUT
のファイルへの書き込みが permission denied になる
カスタムアクションを作っていると、/github/file_commands/set_output_<guid>
への書き込みが、permission denied で失敗することが分かった。
time=2024-09-24T08:36:07.762Z level=DEBUG msg="Checking permissions"
time=2024-09-24T08:36:07.762Z level=DEBUG msg="Current process user name and id" user=nonroot uid=65532
time=2024-09-24T08:36:07.762Z level=DEBUG msg="file info" fi="&{Dev:2065 Ino:550836 Nlink:1 Mode:33188 Uid:1001 Gid:127 X__pad0:0 Rdev:0 Size:0 Blksize:4096 Blocks:0 Atim:{Sec:1727166955 Nsec:581692099} Mtim:{Sec:1727166955 Nsec:581692099} Ctim:{Sec:1727166955 Nsec:581692099} X__unused:[0 0 0]}"
Error: print result: open file of GITHUB_OUTPUT: open /github/file_commands/set_output_81a41ae4-699c-4a1e-ba50-eb26527a4d69: permission denied
これは結論から言うと、カスタムアクションを Dockerfile で定義して動かしていると、カスタムアクションの host (大体は ubuntu-latest
のようなものを指定している)のディレクトリへ Docker 内の uid 次第ではアクセスが許可されないようだ。
自作していたカスタムアクションは、ko を使って docker image を作ったのだが、chainguard という rootless コンテナがベースとなっている。
rootless コンテナの uid は 65534 (no body) などに設定される。
しかし、上記のログのとおり、/github/file_commands/set_output_81a41ae4-699c-4a1e-ba50-eb26527a4d69
のファイルは uid 1001 が所有者になっている。
この uid 1001 は host で定義されている GitHub Acions 向けの user のようだ。
よって、解決策は下記となる。
- root で稼働する Dockerfile にする。解決した Dockerfile は結局 ko をやめて、wolfi-base という root user が存在するベースイメージにした。もちろん Ubuntu や Rocky などのイメージをベースにしても問題ない
- GitHub Acions の user (uid 1001) を Dockerfile 内で useradd で定義する
- 注: これで実際に permission denied が解決できるかは実際に試したわけではないため、推測であげている
ここの仕様はインターネット上に情報としてあまり記載されておらず、解決するのがやや難儀したので、記事にした。
https://github.com/go-zen-chu/aictl/blob/9c0d780ebb4c3594a8e0aed1f5248f042fd25a57/cmd/aictl/cmd/query.go#L103-L123 に実際に Go 言語で開発したカスタムアクションの outputs を実現した例があるので、もしよければ参考にされたし。