LoginSignup
4
2

GitHub ActionsでDockerコンテナ上でGitを操作する際の罠

Last updated at Posted at 2023-06-03

前提

  • 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.2safe.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を行うことができた
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2