Skip to main content

Criar um script de hook pre-receive

Use os scripts de hooks pre-receive a fim de criar requisitos para aceitar ou rejeitar um push com base no conteúdo.

Veja exemplos de ganchos de pré-recebimento do GitHub Enterprise Server no repositório github/platform-samples.

Gravar um script de hook pre-receive

Um script de gancho de pré-recebimento é executado em um ambiente de gancho de pré-recebimento no sua instância do GitHub Enterprise Server. Ao criar um script de hook pre-receive, considere a entrada, saída, estado de saída e variáveis de ambiente disponíveis.

Entrada (stdin)

Após um push e antes da atualização de quaisquer referências no repositório remoto, o processo git-receive-pack no sua instância do GitHub Enterprise Server invoca o script do gancho de pré-recebimento. A entrada padrão para o script, stdin, é uma cadeia de caracteres que contém uma linha para cada referência a ser atualizada. Cada linha contém o nome antigo do objeto para ref, o novo nome do objeto para o ref e o nome completo do ref.

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

Essa frase representa os argumentos a seguir.

ArgumentoDescrição
<old-value>Nome do objeto antigo armazenado na referência.
Quando você cria uma referência, o valor é 40 zeros.
<new-value>Novo nome de objeto a ser armazenado na referência.
Quando você exclui uma referência, o valor é 40 zeros.
<ref-name>O nome completo da ref.

Para obter mais informações sobre git-receive-pack, confira "git-receive-pack" na documentação do Git. Para obter mais informações sobre as referências, confira "Referências do Git" em Pro Git.

Saída (stdout)

A saída padrão do script, stdout, é transmitida novamente para o cliente. As instruções echo ficarão visíveis para o usuário na linha de comando ou na interface do usuário.

Status da saída

O status de saída de um script pre-receive determina se o push será aceito.

Valor de status de saídaAção
0O push será aceito.
diferente de zeroO push será rejeitado.

Variáveis de ambiente

Além da entrada padrão para o script de gancho de pré-recebimento, stdin, o GitHub Enterprise Server disponibiliza as variáveis a seguir no ambiente do Bash para a execução do script. Para obter mais informações sobre o stdin do script de gancho de pré-recebimento, confira "Entrada (stdin)".

Diferentes variáveis de ambiente estão disponíveis para o seu script de hook pre-receive dependendo do que acionar o script.

Sempre disponível

As seguintes variáveis estão sempre disponíveis no ambiente de do hook pre-receive.

VariávelDescriçãoValor de exemplo
$GIT_DIR
Caminho para o repositório remoto na instância/data/user/repositories/a/ab/
a1/b2/34/100001234/1234.git
$GIT_PUSH_OPTION_COUNT
O número de opções de push enviadas pelo cliente com --push-option. Para obter mais informações, confira "git-push" na documentação do Git.1
$GIT_PUSH_OPTION_N
Quando N for um número inteiro que começa no 0, essa variável conterá a cadeia de caracteres da opção de push enviada pelo cliente. A primeira opção enviada é armazenada em GIT_PUSH_OPTION_0, a segunda opção enviada é armazenada em GIT_PUSH_OPTION_1 etc. Para obter mais informações sobre as opções de push, confira "git-push" na documentação do Git.abcd
$GIT_USER_AGENT
String de usuário-agente enviada pelo cliente Git que realizou push das alteraçõesgit/2.0.0
$GITHUB_REPO_NAME
Nome do repositório que está sendo atualizado no formato NOME/PROPRIETÁRIOocto-org/hello-enterprise
$GITHUB_REPO_PUBLIC
Booleano público, que representa se o repositório está sendo atualizado
  • true: A visibilidade do repositório é pública
  • false: A visibilidade do repositório é privada ou interna
$GITHUB_USER_IP
Endereço IP do cliente que iniciou o push192.0.2.1
$GITHUB_USER_LOGIN
Nome de usuário para a conta que iniciou o pushoctocat

Disponível para pushes a partir da interface web ou API

A variável $GITHUB_VIA ficará disponível no ambiente do gancho de pré-recebimento quando for feita a atualização de referência que dispara o gancho por meio da interface da Web ou da API do GitHub Enterprise Server. O valor descreve a ação que atualizou o ref.

ValorAçãoMais informações
auto-merge deployment api
Merge automático do branch base através de uma implantação criada com a API"Pontos de extremidade da API REST para implantações"
blob#save
Mudar para o conteúdo de um arquivo na interface web"Editando arquivos"
branch merge api
Merge de um branch através da API"Pontos de extremidade da API REST para ramificações e suas configurações"
branches page delete button
Exclusão de um branch na interface web"Criar e excluir branches no repositório"
git refs create api
Criação de um ref através da API"Pontos de extremidade da API REST para referências Git"
git refs delete api
Exclusão de uma ref através da API"Pontos de extremidade da API REST para referências Git"
git refs update api
Atualização de um ref através da API"Pontos de extremidade da API REST para referências Git"
git repo contents api
Mudança no conteúdo de um arquivo através da API"Pontos de extremidade da API REST para conteúdos de repositório"
mergeMesclagem de uma solicitação de pull com a mesclagem automática"Fazer merge automático de um pull request"
merge base into head
Atualização do branch do tópico partindo do branch base quando o branch base exige verificações de status rígidas (por meio de Atualizar branch em uma solicitação de pull, por exemplo)"Sobre branches protegidos"
pull request branch delete button
Exclusão de um branch do tópico de uma solicitação de pull na interface da Web"Excluir e restaurar branches em uma pull request"
pull request branch undo button
Restauração de um branch do tópico de uma solicitação de pull na interface da Web"Excluir e restaurar branches em uma pull request"
pull request merge api
Mesclagem de uma pull request por meio da API"Pontos de extremidade da API REST para pull requests"
pull request merge button
Mesclagem de uma solicitação de pull na interface da Web"Mesclar uma solicitação de pull"
pull request revert button
Reversão de uma solicitação de pull"Reverter uma pull request"
releases delete button
Exclusão de uma versão"Gerenciar versões em repositórios"
stafftools branch restore
Restauração de um branch do painel de administração do site"Administrar sua instância por meio da interface do usuário da Web"
tag create api
Criação de uma tag por meio da API"Pontos de extremidade da API REST para tags do Git"
slumlord (#SHA)
Commit por meio do Subversion"Suporte para clientes do Subversion"
web branch create
Criação de um branch por meio da interface da Web"Criar e excluir branches no repositório"

Disponível para merge de pull request

As variáveis a seguir estão disponíveis no ambiente de hook pre-receive quando o push que aciona o hook é um push devido ao merge de um pull request.

VariávelDescriçãoValor de exemplo
$GITHUB_PULL_REQUEST_AUTHOR_LOGIN
Nome de usuário da conta que criou o pull requestoctocat
$GITHUB_PULL_REQUEST_HEAD
O nome do branch do tópico da solicitação de pull, no formato USERNAME:BRANCHoctocat:fix-bug
$GITHUB_PULL_REQUEST_BASE
O nome do branch base da solicitação de pull, no formato USERNAME:BRANCHoctocat:main

Disponível para pushes que usam autenticação SSH

VariávelDescriçãoValor de exemplo
$GITHUB_PUBLIC_KEY_FINGERPRINT
A impressão digital da chave pública para o usuário que fez push das alteraçõesa1:b2:c3:d4:e5:f6:g7:h8:i9:j0:k1:l2:m3:n4:o5:p6

Configurar permissões e fazer push de um hook pre-receive para o GitHub Enterprise Server

Um script de gancho de pré-recebimento está contido em um repositório no sua instância do GitHub Enterprise Server. O administrador do site deve considerar as permissões do repositório e garantir que somente os usuários adequados tenham acesso.

Recomendamos consolidar os hooks em um único repositório. Se o repositório do gancho consolidado for público, o README.md poderá ser usado para explicar a imposição das políticas. Além disso, é possível aceitar contribuições via pull request. No entanto, os hooks pre-receive só podem ser adicionados pelo branch padrão. Em fluxos de trabalho de teste, devem ser usados forks do repositório com a devida configuração.

  1. Para usuários de Mac, certifique-se de que os scripts tenham estas permissões de execução:

    sudo chmod +x SCRIPT_FILE.sh
    

    Para usuários de Windows, certifique-se de que os scripts tenham estas permissões de execução:

    git update-index --chmod=+x SCRIPT_FILE.sh
    
  2. Confirme e envie por push ao repositório designado para ganchos de pré-recebimento no sua instância do GitHub Enterprise Server.

    git commit -m "YOUR COMMIT MESSAGE"
    git push
    
  3. Crie o gancho de pré-recebimento na instância do GitHub Enterprise Server.

Testar scripts pre-receive no local

É possível testar um script de gancho de pré-recebimento localmente antes de criá-lo ou atualizá-lo no sua instância do GitHub Enterprise Server. Uma forma de fazer isso é criar um ambiente Docker local para funcionar como repositório remoto que pode executar o hook pre-receive.

  1. Verifique se o Docker está instalado localmente.

  2. Crie um arquivo chamado Dockerfile.dev contendo:

    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. Crie um script de pré-recebimento de teste chamado always_reject.sh. Este exemplo de script rejeitará todos os pushes, o que é importante para bloquear um repositório:

    #!/usr/bin/env bash
    
    echo "error: rejecting all pushes"
    exit 1
    
  4. Verifique se os scripts always_reject.sh têm permissões de execução:

    chmod +x always_reject.sh
    
  5. No diretório que contém Dockerfile.dev, compile uma imagem:

    $ 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. Execute um contêiner de dados que contenha uma chave SSH gerada:

    docker run --name data pre-receive.dev /bin/true
    
  7. Copie o gancho de pré-recebimento de teste always_reject.sh para o contêiner de dados:

    docker cp always_reject.sh data:/home/git/test.git/hooks/pre-receive
    
  8. Execute um contêiner de aplicativo que executa sshd e executa o gancho. Anote o ID do contêiner:

    $ docker run -d -p 52311:22 --volumes-from data pre-receive.dev
    > 7f888bc700b8d23405dbcaf039e6c71d486793cad7d8ae4dd184f4a47000bc58
    
  9. Copie a chave SSH gerada do contêiner de dados para a máquina local:

    docker cp data:/home/git/.ssh/id_ed25519 .
    
  10. Modifique o repositório remoto de um repositório de teste e efetue push para o repositório test.git no contêiner do Docker. Este exemplo usa git@github.com:octocat/Hello-World.git, mas você poderá usar qualquer repositório que desejar. Este exemplo pressupõe que a sua máquina local (127.0.0.1) está vinculando a porta 52311, mas você pode usar outro endereço IP se o docker estiver sendo executado em uma máquina remota.

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

    Observe que o push foi rejeitado após a execução do hook pre-receive e o eco da saída do script.

Leitura adicional