Git サーバーフック

Gitサーバーフック(システムフックや ファイルフックと混同しないでください)はGitLabサーバー上でカスタムロジックを実行します。以下のようなGit関連のタスクを実行するために使うことができます:

  • 特定のコミットポリシーの強制
  • リポジトリの状態に基づいたタスクの実行。

Git サーバーフックは、pre-receivepost-receiveupdate Git サーバーサイドフックを使います。

GitLab管理者は、GitLabサーバーのファイルシステム上でサーバーフックを設定します。ファイルシステムにアクセスできない場合は、サーバーフックの代わりに次のような方法があります:

Geoはサーバーフックをセカンダリノードに複製しません。

リポジトリのサーバーフックの設定

GitLab 15.11 and later

GitLab 15.11で導入されたhooks set ファイルシステムへの直接アクセスを置き換えるコマンド hooks setです。hooks set 既存の Git フックをマイグレーションする必要は hooks setありません。

前提条件:

リポジトリにサーバーフックを設定するには

  1. カスタムフックを含む tarball を作成します:
    1. サーバーフックが期待通りに機能するようにコードを書きます。Git サーバーフックはどんなプログラミング言語でも使えます。先頭のshebangが言語の種類を反映していることを確認しましょう。たとえば、スクリプトが Ruby であれば shebang はおそらく#!/usr/bin/env ruby となるでしょう。

      • 一つのサーバフックを作成するには、フックの種類に合った名前のファイルを作成します。例えば、pre-receive サーバーフックの場合、ファイル名は pre-receive拡張子のないものにします。
      • 多くのサーバフックを作成するには、フックの種類に合ったフック用のディレクトリを作成します。例えば、pre-receive サーバフックの場合、ディレクトリ名はpre-receive.d とします。そのディレクトリにフック用のファイルを置きます。
    2. サーバーフックファイルが実行可能で、バックアップファイルのパターン (*~) と一致しないことを確認してください。サーバーフックは tarball のルートにあるcustom_hooks ディレクトリに置きます。
    3. tarコマンドでカスタムフックアーカイブを作成します。例えば、tar -cf custom_hooks.tar custom_hooks
  2. hooks set サブコマンドを必要なオプションをつけて実行し、リポジトリの Git フックを設定します。たとえば、cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>

    • ノードに接続し、--config フラグに提供するためには、ノードの有効な Gitaly 設定へのパスが必要です。
    • カスタムフックのtarballは、stdin 。例えば、cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>.
  3. Gitaly Clusterを使用している場合、すべてのGitalyノードでhooks set サブコマンドを実行する必要があります。詳しくは、Gitaly Cluster上のサーバ・フックをご覧ください。

サーバーフックのコードが正しく実装されていれば、Gitフックが次にトリガーされたときに実行されるはずです。

GitLab 15.10 and earlier

リポジトリ用のサーバーフックを作成するには

  1. 左のサイドバーで、Search を選択するか、次のページに進んでください。
  2. Admin Areaを選択します。
  3. 概要 > プロジェクト]に進み、サーバーフックを追加したいプロジェクトを選択します。
  4. 表示されたページで、相対パスの値を確認します。このパスは、サーバーフックを配置する場所です。
  5. ファイルシステム上で、正しい場所にcustom_hooks という新しいディレクトリを作成します。
  6. 新しいcustom_hooks ディレクトリに:
    • 一つのサーバフックを作成するには、フックの種類に合った名前のファイルを作成します。例えば、pre-receive サーバーフックの場合、ファイル名は pre-receive拡張子のないものにします。
    • 多くのサーバーフックを作成するには、フックの種類に合ったフック用のディレクトリを作成します。例えば、pre-receive サーバフックの場合、ディレクトリ名はpre-receive.d とします。そのディレクトリにフック用のファイルを置きます。
  7. サーバーフックのファイルを実行可能なものにし、Gitユーザーがそのファイルを所有するようにします。
  8. サーバーフックが期待通りに機能するようにコードを書きます。Git のサーバーフックは、どんなプログラミング言語でも使うことができます。先頭のshebangが言語の種類を反映していることを確認しましょう。たとえば、スクリプトが Ruby であれば shebang はおそらく#!/usr/bin/env ruby となるでしょう。
  9. フックファイルがバックアップファイルのパターン (*~) と一致しないことを確認します。
  10. Gitaly Clusterを使用している場合、すべてのGitalyノードでこのプロセスを繰り返す必要があります。詳しくは、Gitaly Cluster上のサーバ・フックをご覧ください。

サーバーフックのコードが適切に実装されていれば、Gitフックが次にトリガーされたときに実行されるはずです。

Gitalyクラスタでのサーバーフック

Gitaly Clusterを使用すると、個々のリポジトリがPraefectの複数のGitalyストレージに複製されることがあります。その結果、リポジトリのレプリカを持つすべての Gitaly ノードにフックスクリプトをコピーする必要があります。このためには、該当するバージョンのカスタムリポジトリフックを設定する手順と同じ手順を、各ストレージについて繰り返します。

スクリプトをコピーする場所は、リポジトリが保存されている場所に依存します:

すべてのリポジトリ用にグローバルサーバーフックを作成します。

すべてのリポジトリに適用される Git フックを作成するには、グローバルサーバーフックを設定します。グローバルサーバーフックは、次のような場合にも適用されます:

サーバーフックディレクトリの選択

グローバルサーバーフックを作成する前に、そのディレクトリを選択する必要があります。

Linux パッケージインストールの場合、ディレクトリはgitaly['configuration'][:hooks][:custom_hooks_dir] の下のgitlab.rb に設定されます。以下のいずれかを実行します:

  • /var/opt/gitlab/gitaly/custom_hooks ディレクトリをアンコメントして、デフォルトの提案を使用します。
  • 独自の設定を追加してください。

セルフコンパイルによるインストールの場合:

  • ディレクトリは設定ファイルで設定します。設定ファイルの場所はGitLabのバージョンによって異なります:
    • GitLab 13.1以降では、ディレクトリは[hooks] セクションの下のgitaly/config.toml 。ただし、gitaly/config.toml の値が空白か存在しない場合、GitLab はgitlab-shell/config.ymlcustom_hooks_dir の値を尊重します。
    • GitLab 13.0以前では、gitlab-shell/config.yml に設定されたディレクトリが優先されます。
  • デフォルトのディレクトリは/home/git/gitlab-shell/hooks です。

グローバルサーバーフックの作成

すべてのリポジトリ用のグローバルサーバフックを作成します:

  1. GitLabサーバーで、設定されたグローバルサーバーフックディレクトリに移動します。
  2. 設定されたグローバルサーバーフックディレクトリに、フックの種類に合ったフック用のディレクトリを作成します。例えば、pre-receive サーバフックの場合、ディレクトリ名はpre-receive.d とします。
  3. この新しいディレクトリの中に、サーバーフックを追加します。Git サーバーフックは、どのプログラミング言語でもかまいません。先頭のshebangが言語の種類を反映していることを確認しましょう。たとえば、スクリプトが Ruby であれば shebang はおそらく#!/usr/bin/env ruby となるでしょう。
  4. フックファイルを実行可能なものにし、Gitユーザーの所有物にし、バックアップファイルのパターン (*~) にマッチしないようにします。

サーバーフックのコードが適切に実装されていれば、次に Git フックが起動したときに実行されるはずです。フックは、フックタイプのサブディレクトリでファイル名のアルファベット順に実行されます。

リポジトリのサーバーフックの削除

GitLab 15.11 and later

GitLab 15.11 で導入された hooks set コマンドは、ファイルシステムへの直接アクセスを置き換えます。

前提条件:

サーバーフックを削除するには、hook set に空の tarball を渡して、リポジトリにフックが含まれていないことを示します。例えば

cat empty_hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>`.
GitLab 15.10 and earlier

サーバーフックを削除するには

  1. ディスク上のリポジトリの場所に移動します。
  2. custom_hooks ディレクトリのサーバーフックを削除します。

連鎖したサーバーフック

GitLabはサーバーフックをチェーンして実行することができます。GitLabは以下の順序でサーバーフックを検索し、実行します:

  • 組み込みのGitLabサーバーフック。これらのサーバーフックはユーザーがカスタマイズすることはできません。
  • <project>.git/custom_hooks/<hook_name>:プロジェクトごとのフック。この場所は後方互換性のために残されています。
  • <project>.git/custom_hooks/<hook_name>.d/*:プロジェクトごとのフックの場所。
  • <custom_hooks_dir>/<hook_name>.d/*:エディタのバックアップファイルを除く、実行可能なすべてのグローバルフックファイルの場所。

サーバーフックディレクトリ内では、hooks:

  • アルファベット順に実行されます。
  • フックがゼロ以外の値で終了すると実行を停止します。

サーバーフックで使用可能な環境変数

サーバーフックにはどのような環境変数でも渡すことができますが、サポートされている環境変数にのみ依存するようにしてください。

以下の GitLab 環境変数がすべてのサーバーフックでサポートされています:

環境変数説明
GL_IDプッシュを開始したユーザーまたは SSH キーの GitLab 識別子。例えば、user-2234 またはkey-4
GL_PROJECT_PATH(GitLab 13.2 以降) GitLab プロジェクトのパス。
GL_PROTOCOL(GitLab 13.2 以降) 変更に使用するプロトコル。http (Gitpush using HTTP)、ssh (Gitpush using SSH)、web (all other actions) のいずれか。
GL_REPOSITORY project-<id> id はプロジェクトのIDです。
GL_USERNAMEプッシュを開始したユーザーの GitLab ユーザー名。

pre-receivepost-receive サーバーフックでは、以下の Git 環境変数がサポートされています:

環境変数説明
GIT_ALTERNATE_OBJECT_DIRECTORIES隔離環境の代替オブジェクトディレクトリ。Gitreceive-pack ドキュメントを参照してください。
GIT_OBJECT_DIRECTORY隔離環境の GitLab プロジェクトパス。Gitreceive-pack ドキュメントを参照してください。
GIT_PUSH_OPTION_COUNT プッシュオプションの数。Gitpre-receive ドキュメントを参照してください。
GIT_PUSH_OPTION_<i> プッシュオプションの値。i0 からGIT_PUSH_OPTION_COUNT - 1 まで。Gitpre-receive ドキュメントを参照。

カスタムエラーメッセージ

コミットが拒否されたときやGitフック中にエラーが発生したときに、GitLab UIにカスタムエラーメッセージを表示させることができます。カスタムエラーメッセージを表示するには、スクリプトに以下の設定が必要です:

  • カスタムエラーメッセージをスクリプトのstdout またはstderr に送信します。
  • 各メッセージのプレフィックスはGL-HOOK-ERR: とし、プレフィックスの前には文字を付けないでください。

使用例:

#!/bin/sh
echo "GL-HOOK-ERR: My custom error message.";
exit 1