Do zero à automação em 7 minutos com GitHub Actions

Lucas Santos - May 13 '20 - - Dev Community
Photo by Josh Redd on Unsplash

Em um artigo anterior, comentei como poderíamos criar um backend GraphQL completo apenas usando uma imagem Docker e um arquivo de configuração. Tudo isso hospedado no Azure. Agora vamos aprender a automatizar os deploys que são feitos para a nossa hospedagem e a atualização automática do nosso backend!

Este projeto todo visa criar um backend para meu futuro arquivo de conteúdo que estará presente no meu site. Mas sempre que eu atualizar o backend ou mudar o schema do GraphQL vou ter que fazer todo o deploy do serviço novamente.

Então, ao invés disso, eu gostaria que, a cada push no meu branch master, eu gerasse uma nova versão do arquivo e enviasse a atualização para o Azure. Porém eu não quero ter que usar outras ferramentas para isso, quero manter toda a stack o mais simples possível, como estamos utilizando somente o GitHub e o Azure, nada mais justo do que continuar no GitHub para fazer a automação, não é mesmo?

Por isso que vamos usar os GitHub Actions

Similar a outros provedores de CI como o Travis ou o Circle, o GitHub também possui um sistema de integração e automação do repositório. A facilidade deste sistema em relação aos outros é que você já está dentro do mesmo repositório e ja está dentro da mesma ferramenta.

O projeto que vamos utilizar para automatizar será o meu repositório publico de backend:

Veja que o repositório é super simples, não contém muitos arquivos, apenas um docker-compose.yml para testes locais e o nosso arquivo yml do mongoke que será o schema GraphQL.

No topo da página, ao lado de settings, temos o botão Actions, será lá que vamos configurar a nossa automação!

O GitHub já possui uma série de workflows prontos, porém, infelizmente, ainda não temos nenhum para o que queremos fazer. Mas o que queremos fazer? Para deixar tudo mais claro, vamos listar todas as etapas do processo:

  1. Recebemos um push na branch master
  2. Conectamos com a Azure através de um service principal e de uma action chamada Azure/login
  3. Depois vamos utilizar a action Azure/cli para poder executar o comando de deploy do nosso container

Alguns detalhes que temos que perceber:

  • O cache do GitHub Pages é um pouco longo, então vamos ter que gerar um número aleatório ou uma fingerprint para colocar na URL do nosso arquivo YAML do Mongoke
  • Temos uma URI do MongoDB que deve ser um segredo

Criando um secret

Primeiramente vamos tratar das nossas dependências, a dependência mais fácil de ser resolvida é criar a URL do MongoDB como um secret. Para isso vamos até a nossa aba Settings e clicamos em Secrets. Basta adicionar um novo secret clicando no link Add new Secret e preencher um nome e o conteúdo do mesmo. No caso estamos adicionando a URI do MongoDB, então vamos chamar este secret de MONGODB_URI

Permitindo ações na Azure

Para que possamos permitir que o GitHub execute ações em nosso nome na Azure, vamos precisar criar um Service Principal. Este recurso nos dá uma conta de aplicação para que possamos permitir que outras pessoas ou serviços conectem-se em nosso portal e realize ações em nosso nome.

Para criarmos este recurso, vamos usar o Azure CLI. Depois de realizar o login com o comando az login, basta executar o seguinte comando:

az ad sp create-for-rbac --name <nome-do-SP> --role contributor --scopes /subscriptions/<ID-da-subscription>/resourceGroups/<nome-do-resourcegroup> --sdk-auth
Enter fullscreen mode Exit fullscreen mode

Para obter o ID da sua subscription basta executar o comando az account list e buscar a chave id da subscription que estiver com a chave isDefault marcada como true. Você também pode dar qualquer nome ao seu Service Principal, faça com que ele seja descritivo para saber a quem você está garantindo permissões.

Por último, outro detalhes importante é somente dar as permissões aos recursos necessários, ou seja, não vamos criar um SP para a conta TODA , mas sim somente para o Resource Group que precisamos, no meu caso, este RG se chama personal-website e é onde eu estou agrupando todos os recursos relativos ao meu site.

Este comando deve dar uma resposta em JSON do tipo:

{
  "clientId": "xxxxxxx",
  "clientSecret": "xxxxxxxx",
  "subscriptionId": "xxxxxxxx",
  ...
}
Enter fullscreen mode Exit fullscreen mode

Copie toda essa resposta e crie um novo secret no GitHub chamado AZURE_CREDENTIALS:

Agora devemos ter dois secrets criados:

Criando um workflow

Para criarmos o nosso primeiro workflow, basta voltarmos para o painel Actions ao lado de Settings e clicar no botão Set up this workflow:

Esta ação deve levar para uma nova tela com um modelo inicial do código:

Perceba que as GitHub Actions nada mais são do que um arquivo YAML que ficam em uma pasta /.github/workflows e este será o nome do workflow, portanto é importante que ele seja bastante descritivo. Vamos dar o nome do nosso de publish-prod.yml:

O conteúdo que temos é o seguinte:

Primeiro, vamos setar um nome para nosso workflow, este será o nome que aparecerá na UI do GitHub, então podemos deixar um pouco mais bonito:

Agora vamos definir em qual tipo de ação queremos que ele rode. Como queremos que ele rode em qualquer push ou PR no branch master, não vamos fazer nenhuma alteração, mas se precisássemos alterar esta ação, teríamos que mudar a chave on. Para verificar quais são as ações disponíveis, basta clicar no editor e apertar ENTER que um intellisense será mostrado:

Veja que temos várias ações possíveis, para detalhar melhor, veja a documentação oficial

Então vamos criar uma seção para compartilhar variáveis de ambiente e conteúdos que vamos usar na parte mais a frente do nosso script, por exemplo, o nome do container e também o nome do resource group. Para isso criamos um bloco env:

Agora vamos, de fato, criar a máquina e o que chamamos de runner, que é quem vai rodar o nosso código de testes e de publicação. Todo o workflow é composto de um ou mais jobs que podem ser executados sequencialmente ou em paralelo. No nosso caso não temos que fazer muita coisa, apenas conectar e fazer o deploy. Portando vamos modificar a seção jobs:

Iremos rodar nosso job em uma imagem do Ubuntu, veja as demais opções na documentação. Depois disso vamos configurar os nossos steps, um step é uma sequencia de tarefas que serão executadas como partes de um job, ou seja, aqui será o lugar onde vamos executar o nosso login e o nosso deploy!

Para isso vamos modificar a chave steps e vamos remover todo o conteúdo, então vamos utilizar os steps pré prontos da Azure para poder fazer o login! Podemos pesquisar na caixa de texto lateral por Azure/login:

Ao clicar no nome do step, vamos ter um tutorial de como usá-lo, neste caso é bastante simples, basta copiarmos o seguinte código para dentro do nosso step:

E será aqui que vamos setar o nosso primeiro secret, precisamos do AZURE_CREDENTIALS que criamos anteriormente para poder prover as credenciais de acesso para o login. Para usar um secret basta colocá-lo entre chaves duplas como em: ${{ secrets.AZURE_CREDENTIALS }}.

Nosso arquivo está assim:

Vamos criar um segundo step que vamos chamar de Deploy ACI, que será aonde vamos executar o nosso comando do Azure CLI. Para isso vamos utilizar outro step com o comando run que vai conter a linha que vamos executar em nosso CLI. Em nosso a caso, já com as variáveis substituídas, será esta:

Vamos observar bem a última parte onde criamos a variável MONGOKE_CONFIG_URL, esta variável sozinha não vai ser suficiente, temos que concatená-la com o valor do SHA do commit para não sofrermos com o cache. Para concatenarmos variáveis, temos que trabalhar somente no nível de steps, pois expressões não são permitidas a níveis de jobs ou do workflow como um todo. Vamos então criar um outro step e chamá-lo de Create URL.

Neste step, vamos executar uma Workflow Command, que são comandos nativos do GitHub Actions, que podem ser acessados com a sintaxe ::comando. No nosso caso vamos usar o comando set-env, que serve para criar uma nova variável de ambiente, a sintaxe é a seguinte: ::set-env name=:: e ai poderemos utilizar as expressões de concatenação:

Veja que estamos concatenando ${{ env.MONGOKE_CONFIG_URL }} com ?v= e pegando os seis primeiros digitos de uma variável nativa de ambiente chamada GITHUB_SHA. Vamos adicionar este step após o login:

Agora vamos para o último passo, onde vamos executar o nosso comando, com uma pequena alteração, ao invés de utilizar a variável MONGOKE_CONFIG_URL, vamos trocar para a nossa nova variável MONGOKE_URL:

Nosso arquivo final será assim:

Agora podemos clicar no botão Start Commit e esperar o nosso action ser executado:

Acompanhando o workflow

Podemos acompanhar o nosso workflow na aba Actions:

Lembrando que workflows não executados nenhuma vez não vão aparecer na lista. Basta clicarmos no nome do workflow para podermos ver o que aconteceu:

Agora podemos observar no portal da Azure que nosso container foi atualizado:

E que também nossas URLs estão corretas:

Conclusão

Em 7 minutos automatizamos todo o processo de deploy da nossa aplicação para a Azure e, sem perceber, ganhamos muito tempo com uma ação simples e rápida que pode ser feita em poucos minutos!

Em outros artigos vamos explorar ainda mais os GitHub Actions para outras ferramentas e modelos de aplicação distribuída!

Não deixe de acompanhar mais do meu conteúdo no meu blog e se inscreva na newsletter para receber notícias semanais!

Até mais!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .