GitHub Actions で service のコンテナにリポジトリのファイルをマウントしようとするとエラーになる #GitHub #Actions
概要
GitHub Actions では、ジョブのサービスとして MySQL や Redis が使える。
volumes ( jobs.<job_id>.services.<service_id>.volumes
) を指定することで、サービス間やステップ間でデータを共有できる。
ただソースコードは通常 actions/checkout を利用すると思うが、リポジトリで管理しているようなファイルパスをそのままマウントしようとエラーになる。
rm: cannot remove '/home/runner/work/your_repo/path/to/mysql/conf.d': Permission denied
たとえば下記のような Workflow である。
jobs: job-name: runs-on: ubuntu-latest services: mysql: image: mysql ports: - 3306:3306 volumes: - ${{github.workspace}}/path/to/mysql/conf.d:/etc/mysql/conf.d steps: - uses: actions/checkout@v3
原因
Workflow のジョブはサービスが立ち上がった後に動くため、 actions/checkout はマウント後に動く。
そうするとチェックアウトするディレクトリにマウントするディレクトリが存在する(空ではない)とされて、 actions/checkout は一度対象ディレクトリの中を空にしようとするようだ。
その際、サービスを動かすユーザーと actions/checkout を動かすユーザー(権限)異なるため、エラーになってしまう。
解決策
リポジトリをチェックアウトするディレクトリと、マウントする場所を分ければ解決する。
jobs.<job_id>.defaults.run
の working-directory を設定する- チェックアウト場所を working-directory にする
- 対象ファイルを cp などで移動する
jobs: job-name: runs-on: ubuntu-latest defaults: run: working-directory: my_target services: mysql: image: mysql ports: - 3306:3306 volumes: - ${{github.workspace}}/path/to/mysql/conf.d:/etc/mysql/conf.d steps: - uses: actions/checkout@v3 with: path: my_target - run: | cp -r path/to/mysql/conf.d ${{github.workspace}}/path/to/mysql/conf.d
補足
working-directory の default を指定しているのは、 step の追加・変更時にパスをできるだけ意識せずに済むようにするため。
別に workflow 単位でも指定できるし、 step の中で cd してもよい。
例では MySQL の設定ファイルをマウントしているが、反映するためには大抵再起動が必要になるので、実際には data ファイルとかになると思う(テストデータを step 間で使い回すとか?)。