前提
- GitHub ActionsのセルフホステッドランナーではGitHubホステッドランナーとは異なり、ジョブ毎に隔離された仮想マシンが起動し、その中でジョブが実行されるわけではない
- そのため、ジョブ内で行ったサーバの設定変更がセルフホステッドランナーを起動しているホストマシンに直接影響してしまう
- これではジョブ間で実行される環境が変わってしまい、イミュータブルでなくなってしまう
- そのため、各ジョブは可能な限りGitHub Actionsが提供するDockerコンテナ上で動作させる機能を使用し、セルフホステッドランナーを起動しているホストマシンへの影響を最小化させることが好ましい
問題点
- GitHub Actionsのジョブにおいて
git push
を行ったり、git log
を取得したりといったGitの操作は比較的よく行われる - しかしDockerコンテナ上でジョブを実行した場合、直接ホストマシン上でジョブを実行する場合と比べ、様々な罠が存在する
検証
- 上記の問題点を踏まえ、以下にその検証の過程と解決策についてまとめた
検証1
- Dockerコンテナ上で
git push
を行う最低限のコードを実行 - 設定
.github/workflows/example.yml
name: Git example
on:
push
jobs:
git-push:
runs-on:
- ubuntu-latest
# Dockerコンテナイメージの指定
container:
image: debian:stable-slim
steps:
# Gitリポジトリにチェックアウト
- name: Checkout repository
uses: actions/checkout@v3
# git commit、git pushするための最低限の設定
- name: Commit & push
run: |
git config user.name github-actions
git config user.email github-actions@github.com
# 今回は例なので --allow-empty オプションを付与して空のコミットを作成している
git commit --allow-empty -m "Test commit"
git push
- 実行結果
/__w/_temp/09fdd765-0703-40c9-80b8-2c04c2e0eef1.sh: 1: git: not found
Error: Process completed with exit code 127.
- このDockerイメージにはGitがインストールされていないという旨のエラーが発生している
検証2
- 検証1の設定にGitをインストールするステップを追加
- 設定
.github/workflows/example.yml
...
steps:
- name: Checkout repository
uses: actions/checkout@v3
+ - name: Install git
+ run: |
+ apt-get update
+ apt-get install git -y
- name: Commit & push
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git commit --allow-empty -m "Test commit"
git push
- 実行結果
fatal: not in a git directory
Error: Process completed with exit code 128.
- 1つ目のステップでGitリポジトリをチェックアウトしているはずだが、Gitリポジトリではないという旨のエラーが発生している
検証3
- チェックアウトしたGitリポジトリにどんなファイルとディレクトリが格納されているのか調査する
- 設定
.github/workflows/example.yml
...
steps:
- name: Checkout repository
uses: actions/checkout@v3
+ - name: Display files
+ run: ls -la
- name: Install git
run: |
apt-get update
apt-get install git -y
...
- 実行結果
total 12
drwxr-xr-x 3 1001 123 4096 Jun 1 22:31 .
drwxr-xr-x 3 1001 123 4096 Jun 1 22:31 ..
drwxrwxr-x 3 root root 4096 Jun 1 22:31 .github
- Gitリポジトリの場合、本来
.git
ディレクトリが作成されているはずだが存在していない - そのせいでGitリポジトリではないという旨のエラーが発生しているということが分かった
- どうやら
actions/checkout@v3
はGitが存在しない場合、GitHub REST APIを使用してGitリポジトリにチェックアウトしている模様
検証4
- GitのインストールをGitリポジトリのチェックアウトよりも先に実行してみる
- 設定
.github/workflows/example.yml
...
steps:
+ - name: Install git
+ run: |
+ apt-get update
+ apt-get install git -y
- name: Checkout repository
uses: actions/checkout@v3
...
- 実行結果
total 16
drwxr-xr-x 4 1001 123 4096 Jun 1 22:34 .
drwxr-xr-x 3 1001 123 4096 Jun 1 22:34 ..
drwxr-xr-x 8 root root 4096 Jun 1 22:34 .git
drwxr-xr-x 3 root root 4096 Jun 1 22:34 .github
-
.git
ディレクトリが作成されていることが確認できた
fatal: not in a git directory
Error: Process completed with exit code 128.
- しかし依然としてGitリポジトリではないという旨のエラーが発生している
検証5
-
actions/checkout@v3
ではホストマシンにクローンしたリポジトリをDockerコンテナ上にボリュームマウントするような挙動をしている - そのため、Dockerコンテナの現在のユーザからGitで操作できないファイルやディレクトリのパーミッションが設定されている可能性があるという仮説を立てた
- 調査すると、
git 2.35.2
でsafe.directory
という設定が導入されており、ここに設定されていないディレクトリでかつ現在のユーザが所有者でないGitリポジトリは安全ではないとみなしてGitから操作できないようになっている模様 - そのため、
git config --global --add safe.directory $PWD
という設定を追加 - 設定
.github/workflows/example.yml
...
steps:
- name: Install git
run: |
apt-get update
apt-get install git -y
- name: Checkout repository
uses: actions/checkout@v3
+ - name: Add safe directory
+ run: git config --global --add safe.directory $PWD
- name: Commit & push
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git commit --allow-empty -m "Test commit"
git push
- 実行結果
[master 0f925af] Test commit
remote: Permission to XXXXXXXX/XXXXXXXX.git denied to github-actions[bot].
fatal: unable to access 'https://github.com/XXXXXXXX/XXXXXXXX/': The requested URL returned error: 403
Error: Process completed with exit code 128.
- どうやらGitリポジトリではないという旨のエラーは解決できた模様
- しかし今度は
git push
を行うためのパーミッションが無いという旨のエラーが発生している
検証6
- GitHub Actionsに書き込み権限を付与する
.github/workflows/example.yml
name: Git example
on:
push
+ permissions:
+ contents: write
jobs:
git-push:
runs-on:
- ubuntu-latest
...
- こうすることで無事、GitHub Actionsから
git push
を行うことができた