Skip to main content

Pre-Receive-Hook-Skript erstellen

Mit pre-receive-Hook genannten Skripts kannst du Anforderungen zum Akzeptieren oder Ablehnen eines Push-Vorgangs anhand der Inhalte erstellen.

Beispiele für Pre-Receive-Hooks für GitHub Enterprise Server sind im Repository github/platform-samples enthalten.

Pre-Receive-Hook-Skript schreiben

Ein Pre-Receive-Hook-Skript wird in einer Pre-Receive-Hook-Umgebung auf Ihre GitHub Enterprise Server-Instance ausgeführt. Beachte beim Erstellen eines Pre-Receive-Hook-Skripts die verfügbaren Eingaben, Ausgaben, Beendigungsstatus und Umgebungsvariablen.

Eingabe (stdin)

Nach einem Push und vor der Aktualisierung von Verweisen (refs) für das Remoterepository ruft der Prozess git-receive-pack auf Ihre GitHub Enterprise Server-Instance das Pre-Receive-Hook-Skript auf. Die Standardeingabe für das Skript (stdin) ist eine Zeichenfolge mit einer Zeile für jeden zu aktualisierenden Verweis. Dabei enthält jede Zeile den alten Objektnamen, den neuen Objektnamen und den vollständigen Namen des Verweises.

<old-value> SP <new-value> SP <ref-name> LF

Diese Zeichenfolge stellt die folgenden Argumente dar.

ArgumentBESCHREIBUNG
<old-value>Der alte Objektname, der im Verweis gespeichert ist.
Wenn du einen neuen Verweis erstellst, umfasst der Wert 40 Nullen.
<new-value>Der neue Objektname, der im Verweis gespeichert werden soll.
Wenn du einen Verweis löschst, umfasst der Wert 40 Nullen.
<ref-name>Der vollständige Name des Verweises.

Weitere Informationen zu git-receive-pack findest du unter git-receive-pack in der Git-Dokumentation. Weitere Informationen zu Verweisen findest du unter Git-Verweise in Pro Git.

Ausgabe (stdout)

Die Standardausgabe für das Skript (stdout) wird an den Client zurückgegeben. Alle echo-Anweisungen sind für Benutzer*innen in der Befehlszeile oder auf der Benutzeroberfläche sichtbar.

Beendigungsstatus

Der Beendigungsstatus eines Pre-Receive-Skripts gibt an, ob der Push akzeptiert wird.

Wert des BeendigungsstatusAktion
0Der Push wird akzeptiert.
ungleich nullDer Push wird abgelehnt.

Umgebungsvariablen

Zusätzlich zur Standardeingabe für dein Pre-Receive-Hook-Skript (stdin) stellt GitHub Enterprise Server in der Bash-Umgebung die folgenden Variablen für die Ausführung deines Skripts zur Verfügung. Weitere Informationen zu stdin für dein Pre-Receive-Hook-Skript findest du unter Eingabe (stdin).

Abhängig davon, wodurch die Skriptausführung ausgelöst wird, sind unterschiedliche Umgebungsvariablen für dein Pre-Receive-Hook-Skript verfügbar.

Immer verfügbar

Die folgenden Variablen sind immer in der Pre-Receive-Hook-Umgebung verfügbar.

VariableBESCHREIBUNGBeispielwert
$GIT_DIR
Pfad zum Remoterepository der Instanz/data/user/repositories/a/ab/
a1/b2/34/100001234/1234.git
$GIT_PUSH_OPTION_COUNT
Die Anzahl von Pushoptionen, die vom Client mit --push-option gesendet wurden. Weitere Informationen findest du unter git-push in der Git-Dokumentation.1
$GIT_PUSH_OPTION_N
N entspricht hierbei einer ab 0 beginnenden Ganzzahl. Diese Variable enthält die Zeichenfolge der vom Client gesendeten Pushoption. Die erste gesendete Option wird in GIT_PUSH_OPTION_0, die zweite in GIT_PUSH_OPTION_1 gespeichert usw. Weitere Informationen zu Pushoptionen findest du unter git-push in der Git-Dokumentation.abcd
$GIT_USER_AGENT
Benutzer-Agent-Zeichenfolge, die vom Git-Client gesendet wurde, der die Änderungen gepusht hatgit/2.0.0
$GITHUB_REPO_NAME
Name des Repositorys, das aktualisiert wird, im Format NAME/BESITZERocto-org/hello-enterprise
$GITHUB_REPO_PUBLIC
Boolescher Wert, der angibt, ob das aktualisierte Repository öffentlich ist
  • true: Das Repository ist öffentlich
  • false: Das Repository ist privat oder intern
$GITHUB_USER_IP
Die IP-Adresse des Clients, der den Push initiiert hat192.0.2.1
$GITHUB_USER_LOGIN
Der Benutzername für das Konto, das den Push initiiert hatoctocat

Verfügbar für Pushvorgänge über die Weboberfläche oder die API

Die Variable $GITHUB_VIA ist in der Pre-Receive-Hook-Umgebung verfügbar, wenn die Verweisaktualisierung, die den Hook auslöst, über die Weboberfläche oder die API für GitHub Enterprise Server erfolgt. Der Wert beschreibt die Aktion, durch die der Verweis aktualisiert wurde.

WertAktionWeitere Informationen
auto-merge deployment api
Automatischer Merge des Basisbranches über eine Bereitstellung, die mit der API erstellt wurdeBereitstellungen in der REST-API-Dokumentation
blob#save
Ändern des Inhalts einer Datei über die WeboberflächeBearbeiten von Dateien
branch merge api
Zusammenführen eines Branches über die APIREST-API-Endpunkte für Branches und deren Einstellungen
branches page delete button
Löschen eines Branches über die WeboberflächeErstellen und Löschen von Branches in deinem Repository
git refs create api
Erstellen eines Verweises über die APIREST-API-Endpunkte für Git-Datenbank
git refs delete api
Löschen eines Verweises über die APIREST-API-Endpunkte für Git-Datenbank
git refs update api
Aktualisieren eines Verweises über die APIREST-API-Endpunkte für Git-Datenbank
git repo contents api
Ändern des Inhalts einer Datei über die APIRepositorys in der REST-API-Dokumentation
mergeZusammenführen eines Pull Requests über die Funktion für automatisches ZusammenführenAutomatisches Zusammenführen eines Pull Requests
merge base into head
Aktualisieren des Topic-Branches anhand des Basisbranches, wenn der Basisbranch strikte Statusüberprüfungen erfordert (z. B. über Branch aktualisieren in einem Pull Request)Informationen zu geschützten Branches
pull request branch delete button
Löschen eines Topic-Branches aus einem Pull Request auf der WeboberflächeBranches in einem Pull Request löschen und wiederherstellen
pull request branch undo button
Wiederherstellen eines Topic-Branches aus einem Pull Request auf der WeboberflächeBranches in einem Pull Request löschen und wiederherstellen
pull request merge api
Zusammenführen eines Pull Requests über die APIPulls in der REST-API-Dokumentation
pull request merge button
Zusammenführen eines Topic-Branches aus einem Pull Request auf der WeboberflächeEinen Pull Request zusammenführen
pull request revert button
Wiederherstellen eines Pull RequestsEinen Pull Request rückgängig machen
releases delete button
Löschen eines ReleaseVeröffentlichungen in einem Repository verwalten
stafftools branch restore
Wiederherstellung eines Branches auf dem Websiteadministratoren-DashboardVerwalten Ihrer Instanz über die Web-Benutzeroberfläche
tag create api
Erstellen eines Tags über die APIREST-API-Endpunkte für Git-Datenbank
slumlord (#SHA)
Committen über SubversionUnterstützung für Subversion-Clients
web branch create
Löschen eines Branches über die WebbenutzeroberflächeErstellen und Löschen von Branches in deinem Repository

Verfügbar für Pull Request-Merges

Die folgenden Variablen sind in der Pre-Receive-Hook-Umgebung verfügbar, wenn der Push, der den Hook auslöst, aufgrund der Zusammenführung eines Pull Requests ein Push ist.

VariableBESCHREIBUNGBeispielwert
$GITHUB_PULL_REQUEST_AUTHOR_LOGIN
Benutzername des Kontos, das den Pull Request erstellt hatoctocat
$GITHUB_PULL_REQUEST_HEAD
Der Name des PR-Topic-Branches im Format USERNAME:BRANCHoctocat:fix-bug
$GITHUB_PULL_REQUEST_BASE
Der Name des PR-Basisbranches im Format USERNAME:BRANCHoctocat:main

Verfügbar für Pushvorgänge unter Verwendung der SSH-Authentifizierung

VariableBESCHREIBUNGBeispielwert
$GITHUB_PUBLIC_KEY_FINGERPRINT
Der Fingerabdruck des öffentlichen Schlüssels für die oder den Benutzer*in, die bzw. der die Änderungen gepusht hata1:b2:c3:d4:e5:f6:g7:h8:i9:j0:k1:l2:m3:n4:o5:p6

Berechtigungen festlegen und einen Pre-Receive-Hook per Push-Vorgang an GitHub Enterprise Server übertragen

Ein Pre-Receive-Hook-Skript ist in einem Repository auf Ihre GitHub Enterprise Server-Instance enthalten. Ein Websiteadministrator muss die Repository-Berechtigungen beachten und sicherstellen, dass nur die richtigen Benutzer über Zugriff verfügen.

Es wird empfohlen, Hooks in einem einzelnen Repository zu konsolidieren. Wenn das konsolidierte Hook-Repository öffentlich ist, kann README.md verwendet werden, um Richtlinienerzwingungen zu erläutern. Darüber hinaus können Beiträge über Pull Requests akzeptiert werden. Pre-Receive-Hooks können jedoch nur auf dem Standardbranch hinzugefügt werden. Für einen Test-Workflow sollten Forks des Repositorys mit entsprechender Konfiguration verwendet werden.

  1. Stelle für Mac-Benutzer sicher, dass die Skripts über Ausführungsberechtigungen verfügen:

    sudo chmod +x SCRIPT_FILE.sh
    

    Stelle für Windows-Benutzer sicher, dass die Skripts über Ausführungsberechtigungen verfügen:

    git update-index --chmod=+x SCRIPT_FILE.sh
    
  2. Führe einen Commit und einen Push in das gewünschte Repository für Pre-Receive-Hooks auf Ihre GitHub Enterprise Server-Instance aus.

    git commit -m "YOUR COMMIT MESSAGE"
    git push
    
  3. Erstelle den Pre-Receive-Hook in der GitHub Enterprise Server-Instanz.

Pre-Receive-Skripts lokal testen

Du kannst ein Pre-Receive-Hook-Skript lokal testen, bevor du es in Ihre GitHub Enterprise Server-Instance erstellst oder aktualisierst. Eine Methode besteht darin, eine lokale Docker-Umgebung zu erstellen, die als ein Remote-Repository fungiert und als den Pre-Receive-Hook ausführen kann.

  1. Stelle sicher, dass Docker lokal installiert ist.

  2. Erstelle eine Datei mit dem Namen Dockerfile.dev, die Folgendes enthält:

    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. Erstelle ein Pre-Receive-Testskript mit dem Namen always_reject.sh. Dieses Beispielskript lehnt alle Push-Vorgänge ab, was zum Sperren eines Repositorys nützlich ist:

    #!/usr/bin/env bash
    
    echo "error: rejecting all pushes"
    exit 1
    
  4. Stelle sicher, dass das Skript always_reject.sh über Ausführungsberechtigungen verfügt:

    chmod +x always_reject.sh
    
  5. Erstelle in dem Verzeichnis, das Dockerfile.dev enthält, ein Image:

    $ 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. Führe einen Datencontainer aus, der einen generierten SSH-Schlüssel enthält:

    docker run --name data pre-receive.dev /bin/true
    
  7. Kopiere den Pre-Receive-Testhook always_reject.sh in den Datencontainer:

    docker cp always_reject.sh data:/home/git/test.git/hooks/pre-receive
    
  8. Führe einen Anwendungscontainer aus, der sshd und den Hook ausführt. Beachte die zurückgegebene Container-ID.

    $ docker run -d -p 52311:22 --volumes-from data pre-receive.dev
    > 7f888bc700b8d23405dbcaf039e6c71d486793cad7d8ae4dd184f4a47000bc58
    
  9. Kopiere den generierten SSH-Schlüssel aus dem Datencontainer auf den lokalen Computer:

    docker cp data:/home/git/.ssh/id_ed25519 .
    
  10. Ändere den Remotezugriff eines Testrepositorys, und führe einen Push in das Repository test.git innerhalb des Docker-Containers aus. In diesem Beispiel wird git@github.com:octocat/Hello-World.git verwendet, du kannst jedoch ein beliebiges Repository auswählen. In diesem Beispiel wird davon ausgegangen, dass dein lokaler Computer (127.0.0.1) Port 52311 bindet. Du kannst jedoch eine andere IP-Adresse verwenden, wenn Docker auf einem Remotecomputer ausgeführt wird.

    $ 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'
    

    Beachte, dass der Push abgelehnt wurde, nachdem du den Pre-Receive-Hook ausgeführt und die Ausgabe des Skripts wiedergegeben hast.

Weiterführende Themen