https://a.storyblok.com/f/270183/84184/63362c97bb/e_gitlab-ci-pipeline_1200x600.jpg

Envio de notificações do pipeline do GitLab CI com o Nexmo Messages

Publicado em May 7, 2021

Tempo de leitura: 6 minutos

Tenho meu próprio blog, The Polyglot Developer, que publica como parte de um pipeline de integração contínua e implantação contínua. Basicamente, a seguinte sequência de eventos ocorre toda vez que uma git push é concluída:

  1. O site estático é enviado para o GitLab

  2. O processo de compilação do pipeline é iniciado

  3. O processo de implantação do pipeline é iniciado

  4. O site estático foi publicado e está pronto para ser acessado

Em mais situações do que eu gostaria de admitir, o processo falha porque ou minha compilação deu errado ou a implantação falhou. O problema é que muitas vezes eu nem percebo que essas falhas ocorrem, o que às vezes me obriga a refazer todo o trabalho.

Vamos ver como melhorar o processo de CI/CD incluindo notificações por SMS, com tecnologia da Nexmo, em caso de falha.

Entendendo a configuração e o processo do GitLab CI

Caso você não esteja familiarizado com o GitLab, é possível utilizar os serviços de CI deles incluindo um arquivo arquivo .gitlab-ci.yml na raiz do seu projeto Git. Esse arquivo pode ter uma aparência semelhante a esta:

image: "node:alpine"

stages:
  - build
  - deploy

build:
  stage: build
  script: 
    - npm install
    - npx gulp build
    artifacts:
      paths:
        - dist

deploy:
  stage: deploy
  script:
    - npm install
    - npx gulp deploy

A configuração acima é fictícia, mas segue o formato correto de um arquivo .gitlab-ci.yml . No cenário acima, há um build etapa que executa a build tarefa gulp e um deploy etapa que executa a deploy tarefa gulp.

Se alguma das duas etapas falhar, o que acontece?

Com o GitLab CI, você pode definir quando determinadas etapas serão executadas, o que significa que é possível configurar uma etapa para ser executada quando ocorrer uma falha. Com isso em mente, poderíamos atualizar nosso .gitlab-ci.yml para que fique mais ou menos assim:

image: "node:alpine"

stages:
  - build
  - deploy
  - failure

build:
  stage: build
  script: 
    - npm install
    - npx gulp build
    artifacts:
      paths:
        - dist

deploy:
  stage: deploy
  script:
    - npm install
    - npx gulp deploy

failure:
  stage: failure
  script:
    - echo "failure"
  when: on_failure

A informação importante é a when propriedade que existe na failure palco.

Então, agora que sabemos como criar uma configuração do GitLab CI, como podemos aproveitar isso para sermos notificados sempre que houver uma falha no pipeline?

É aí que a Nexmo e o serviço de SMS se mostram valiosos.

Como usar a SMS API da Nexmo

Quando nosso pipeline falhar, podemos utilizar o serviço de SMS da Nexmo para receber uma mensagem de texto que pode incluir informações sobre o pipeline, informações sobre o commit ou, na verdade, qualquer coisa que possa ser útil para nós ou para a equipe responsável pelo projeto.

Para usar a SMS API da Nexmo, você precisará de um Account. Na seção seção “Configurações” da sua conta de usuário, anote a chave da API e o segredo da API.

SettingsSettings

As informações da API serão necessárias para o envio automático de mensagens SMS.

Se realmente quiséssemos — o que não devemos fazer —, poderíamos criar uma instrução cURL, codificar manualmente todas as nossas informações de API e números de telefone e adicioná-la diretamente à configuração do GitLab CI. Poderíamos, mas não devemos. Em vez disso, devemos criar variáveis de ambiente do pipeline no GitLab.

No aba CI/CD -> Configurações do seu projeto no GitLab, expanda a seção seção Variáveis .

Gitlab env variablesGitlab env variables

É aqui que você deve inserir suas informações confidenciais, para que não fiquem expostas a todos os que trabalham no seu projeto. Insira a chave da API e o segredo da API, bem como o número de telefone de destino para o SMS. Para protegê-las da saída do log do pipeline, certifique-se de que essas variáveis estejam mascaradas, para que não sejam exibidas.

Agora, vamos dar uma olhada novamente no arquivo arquivo .gitlab-ci.yml . Para facilitar a compreensão, vamos simplificá-lo um pouco e deixá-lo com a seguinte aparência:

image: "alpine:latest"

stages:
  - build
  - notify

build:
  stage: build
  script: 
    - exit 1

notify:
  stage: notify
  script:
    - apk add curl
    - curl -X "POST" "https://rest.nexmo.com/sms/json" -d "from=15404161937" -d "text=${CI_PROJECT_NAME} ${CI_COMMIT_SHORT_SHA} Failed!" -d "to=${to}" -d "api_key=${api_key}" -d "api_secret=${api_secret}"
  when: on_failure

Observe que temos apenas duas etapas, sendo que uma delas só ocorre quando há uma falha. Nesta build etapa, estamos forçando uma falha para fins ilustrativos. Essa falha aciona a notify etapa em que o aplicativo cURL é baixado e uma solicitação HTTP é enviada à SMS API da Nexmo.

Na solicitação do cURL, são utilizadas certas variáveis. A ${CI_PROJECT_NAME} e ${CI_COMMIT_SHORT_SHA} variáveis são pré-definidas pelo GitLab, mas a ${to}, ${api_key}e ${api_secret} são as que definimos contendo nossas informações do Nexmo.

Se você enviar seu projeto Git, ele deve enviar um SMS em caso de falha, e esse SMS deve incluir o projeto que falhou, bem como o commit que falhou.

Ampliando as opções de mensagens com a Messages API

A SMS API da Nexmo é ótima, mas e se você quiser alcançar outras plataformas além do simples SMS? É aí que entra a Messages API da Nexmo, que oferece suporte a SMS, Facebook Messenger, Viber e WhatsApp.

A configuração exige um pouco mais de trabalho, mas, em troca, você tem acesso a muito mais recursos.

Para começar, você vai precisar de algum tipo de serviço de back-end. Como o Nexmo é compatível com o Node.js, faz sentido usar o Node.js e o JavaScript para evitar ter que criar suas próprias solicitações HTTP.

Crie um novo diretório de projeto, que ficará hospedado fora do seu projeto no GitLab. Nesse diretório, execute o seguinte:

npm init -y
npm install nexmo@beta express --save
touch main.js

Os comandos acima criarão um novo arquivo package.json e um main.js para toda a lógica do aplicativo e instalarão cada uma das dependências.

O objetivo desse backend é controlar os webhooks que o serviço Nexmo utilizará. Ao trabalhar com a Messages API do Nexmo, um webhook de status e um webhook de entrada são obrigatórios como parte do fluxo de mensagens.

Abra o arquivo arquivo main.js e inclua o seguinte:

const Express = require("express");
const Nexmo = require('nexmo');

const server = Express();

server.use(Express.json());
server.use(Express.urlencoded({ extended: false }));

const nexmo = new Nexmo({
    apiKey: "NEXMO_API_KEY",
    apiSecret: "NEXMO_API_SECRET",
    applicationId: "NEXMO_APPLICATION_ID",
    privateKey: "NEXMO_PATH_TO_PRIVATE_KEY"
});

server.post("/status", (request, response, next) => {
    console.log(request.body);
    response.send(request.body);
});

server.post("/inbound", (request, response, next) => {
    console.log(request.body);
    response.send(request.body);
});

server.listen("3000", () => {
    console.log("Listening at :3000...");
});

Por enquanto, ignore os tokens. Vamos nos preocupar em obtê-los daqui a pouco.

O código acima cria um servidor Node.js simples com dois endpoints de API, que representarão os webhooks necessários. No nosso cenário, vamos apenas exibir as solicitações que chegam aos webhooks e devolvê-las ao solicitante.

Uma solicitação que chega ao status pode ser semelhante a esta:

{
    message_uuid: 'UUID_STRING',
    to: { number: 'RECIPIENT_PHONE_NUMBER', type: 'sms' },
    from: { number: 'SENDER_PHONE_NUMBER', type: 'sms' },
    timestamp: '2019-09-09T23:18:25.308Z',
    usage: { price: '0.0062', currency: 'EUR' },
    status: 'delivered'
}

Como não receberemos mensagens dos usuários, o webhook não é muito relevante para nós, embora seja obrigatório.

Então, vamos voltar às informações sobre o token:

const nexmo = new Nexmo({
    apiKey: "NEXMO_API_KEY",
    apiSecret: "NEXMO_API_SECRET",
    applicationId: "NEXMO_APPLICATION_ID",
    privateKey: "NEXMO_PATH_TO_PRIVATE_KEY"
});

A esta altura, você já deve ter o apiKey e apiSecret valores do exemplo anterior, em que a SMS API foi usada diretamente com o cURL no caso de uma implantação com falha. O que ainda não temos são os applicationId e o privateKey , que na verdade é um arquivo.

No Painel do Nexmo, clique em Mensagens e Envio e prossiga com a criação de um novo aplicativo.

Nexmo Messages ApplicationCreate messages application

Dê um nome ao aplicativo e forneça a URL de cada um dos webhooks que você acabou de criar. Se ainda estiver testando localmente, considere usar o ngrok para criar um túnel para o localhost, de modo que você possa continuar testando sem precisar implantar seu aplicativo. Opte por gerar um novo par de chaves (privada e pública) e mova a chave privada baixada para o diretório do seu projeto Node.js.

Ao visualizar as aplicações que você criou no Painel do Nexmo, você deve ter acesso ao ID da aplicação que acabamos de criar. Forneça tanto o ID da aplicação quanto o caminho para a chave privada na nexmo variável que existe em nosso projeto Node.js.

Em teoria, desde que você esteja executando o aplicativo webhook, há duas opções para enviar mensagens do GitLab:

  1. Você pode criar outro endpoint que utilize o SDK do JavaScript para enviar dados.

  2. Você pode usar o cURL, mas também gerar um JWT.

A opção mais simples das duas é simplesmente adicionar outro endpoint ao aplicativo de webhook, algo que o GitLab pode executar em caso de falha, já que o SDK do JavaScript lida com a geração do JWT automaticamente.

No projeto Node.js, inclua o seguinte:

server.post("/notify", (request, response, next) => {
    nexmo.channel.send(
        { type: "sms", number: request.body.recipient },
        { type: "sms", number: request.body.sender },
        {
            content: {
                type: "text",
                text: request.body.message
            }
        },
        (error, data) => {
            if(error) {
                return response.status(500).send(error);
            }
            response.send(data);
        },
        { useBasicAuth: true },
    );
});

No cenário acima, as informações do destinatário e do remetente, bem como as informações da mensagem, são enviadas junto com a solicitação. Em seguida, o aplicativo enviará a mensagem, e os webhooks serão utilizados nesse processo.

Se fôssemos atualizar nossa configuração do GitLab CI, ela poderia ficar assim:

image: "alpine:latest"

stages:
  - build
  - notify

build:
  stage: build
  script: 
    - exit 1

notify:
  stage: notify
  script:
    - apk add curl
    - curl -X "POST" "http://HOST/notify" -H 'content-type: application/json' -d '{ "sender": "15404161937", "recipient": "${to}", "message": "${CI_PROJECT_NAME} ${CI_COMMIT_SHORT_SHA} Failed!" }'
  when: on_failure

Na configuração acima, é utilizada a aplicação Node.js e é enviada uma carga JSON. As informações contidas na carga são os dados que foram previamente adicionados como variáveis de pipeline para o projeto do GitLab.

Lembre-se de que, com a Messages API, você pode utilizar técnicas de envio de mensagens além do SMS, embora o SMS tenha servido de base para este exemplo.

Conclusão

Você acabou de ver como incluir notificações por SMS no seu pipeline de integração contínua e implantação contínua usando o Nexmo e o GitLab. Embora não tenhamos criado um projeto muito sofisticado neste tutorial, os Concepts utilizados poderiam ser facilmente aplicados a um projeto mais complexo. O importante aqui é que você pode usar suas informações do Nexmo, criar variáveis de ambiente para o seu pipeline e configurar uma etapa de falha para notificar sua equipe por SMS.

Compartilhar:

https://a.storyblok.com/f/270183/384x384/5b89273998/nraboy.png
Nic Raboy