Skip to main content

Enterprise Server 3.20 は、現在リリース候補として使用できます。

pre-receiveフックスクリプトの作成

pre-receiveフックのスクリプトを使って、プッシュの内容に基づいて受け入れまたは拒否するための条件を作成します。

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](https://git-scm.com/docs/git-receive-pack)」を参照してください。 参照の詳細については、[Pro Git](https://git-scm.com/book/en/v2/Git-Internals-Git-References) の「_Git References_」(Git の参照) を参照してください。

出力 (stdout)

スクリプトの標準出力 stdout はクライアントに返されます。 すべての echo ステートメントは、コマンド ラインまたはユーザー インターフェイスでユーザーに表示されます。

終了ステータス

受信前スクリプトの終了ステータスによって、プッシュが受け付けられるかどうかが決まります。

終了ステータスの値アクション
0プッシュは受け付けられます。
非ゼロプッシュは拒否されます。

環境変数

受信前フック スクリプトの標準入力 stdin に加え、GitHub Enterprise Server によって、スクリプトの実行のために次の変数が Bash 環境で使用できるようになります。 受信前フック スクリプトの stdin に関する詳細は、「入力 (stdin)」を参照してください。

受信前フック スクリプトで使用できる環境変数は、スクリプトが実行するトリガーに応じて異なります。

  •         [常に使用可能](#always-available)
    
  •         [Web インターフェイスまたは API からのプッシュで使用可能](#available-for-pushes-from-the-web-interface-or-api)
    
  •         [プルリクエストのマージに利用可能](#available-for-pull-request-merges)
    
  •         [SSH 認証を使用したプッシュで使用可能](#available-for-pushes-using-ssh-authentication)
    

常に使用可能

次の変数は、受信前フック環境で常に使用できます。

変数説明値の例
$GIT_DIR
インスタンス上のリモート リポジトリのパス/data/user/repositories/a/ab/
a1/b2/34/100001234/1234.git
$GIT_OBJECT_DIRECTORY
プッシュされるオブジェクトを含む一時ディレクトリへのパス/data/user/repositories/a/ab/
a1/b2/34/100001234/1234.git/
オブジェクト/ghq_luvYC864B9j
$GIT_QUARANTINE_PATH
          `$GIT_OBJECT_DIRECTORY` と同じ値が含まれます | /data/user/repositories/a/ab/<br>a1/b2/34/100001234/1234.git/<br>オブジェクト/ghq_luvYC864B9j |

|

$GIT_ALTERNATE_OBJECT_
DIRECTORIES
| インスタンス上にあるリポジトリのオブジェクト ディレクトリのパス | /data/user/repositories/a/ab/
a1/b2/34/100001234/1234.git/objects | |
$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
| 更新対象のリポジトリがパブリックかどうかを表すブール値 |
  • true: リポジトリの可視性がパブリック
  • false: リポジトリの可視性はプライベートまたは内部です
|
$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 を使用して作成されたデプロイを介したベース ブランチの自動マージ
          [AUTOTITLE](/rest/deployments#create-a-deployment) |

|

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 | 「自動マージ」を使用したプルリクエストの統合 | プルリクエストを自動的にマージする | |
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 のマージ | |
pull request revert button
| プルリクエストの取り消し | プルリクエストをリバートする | |
releases delete button
| リリースの削除 | リポジトリのリリースを管理する | |
stafftools branch restore
| サイト管理者ダッシュボードでのブランチの復元 | Web UI からインスタンスを管理する | |
tag create api
| API を使用したタグの作成 | Git タグ用 REST API エンドポイント | |
web branch create
| Web インターフェイスを使用したブランチの作成 | リポジトリ内でブランチを作成および削除する |

pull request のマージで使用可能

次の変数を受信前フック環境で使用できるのは、フックをトリガーするプッシュが pull request のマージによるプッシュであるときです。

変数説明値の例
$GITHUB_PULL_REQUEST_AUTHOR_LOGIN
pull request を作成したアカウントのユーザー名octocat
$GITHUB_PULL_REQUEST_HEAD
pull request のトピック ブランチの名前 (USERNAME:BRANCH 形式)
          <span style="white-space: nowrap;">octocat:fix-bug</span> |

|

$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フックはデフォルトブランチからのみ追加できます。 テストのワークフロー用には、設定を持つリポジトリのフォークを使うべきです。

  1. Mac ユーザは、スクリプトに実行権限を持たせてください。

    sudo chmod +x SCRIPT_FILE.sh
    

    Windowsユーザーの場合は、スクリプトに実行アクセス許可があることを確認します。

    git update-index --chmod=+x SCRIPT_FILE.sh
    
  2. お使いの GitHub Enterprise Server インスタンス上の受信前フック用の指定リポジトリにコミットしてプッシュします。

    git commit -m "YOUR COMMIT MESSAGE"
    git push
    
  3. GitHub Enterprise Server インスタンス上に受信前フックを作成します。

ローカルでのpre-receiveスクリプトのテスト

受信前フック スクリプトを お使いの GitHub Enterprise Server インスタンス上で作成または更新する前に、ローカルでテストできます。 その方法の 1 つは、pre-receive フックを実行できるリモートリポジトリとして働くローカルの Docker 環境を作成することです。

  1. ローカルに Docker がインストールされていることを確実にします

  2. 次を含む 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"]
    
  3.        `always_reject.sh` という名前のテスト用の受信前スクリプトを作成します。 このスクリプト例では、全てのプッシュを拒否します。これは、リポジトリをロックする場合に役立ちます。
    
    #!/usr/bin/env bash
    
    echo "error: rejecting all pushes"
    exit 1
    
  4.        `always_reject.sh` スクリプトに実行アクセス許可があることを確認します。
    
    chmod +x always_reject.sh
    
  5.        `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
    
  6. 生成された SSH キーを含むデータコンテナを実行してください。

    docker run --name data pre-receive.dev /bin/true
    
  7. テスト用の受信前フック always_reject.sh をデータ コンテナーにコピーします。

    docker cp always_reject.sh data:/home/git/test.git/hooks/pre-receive
    
  8.        `sshd` を実行してフックを実行するアプリケーション コンテナーを実行します。 返されたコンテナ ID をメモしておいてください:
    
    $ docker run -d -p 52311:22 --volumes-from data pre-receive.dev
    > 7f888bc700b8d23405dbcaf039e6c71d486793cad7d8ae4dd184f4a47000bc58
    
  9. 生成された SSH キーをデータコンテナからローカルマシンにコピーしてください:

    docker cp data:/home/git/.ssh/id_ed25519 .
    
  10. テスト リポジトリのリモートを変更し、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 ウェブサイト」の「Git のカスタマイズ - Git によるポリシー実施の例」