GitHub Enterprise Server の受信前フックの例を github/platform-samples
リポジトリで参照できます。
pre-receiveフックスクリプトの作成
受信前フック スクリプトは、お使いの GitHub Enterprise Server インスタンス 上の受信前フック スクリプト環境で実行されます。 受信前フック スクリプトを作成する際には、利用可能な入力、出力、終了ステータス、環境変数について考慮します。
入力 (stdin
)
プッシュが発生した後で、リモート リポジトリに関して参照が更新される前に、お使いの GitHub Enterprise Server インスタンス上の 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 を使用した参照の作成 | 「Git リファレンス用 REST API エンドポイント」 |
git refs delete api | API を使用した参照の削除 | 「Git リファレンス用 REST API エンドポイント」 |
git refs update api | API を使用した参照の更新 | 「Git リファレンス用 REST API エンドポイント」 |
git repo contents api | API を使用したファイルの内容に対する変更 | 「リポジトリ コンテンツの REST API エンドポイント」 |
merge | 自動マージを使用した pull request のマージ | 「プルリクエストを自動的にマージする」 |
merge base into head | ベース ブランチで厳密な状態チェックが必要になる際のベース ブランチのトピック ブランチの更新 (たとえば、pull request で [ブランチを更新] を使用) | 「保護されたブランチについて」 |
pull request branch delete button | Web インターフェイスでの pull request からのトピック ブランチの削除 | 「プルリクエスト中のブランチの削除と復元」 |
pull request branch undo button | Web インターフェイスでの pull request からのトピック ブランチの復元 | 「プルリクエスト中のブランチの削除と復元」 |
pull request merge api | API を使用した pull request の統合 | 「Pull request 用 REST API エンドポイント」 |
pull request merge button | Web インターフェイスでの pull request のマージ | 「プル要求のマージ」 |
pull request revert button | pull request を元に戻す | 「Pull Request を打ち消す」 |
releases delete button | リリースの削除 | 「リポジトリのリリースを管理する」 |
stafftools branch restore | サイト管理者ダッシュボードでのブランチの復元 | 「Web UI からインスタンスを管理する」 |
tag create api | API を使用したタグの作成 | 「Git タグ用 REST API エンドポイント」 |
slumlord (#SHA) | Subversion を使用したコミット | 「Subversion クライアントのサポート」 |
web branch create | Web インターフェイスを使用したブランチの作成 | 「リポジトリ内でブランチを作成および削除する」 |
pull request のマージで使用可能
次の変数を受信前フック環境で使用できるのは、フックをトリガーするプッシュが pull request のマージによるプッシュであるときです。
変数 | 説明 | 値の例 |
---|---|---|
$GITHUB_PULL_REQUEST_AUTHOR_LOGIN | pull request を作成したアカウントのユーザー名 | octocat |
$GITHUB_PULL_REQUEST_HEAD | pull request のトピック ブランチの名前 (USERNAME:BRANCH 形式) | octocat:fix-bug |
$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 フックのプッシュ
受信前フック スクリプトは、お使いの GitHub Enterprise Server インスタンス のリポジトリに含まれています。 サイト管理者はリポジトリの権限を考慮し、適切なユーザだけがアクセスできるようにしなければなりません。
フックは単一のリポジトリに集約することをおすすめします。 集約されたフックのリポジトリがパブリックである場合、README.md
を使用してポリシーの適用を説明できます。 また、コントリビューションをプルリクエスト経由で受け付けることもできます。 しかし、pre-receiveフックはデフォルトブランチからのみ追加できます。 テストのワークフロー用には、設定を持つリポジトリのフォークを使うべきです。
-
Mac ユーザは、スクリプトに実行権限を持たせてください。
sudo chmod +x SCRIPT_FILE.sh
Windows ユーザは、スクリプトに実行権限を持たせてください。
git update-index --chmod=+x SCRIPT_FILE.sh
-
お使いの GitHub Enterprise Server インスタンス上の受信前フック用の指定リポジトリにコミットしてプッシュします。
git commit -m "YOUR COMMIT MESSAGE" git push
-
GitHub Enterprise Server インスタンス上に受信前フックを作成します。
ローカルでのpre-receiveスクリプトのテスト
受信前フック スクリプトを お使いの GitHub Enterprise Server インスタンス上で作成または更新する前に、ローカルでテストできます。 その方法の 1 つは、pre-receive フックを実行できるリモートリポジトリとして働くローカルの Docker 環境を作成することです。
-
ローカルに Docker がインストールされていることを確実にします。
-
次を含む
Dockerfile.dev
というファイルを作成します。FROM alpine:latest 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 . [+] Building 4.5s (8/8) FINISHED => [internal] load build definition from Dockerfile.dev 0.0s => => transferring dockerfile: 641B 0.0s => [internal] load .dockerignore 0.0s => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 1.9s => [auth] library/alpine:pull token for registry-1.docker.io 0.0s => [1/3] FROM docker.io/library/alpine:latest@sha256:82d1e9d7ed48a7523bdebc18cf6290bdb97b82302a8a9c27d4fe885949ea94d1 0.0s => => resolve docker.io/library/alpine:latest@sha256:82d1e9d7ed48a7523bdebc18cf6290bdb97b82302a8a9c27d4fe885949ea94d1 0.0s => => sha256:82d1e9d7ed48a7523bdebc18cf6290bdb97b82302a8a9c27d4fe885949ea94d1 1.64kB / 1.64kB 0.0s => => sha256:25fad2a32ad1f6f510e528448ae1ec69a28ef81916a004d3629874104f8a7f70 528B / 528B 0.0s => => sha256:c1aabb73d2339c5ebaa3681de2e9d9c18d57485045a4e311d9f8004bec208d67 1.47kB / 1.47kB 0.0s => [2/3] RUN apk add --no-cache git openssh bash && ssh-keygen -A && sed -i "s/#AuthorizedKeysFile/AuthorizedKeysFile/g" /e 2.3s => [3/3] WORKDIR /home/git 0.0s => exporting to image 0.1s => => exporting layers 0.1s => => writing image sha256:938447846e19a4328a85883fbd1ccf5eb919d97448cc7256efebf403d8b5a196 0.0s => => naming to docker.io/library/pre-receive.dev
-
生成された 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 master > Warning: Permanently added '[127.0.0.1]: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@127.0.0.1:test.git > ! [remote rejected] master -> master (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 ポリシーの実施例」