GitHub Enterprise Server の受信前フックの例を github/platform-samples
リポジトリで参照できます。
pre-receiveフックスクリプトの作成
受信前フック スクリプトは、上の 受信前フック スクリプト環境で実行されます。 受信前フック スクリプトを作成する際には、利用可能な入力、出力、終了ステータス、環境変数について考慮します。
入力 (stdin
)
プッシュが発生した後で、リモート リポジトリに関して参照が更新される前に、上の git-receive-pack
プロセスが受信前フック スクリプトを呼び出します。 このスクリプトの標準入力 stdin
は、更新する参照ごとの行を含む文字列です。 各行には、参照の古いオブジェクト名、参照の新しいオブジェクト名、および参照の完全な名前が含まれています。
<old-value> SP <new-value> SP <ref-name> LF
この文字列は次の引数を表します。
引数 | 説明 |
---|---|
<old-value> | 参照に� �納されている古いオブジェクト名。 新しい参照を作成するとき、値は 40 個のゼロです。 |
<new-value> | 参照に� �納される新しいオブジェクト名。 参照を削除するとき、値は 40 個のゼロです。 |
<ref-name> | 参照の完全な名前。 |
git-receive-pack
の詳細については、Git ドキュメントの「git-receive-pack」を参照してく� さい。 参照の詳細については、Pro Git の「Git 参照」を参照してく� さい。
出力 (stdout
)
スクリプトの標準出力 stdout
はクライアントに返されます。 すべての echo
ステートメントは、コマンド ラインまたはユーザー インターフェイスでユーザーに表示されます。
終了ステータス
受信前スクリプトの終了ステータスによって、プッシュが受け付けられるかどうかが決まります。
終了ステータスの値 | アクション |
---|---|
0 | プッシュは受け付けられます。 |
0 以外 | プッシュは拒否されます。 |
環境変数
受信前フック スクリプトの標準入力 stdin
に� え、GitHub Enterprise Server によって、スクリプトの実行のために次の変数が Bash 環境で使用できるようになります。 受信前フック スクリプトの stdin
の詳細については、「入力 (stdin
)」を参照してく� さい。
受信前フック スクリプトで使用できる環境変数は、スクリプトが実行するトリガーに応じて異なります。
常に使用可能かどうか
次の変数は、受信前フック環境で常に使用できます。
変数 | 説明 | 値の例 |
---|---|---|
$GIT_DIR | インスタンス上のリモート リポジトリのパス | /data/user/repositories/a/ab/ a1/b2/34/100001234/1234.git |
$GIT_PUSH_OPTION_COUNT | クライアントによって --push-option で送信されたプッシュ オプションの数。 詳細については、Git ドキュメントの「git-push」を参照してく� さい。 | 1 |
$GIT_PUSH_OPTION_N | ここで N は 0 から始まる整数です。この変数にはクライアントから送信されたプッシュ オプションの文字列が含まれます。 送信された最初のオプションは GIT_PUSH_OPTION_0 、送信された 2 番目のオプションは GIT_PUSH_OPTION_1 のように、� �に� �納されます。 プッシュ オプションの詳細については、Git ドキュメントの「git-push」を参照してく� さい。 | abcd |
$GIT_USER_AGENT | 変更をプッシュした Git クライアントから送信されたユーザーエージェント文字列 | git/2.0.0 |
$GITHUB_REPO_NAME | 更新対象のリポジトリの名前 (NAME/OWNER 形式) | octo-org/hello-enterprise |
$GITHUB_REPO_PUBLIC | 更新対象のリポジトリがパブリックかどうかを表すブール値 |
|
$GITHUB_USER_IP | プッシュを開始したクライアントの IP アドレス | 192.0.2.1 |
$GITHUB_USER_LOGIN | プッシュを開始したアカウントのユーザー名 | octocat |
Web インターフェイスまたは API からのプッシュで使用可能
$GITHUB_VIA
変数を受信前フック環境で使用できるのは、フックをトリガーする参照更新が GitHub Enterprise Server の Web インターフェイスまたは API を介して発生するときです。 値は、参照を更新したアクションを表します。
値 | アクション | 説明を見る |
---|---|---|
auto-merge deployment api | API を使用して作成されたデプロイを介したベース ブランチの自動マージ | REST API ドキュメントの「デプロイの作成」 |
blob#save | Web インターフェイスでのファイルの内容に対する変更 | 「ファイルの編集」 |
branch merge api | API を使用したブランチのマージ | REST API ドキュメントの「ブランチのマージ」 |
branches page delete button | Web インターフェイスでのブランチの削除 | 「リポジトリ内でブランチを作成および削除する」 |
git refs create api | API を使用した参照の作成 | REST API ドキュメントの「Git データベース」 |
git refs delete api | API を使用した参照の削除 | REST API ドキュメントの「Git データベース」 |
git refs update api | API を使用した参照の更新 | REST API ドキュメントの「Git データベース」 |
git repo contents api | API を使用したファイルの内容に対する変更 | REST API ドキュメントの「ファイル コンテンツの作成または更新」 |
pull request のマージで使用可能
次の変数を受信前フック環境で使用できるのは、フックをトリガーするプッシュが pull request のマージによるプッシュであるときです。
変数 | 説明 | 値の例 |
---|---|---|
$GITHUB_PULL_REQUEST_AUTHOR_LOGIN | pull request を作成したアカウントのユーザー名 | octocat |
$GITHUB_PULL_REQUEST_HEAD | pull request のトピック ブランチの名前 (USERNAME:BRANCH 形式) | |
$GITHUB_PULL_REQUEST_BASE | pull request のベース ブランチの名前 (USERNAME:BRANCH 形式) | octocat:main |
SSH 認証を使用したプッシュで使用可能
変数 | 説明 | 値の例 |
---|---|---|
$GITHUB_PUBLIC_KEY_FINGERPRINT | 変更をプッシュしたユーザーの公開キー フィンガープリント | a1:b2:c3:d4:e5:f6:g7:h8:i9:j0:k1:l2:m3:n4:o5:p6 |
権限の設定と GitHub Enterprise Server への pre-receive フックのプッシュ
受信前フック スクリプトは、のリポジトリに含まれています。 サイト管理者はリポジトリの権限を考慮し、適切なユーザ� けがアクセスできるようにしなければなりません。
フックは単一のリポジトリに集約することをおすすめします。 集約されたフックのリポジトリがパブリックである� �合、README.md
を使用してポリシーの適用を説明できます。 また、コントリビューションをプルリクエスト経由で受け付けることもできます。 しかし、pre-receiveフックはデフォルトブランチからのみ追� できます。 テストのワークフロー用には、設定を持つリポジトリのフォークを使うべきです。
-
Mac ユーザは、スクリプトに実行権限を持たせてく� さい。
$ sudo chmod +x SCRIPT_FILE.sh
Windows ユーザは、スクリプトに実行権限を持たせてく� さい。
git update-index --chmod=+x SCRIPT_FILE.sh
-
上の受信前フック用の指定リポジトリにコミットしてプッシュします。
$ git commit -m "YOUR COMMIT MESSAGE" $ git push
-
GitHub Enterprise Server インスタンス上に受信前フックを作成します。
ローカルでのpre-receiveスクリプトのテスト
受信前フック スクリプトを 上で作成または更新する前に、ローカルでテストできます。 その方法の 1 つは、pre-receive フックを実行できるリモートリポジトリとして働くローカルの Docker 環境を作成することです。
-
ローカルに Docker がインストールされていることを確実にします。
-
次を含む
Dockerfile.dev
というファイルを作成します。FROM gliderlabs/alpine:3.3 RUN \ apk add --no-cache git openssh bash && \ ssh-keygen -A && \ sed -i "s/#AuthorizedKeysFile/AuthorizedKeysFile/g" /etc/ssh/sshd_config && \ adduser git -D -G root -h /home/git -s /bin/bash && \ passwd -d git && \ su git -c "mkdir /home/git/.ssh && \ ssh-keygen -t ed25519 -f /home/git/.ssh/id_ed25519 -P '' && \ mv /home/git/.ssh/id_ed25519.pub /home/git/.ssh/authorized_keys && \ mkdir /home/git/test.git && \ git --bare init /home/git/test.git" VOLUME ["/home/git/.ssh", "/home/git/test.git/hooks"] WORKDIR /home/git CMD ["/usr/sbin/sshd", "-D"]
-
always_reject.sh
という名前のテスト用の受信前スクリプトを作成します。 このスクリプト例では、全てのプッシュを拒否します。これは、リポジトリをロックする� �合に役立ちます。#!/usr/bin/env bash echo "error: rejecting all pushes" exit 1
-
always_reject.sh
スクリプトに実行アクセス許可があることを確認します。$ chmod +x always_reject.sh
-
Dockerfile.dev
を含むディレクトリで、イメージをビルドします。$ docker build -f Dockerfile.dev -t pre-receive.dev . > Sending build context to Docker daemon 3.584 kB > Step 1 : FROM gliderlabs/alpine:3.3 > ---> 8944964f99f4 > Step 2 : RUN apk add --no-cache git openssh bash && ssh-keygen -A && sed -i "s/#AuthorizedKeysFile/AuthorizedKeysFile/g" /etc/ssh/sshd_config && adduser git -D -G root -h /home/git -s /bin/bash && passwd -d git && su git -c "mkdir /home/git/.ssh && ssh-keygen -t ed25519 -f /home/git/.ssh/id_ed25519 -P ' && mv /home/git/.ssh/id_ed25519.pub /home/git/.ssh/authorized_keys && mkdir /home/git/test.git && git --bare init /home/git/test.git" > ---> Running in e9d79ab3b92c > fetch http://alpine.gliderlabs.com/alpine/v3.3/main/x86_64/APKINDEX.tar.gz > fetch http://alpine.gliderlabs.com/alpine/v3.3/community/x86_64/APKINDEX.tar.gz ....truncated output.... > OK: 34 MiB in 26 packages > ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519 > Password for git changed by root > Generating public/private ed25519 key pair. > Your identification has been saved in /home/git/.ssh/id_ed25519. > Your public key has been saved in /home/git/.ssh/id_ed25519.pub. ....truncated output.... > Initialized empty Git repository in /home/git/test.git/ > Successfully built dd8610c24f82
-
生成された SSH キーを含むデータコンテナを実行してく� さい。
$ docker run --name data pre-receive.dev /bin/true
-
テスト用の受信前フック
always_reject.sh
をデータ コンテナーにコピーします。$ docker cp always_reject.sh data:/home/git/test.git/hooks/pre-receive
-
sshd
を実行してフックを実行するアプリケーション コンテナーを実行します。 返されたコンテナ ID をメモしておいてく� さい:$ docker run -d -p 52311:22 --volumes-from data pre-receive.dev > 7f888bc700b8d23405dbcaf039e6c71d486793cad7d8ae4dd184f4a47000bc58
-
生成された SSH キーをデータコンテナからローカルマシンにコピーしてく� さい:
$ docker cp data:/home/git/.ssh/id_ed25519 .
-
テスト リポジトリのリモートを変更し、Docker コンテナー内の
test.git
リポジトリにプッシュします。 この例ではgit@github.com:octocat/Hello-World.git
を使用しますが、必要に応じてリポジトリを使用できます。 この例ではローカルマシン (127.0.0.1) がポート 52311 をバインドしているものとしていますが、docker がリモートマシンで動作しているなら異なる IP アドレスを使うことができます。$ git clone git@github.com:octocat/Hello-World.git $ cd Hello-World $ git remote add test git@127.0.0.1:test.git $ GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 52311 -i ../id_ed25519" git push -u test main > Warning: Permanently added '[192.168.99.100]:52311' (ECDSA) to the list of known hosts. > Counting objects: 7, done. > Delta compression using up to 4 threads. > Compressing objects: 100% (3/3), done. > Writing objects: 100% (7/7), 700 bytes | 0 bytes/s, done. > Total 7 (delta 0), reused 7 (delta 0) > remote: error: rejecting all pushes > To git@192.168.99.100:test.git > ! [remote rejected] main -> main (pre-receive hook declined) > error: failed to push some refs to 'git@192.168.99.100:test.git'
pre-receive フックの実行後にプッシュが拒否され、スクリプトからの出力がエコーされていることに注意してく� さい。
参考資料
- "Pro Git Web サイト" の「Git のカスタマイズ - Git-Enforced ポリシーの実施例」