Esta versão do GitHub Enterprise foi descontinuada em 2021-09-23. Nenhum lançamento de patch será feito, mesmo para questões críticas de segurança. Para obter melhor desempenho, melhorar a segurança e novos recursos, upgrade to the latest version of GitHub Enterprise. Para ajuda com a atualização, contact GitHub Enterprise support.

Entregar implantações

Ao usar a API RESt de implantações, você pode criar ferramentas personalizadas que interagem com seu servidor e um aplicativo de terceiros.

A API de Implantações fornece seus projetos hospedados em GitHub Enterprise Server com a capacidade de lançá-los em um servidor do qual você é proprietário. Combinado com a API de Status, você será capaz de coordenar suas implantações no momento em que seu código chegar ao branch-padrão.

Este guia usará a API para demonstrar uma configuração que você pode usar. No nosso cenário, iremos:

  • Fazer merge de um pull request
  • Quando a CI terminar, definiremos o status do pull request.
  • Quando o pull request for mesclado, executaremos a nossa implantação no nosso servidor.

O nosso sistema de CI e servidor de hospedagem serão imaginários. Eles podem ser Heroku, Amazon, ou qualquer outra coisa completamente diferente. O principal deste guia será criar e configurar o servidor de gerenciamento da comunicação.

Se você ainda não tiver, certifique-se de fazer o download do ngrok e aprender como usá-lo. Nós achamos que é uma ferramenta muito útil para expor conexões locais.

Observação: você pode baixar o código-fonte completo para este projeto no repositório de amostra de plataforma.

Escrever o seu servidor

Vamos escrever um aplicativo rápido do Sinatra para provar que nossas conexões locais estão funcionando. Vamos começar com isso:

require 'sinatra'
require 'json'

post '/event_handler' do
  payload = JSON.parse(params[:payload])
  "Well, it worked!"
end

(Se você não estiver familiarizado com a forma como Sinatra funciona, recomendamos a leitura do guia do Sinatra.)

Inicie este servidor. Por padrão, o Sinatra começa na porta 4567. Portanto, você deverá configurar o ngrok para começar a ouvir isso também.

Para que esse servidor funcione, precisamos configurar um repositório com um webhook. O webhook deve ser configurado para ser acionado sempre que um pull request for criado ou mesclado. Vá em frente e crie um repositório com o qual você esteja confortável para fazer testes. Podemos sugerir @octocat's Spoon/Knife repository? Em seguida, você criará um novo webhook no seu repositório, alimentando-o com a URL que o ngrok forneceu a você e escolhendo application/x-www-form-urlencoded como o tipo de conteúdo:

Uma nova URL do ngrok

Clique em Update webhook (Atualizar webhook). Você deve ver uma resposta de texto de Well, it worked!. Ótimo! Clique em Permita-me selecionar eventos individuais e selecione o seguinte:

  • Implantação
  • Status da implantação
  • Pull Request

Esses são os eventos que GitHub Enterprise Server serão enviados ao nosso servidor sempre que ocorrer a ação relevante. Vamos configurar nosso servidor para o manipular apenas quando pull requests forem mesclados neste momento:

post '/event_handler' do
  @payload = JSON.parse(params[:payload])

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
      puts "A pull request was merged! Uma implantação deve começar agora..."
    end
  end
end

O que está acontecendo? Cada evento que GitHub Enterprise Server envia, anexa um cabeçalho de HTTP de X-GitHub-Event. Por enquanto, nos importaremos apenas com os eventos do PR. Quando um pull request é mesclado (seu estado é fechado e mesclado é verdadeiro), vamos iniciar uma implantação.

Para testar esta validação de conceito, faça algumas alterações em um branch no repositório de testes, abra um pull request e faça o merge. Seu servidor deve responder de acordo!

Trabalhando com implantações

Como já temos o servidor configurado, o código que está sendo revisado e nosso pull request mesclado, queremos que nosso projeto seja implantado.

Vamos começar modificando nosso detector de evento para processar pull requests quando tiverem feito merge e começar a prestar atenção às implantações:

when "pull_request"
  if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
    start_deployment(@payload["pull_request"])
  end
when "deployment"
  process_deployment(@payload)
when "deployment_status"
  update_deployment_status
end

Com base na informação de uma solicitação, começaremos preenchendo o método start_deployment:

def start_deployment(pull_request)
  user = pull_request['user']['login']
  payload = JSON.generate(:environment => 'production', :deploy_user => user)
  @client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end

As implantações podem ter alguns metadados anexados, na forma de carga e descrição. Embora esses valores sejam opcionais, é útil usar para registrar e representar informações.

Quando uma nova implantação é criada, um evento completamente separado é acionado. É por isso que temos um novo caso de switch no manipulador de eventos para implantação. Você pode usar esta informação para ser notificado quando uma implantação for acionada.

As implantações podem demorar um pouco. Portanto, nós vamos precisar ouvir vários eventos, como quando a implantação foi criada e em que estado se encontra.

Vamos simular uma implantação realize um trabalho e notar o efeito que ela tem na saída. Primeiro, vamos completar nosso método process_deploy:

def process_deployment
  payload = JSON.parse(@payload['payload'])
  # you can send this information to your chat room, monitor, pager, etc.
  puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')
end

Por fim, vamos fazer a simulação do armazenamento da informação de status como a saída do console:

def update_deployment_status
  puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end

Vamos dividir o que está acontecendo. Uma nova implantação é criada por start_deployment, que aciona o evento implantação. A partir daí, chamamos process_deployment para simular o trabalho que está ocorrendo. Durante esse processamento, também fazemos uma chamada para create_deployment_status, que permite que um destinatário saiba o que está acontecendo, pois nós alteramos o status para pendente.

Após a conclusão da implantação, definimos o status para sucesso.

Conclusão

No GitHub, usamos uma versão do Heavan para gerenciar nossas implantações por anos. A common flow is essentially the same as the server we've built above:

  • Wait for a response on the state of the CI checks (success or failure)
  • If the required checks succeed, merge the pull request
  • Heaven takes the merged code, and deploys it to staging and production servers
  • Enquanto isso, o Heaven também notifica todos sobre a criação por meio do Hubot que aguarda nas nossas salas de bate-papo

Pronto! Você não precisa criar sua própria configuração de implantação para usar este exemplo. Você sempre pode confiar nas Integrações do GitHub.