# Realização de 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.

Você pode usar a API REST para implantar seus projetos hospedados em GitHub um servidor que você possui. Para obter mais informações sobre os pontos de extremidade usados para gerenciar as implantações e os status, confira [Pontos de extremidade da API REST para implantações](/pt/enterprise-server@3.22/rest/deployments). Use também a API REST para coordenar suas implantações no momento em que o código chega ao branch padrão. Para saber mais, confira [Criar um servidor de CI](/pt/enterprise-server@3.22/rest/guides/building-a-ci-server).

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

* 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 fruto da nossa imaginação. Eles podem ser o Heroku, o Amazon ou qualquer outro completamente diferente. O aspecto fundamental deste guia será configurar o servidor que gerencia a comunicação.

Caso ainda não tenha feito isso, [baixe o `ngrok`](https://ngrok.com/) e saiba como [usá-lo](https://ngrok.com/docs/getting-started/). Ele é uma ferramenta muito útil para expor aplicativos locais à Internet.

Observação: baixe o código-fonte completo deste projeto [no repositório platform-samples](https://github.com/github/platform-samples/tree/master/api/ruby/delivering-deployments).

## Escrever o seu servidor

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

```ruby
require 'sinatra'
require 'json'

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

(Se você não estiver familiarizado com o funcionamento do Sinatra, recomendamos [ler o guia do Sinatra](http://www.sinatrarb.com/)).

Inicie este servidor. Como o Sinatra é iniciado na porta `4567` por padrão, é recomendado configurar o `ngrok` para começar a ouvir nessa porta 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 onde você se sinta à vontade para experimentar. Podemos sugerir o repositório do Spoon/Knife de [@octocat](https://github.com/octocat/Spoon-Knife)?

Depois disso, você criará um webhook no repositório, alimentando-o com a URL que foi fornecida por `ngrok` e escolhendo `application/x-www-form-urlencoded` como o tipo de conteúdo.

Clique em **Atualizar webhook**. Você verá a resposta de corpo `Well, it worked!`.
Ótimo! Clique em **Deixe-me selecionar eventos individuais** e selecione o seguinte:

* Implantação
* Status da Implantação
* Solicitação de pull

Esses são os eventos GitHub que serão enviados ao nosso servidor sempre que a ação relevante ocorrer. Vamos configurar nosso servidor para *apenas* tratar as solicitações de pull quando elas forem mescladas agora:

```ruby
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! A deployment should start now..."
    end
  end
end
```

O que está havendo? Cada evento enviado por GitHub tem um cabeçalho HTTP `X-GitHub-Event` anexado. Por enquanto, nos importaremos apenas com os eventos do PR. Quando uma solicitação de pull for mesclada (o estado dela é `closed`, e `merged` é `true`), iniciaremos uma implantação.

Para testar esta prova de conceito, faça algumas alterações em um branch no repositório de teste, abra uma solicitação de pull e mescle-a. Seu servidor deve responder de acordo!

## Trabalhando com implantações

Com o servidor em funcionamento, o código em revisão e o pull request mesclado, nós queremos que nosso projeto seja implantado.

Vamos começar modificando o ouvinte de evento para processar as solicitações de pull quando elas forem mescladas e começar a prestar atenção às implantações:

```ruby
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 nas informações da solicitação de pull, começaremos preenchendo o método `start_deployment`:

```ruby
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 um `payload` e de uma `description`. Embora esses valores sejam opcionais, é útil usá-los para registrar em log e representar informações.

Quando uma nova implantação é criada, um evento completamente separado é acionado. É por isso que temos um novo caso `switch` no manipulador de eventos para `deployment`. Você pode usar essas informações para receber uma notificação de quando uma implantação é disparada.

As implantações podem levar bastante tempo. Portanto, vamos precisar monitorar vários eventos, como quando a implantação foi criada e em que estado ela se encontra.

Vamos simular uma implantação que executa uma tarefa e observar o efeito que ela tem no resultado. Primeiro, vamos concluir o método `process_deployment`:

```ruby
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 simular o armazenamento da informação de status como saída do console.

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

Vamos analisar o que está acontecendo. Uma nova implantação é criada por `start_deployment`, que dispara o evento `deployment`. A partir daí, chamamos `process_deployment` para simular o trabalho que está sendo feito. Durante esse processamento, também fazemos uma chamada a `create_deployment_status`, que permite que um destinatário saiba o que está acontecendo, à medida que alternamos o status para `pending`.

Após a conclusão da implantação, definimos o status como `success`.

## Conclusão

No GitHub, usamos uma versão do `Heaven` para gerenciar nossas implantações há anos. Um fluxo comum é essencialmente o mesmo que o servidor que criamos acima:

* Aguarde uma resposta sobre o estado das verificações de CI (sucesso ou falha)
* Se as verificações forem bem-sucedidas, mescle o pull request
* `Heaven` usa o código mesclado e o implanta em servidores de preparo e produção
* Entretanto, `Heaven` também notifica a todos sobre a compilação, por meio do [Hubot](https://github.com/github/hubot) presente em nossas salas de bate-papo.

É isso! Você não precisa criar sua própria configuração de implantação para usar este exemplo.
Você sempre pode contar com integrações [GitHub](https://github.com/integrations).