Docker イメージの GitHub Actions を作り、outputs に値を出力させる

permission に注意


Posted on Tue, Sep 24, 2024
Tags githubactions, docker

GitHub Actions でカスタムアクションを作りたい

まず、前提として、GitHub Actions のカスタムアクションの定義はそこまで難しくなく、

  1. Actions の name, description, branding などのメタ情報
  2. inputs の入力値
  3. outputs の出力値
  4. 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 のようだ。

よって、解決策は下記となる。

  1. root で稼働する Dockerfile にする。解決した Dockerfile は結局 ko をやめて、wolfi-base という root user が存在するベースイメージにした。もちろん Ubuntu や Rocky などのイメージをベースにしても問題ない
  2. 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 を実現した例があるので、もしよければ参考にされたし。

Share with


See Also