Como integrar Rocket.chat e Codeship
Tags: codeship, rocketchat, javascript, node
Published: 2020-10-06 15:37:43

Recentemente eu precisei configurar um CI para as nossas lambdas. Sempre fui acostumado a utilizar o Seed.run para essa função. Mas a empresa em que estou já possui uma conta no Codeship, e isso me veio como um desafio. Como utilizar o codeship para fazer o deploy de nossas lambdas? Isso foi até relativamente simples e esse post não é sobre isso.

Esse post está relacionado a outro problema. Minha empresa não utiliza o Slack e sim o Rocket.chat para a comunicação entre os desenvolvedores. O Rocket.chat é um projeto open source, que conta com mais de 1000 desenvolvedores que contribuem para o projeto. Se você chegou até aqui, é bem provável que você já conheça a plataforma. O problema então é, **como receber as notificações do Codeship no Rocket.chat de uma forma tão otimizada como acontece no Slack?**

Eu vou ser bem suscinto na explicação. Na verdade se você ler as documentações vai ver que não é algo complexo, mesmo assim eu perdi um bom tempo tentando fazer essas configurações e meu objetivo é economizar esse seu tempo.

## Rocket.chat
Você precisa ser administrador do Rocket para fazer a configuração a seguir.

Vá no painel de Administração (clique nos 3 pontinhos na coluna de comandos). Depois vá em **Webhooks ou Intregrações**. Se nada aparecer, clique novamente, depois clique em **Nova integração > Webhook Entrante**. Você verá a seguinte tela: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/x3js9j5baoptm34t5zbu.png)

Aqui algumas opções vão aparecer. A primeira opção é para ativar o webhook, já ative clicando em **Sim**. Preencha todos os campos que vão aparecer. Na opção Script ativado, deixe em **false** por enquanto e depois clique em **Salvar alterações**. O rocket chat tem um bug, ele só mostra a url do webhook depois que você clica em **Salvar alterações**, por isso, clique e logo em seguida, saia da aba integrações e depois volte novamente para aba integrações e encontre o webhook que você acabou de criar, ao clicar nele, você verá que dois novos campos foram adicionados, **Webhook URL e Token**. 

Copie a sugestão de Curl no campo abaixo de **Example** e faça essa requisição para verificar se seu webhook está funcionando. Se não funcionar, sugiro que revise os passos anteriores.

Copie a URL no campo **Webhook URL**. Vamos precisar dele para adicionar ao webhook do Codeship. 

 
## Codeship
No codeship, depois de logado, adicione o seu repositório git a lista de projetos no codeship. Eu não vou me ater a essa adição pois e bem simples. Depois de adicionado, clique no seu projeto e vá até **Project Settings > Notifications**.

É bem provável que nesse ponto, as notificações por email estejam ativadas, o que é bem chato, pois isso quer dizer que a cada deploy você receberá um email com o status do deploy, podendo receber até dois emails por deploy e por projeto. Mas esse é um side problem que nós vamos resolver de tabela, então já desative aí a opção de notificação por email.

Agora, clique em **+ Add**, algumas opções de integrações vão aparecer, se você usar o Slack, seus problemas terminam aqui, é extremamente simples integrar o Codeship com o Slack. Mas nesse ponto, escolha **Webhook** pois nós queremos integrar com o Rocket.chat. Os campos abaixo deverão ser preenchidos.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8q9hewd0wiejb6ecn8tu.png)

No campo **Webhook URL**, cole a URL que você copiou do Rocket.chat. Adicione no campo **Branch** a branch na qual você deseja receber as notificações. A configuração de notificação é por branch, logo, para cada branch você precisa configurar o webhook. Você pode usar o mesmo webhook do Rocket.chat para todas as branchs. Após configurar, clique em **Save**.

Se você ainda não tiver configurado o build do seu projeto no codeship, vá até a aba **Deploy** e clique em **Add Branch +**. Digite o mesmo nome da branch que você adicionou em notifications, daí escolha abaixo nos tipos de deploy o seu deploy preferido, ou **Script**. Daí, digite o comando de deploy. No meu caso é `yarn deploy:staging` pois estou configurando a branch de staging.

Ok, até aqui é extremamente simples. O problema começa exatamente aqui. Se nesse ponto você fizer um deploy da branch staging, você não receberá nenhuma notificação no Rocket.chat. Isto porque o Rocket.chat obriga que enviemos uma requisição POST para o webhook com um payload especifico e o payload que o codeship envia não é compatível. Veja abaixo a diferença:

### Payload esperado pelo Rocket.chat: 
```
{
  "username": "Codeship",
  "icon_url": "https://i.imgur.com/ErQ2qCT.png",
  "text": "Example message",
  "attachments": [
    {
      "title": "Rocket.Chat",
      "title_link": "https://rocket.chat",
      "text": "Rocket.Chat, the best open source chat",
      "image_url": "/images/integration-attachment-example.png",
      "color": "#764FA5"
    }
  ]
}
```

### Payload enviado pelo Codeship:
```
{
  "build": {
    "build_url":"https://www.codeship.com/projects/10213/builds/973711",
    "commit_url":"https://github.com/codeship/docs/
                  commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
    "project_id":10213,
    "build_id":973711,
    "status":"initiated",
    # PROJECT_FULL_NAME IS DEPRECATED AND WILL BE REMOVED IN THE FUTURE
    "project_full_name":"codeship/docs",
    "project_name":"codeship/docs",
    "commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
    "short_commit_id":"96943",
    "message":"Merge pull request #34 from codeship/feature/shallow-clone",
    "committer":"beanieboi",
    "branch":"master"
  }
}
```

É aí que entra o pulo do gato. Nas configurações do Webhook do Rocket.chat, nós temos um campo chamado Script. É nele que nós vamos trabalhar para deixar fazer as notificações funcionarem. Volte ao Rocket.chat, na aba integrações novamente, encontre o webhook que você adicionou e vá até o campo scripts. Aqui você pode escrever código Jasvascript até a versão ES6. Esse campo script é usado exatamente para fazer essas conversões de payloads recebidos pelo webhook. Adicione a esse campo o seguinte código: 
```
/* exported Script */
/* globals console, _, s */

class Script {
  /**
   * @params {object} request
   */
  process_incoming_request({ request }) {
    const build = request.content.build || {}

    const colorEnum = {
      initiated: '#3492eb',
      error: '#e03a02',
      success: '#29d911',
      stopped: '#e03a02',
      waiting: '#3492eb',
      ignored: '#5e615e',
      blocked: '#f7ec4d',
      infrastructure_failure: '#e03a02',
    }

    const content = {
      username: 'Codeship',
      attachments: [{
        color: colorEnum[build.status],
        fields: [
          {
            short: false,
            title: `Build ${build.status}`,
            value: build.message,
          },
          {
            short: true,
            title: 'Branch',
            value: build.branch,
          },
          {
            short: true,
            title: 'Project',
            value: build.project_name,
          },
          {
            short: false,
            title: 'Committer',
            value: build.committer,
          },
          {
            short: false,
            title: 'Commit',
            value: build.commit_url,
          },
          {
            short: false,
            title: 'Build URL',
            value: build.build_url,
          },
        ],
      }]
    }

    return {
      content
    };
  }
}
```
Quando você envia um payload para o webhook do Rocket.chat, esse payload chega dentro do objeto `request.content`. Perceba que o código acima simplesmente faz uma conversão do que foi enviado pelo Codeship para o payload esperado pelo Rocket.chat. E em `colorEnum` você pode configurar as cores da notificação, baseado no status do build. Esse payload foi formatado levando em conta o formato da intergação que existe entre o Slack e o Codeship.

Agora vá até o codeship, na lista de projetos, escolha o projeto que você configurou previamente e clique em **Restart Build**. E Voialááá!!! você receberá no seu Rocket.chat, no canal que você adicionou na configuração do Webhook a notificação de deploy, enviada pelo Codeship.

Caso tenha problemas, você pode testar fazendo uma requisição usando o seguinte Curl:

```
curl \
  -X POST \
  -H 'Content-Type: application/json' \
  --url <URL DO SEU WEBHOOK> \
  -d '{
    "build": {
      "build_url":"https://www.codeship.com/projects/10213/builds/973711",
      "commit_url":"https://github.com/codeship/docs/commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
      "project_id":10213,
      "build_id":973711,
      "status":"initiated",
      "project_full_name":"codeship/docs",
      "project_name":"codeship/docs",
      "commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
      "short_commit_id":"96943",
      "message":"Merge pull request #34 from codeship/feature/shallow-clone",
      "committer":"beanieboi",
      "branch":"master"
    }
  }'
```

Espero que a informação seja útil, qualquer adição, por favor informe nos comentários.

## Referências: 
- [Documentação do Rocket.chat sobre o webhook](https://docs.rocket.chat/guides/administrator-guides/integrations)
- [Documentação do Codeship sobre notificações](https://documentation.codeship.com/general/projects/notifications/)