10 boas práticas e dicas para usar o GitHub Actions

Neste artigo você vai ver:

GitHub Actions é uma ferramenta relativamente nova (2019), mas com uma adoção crescente a cada dia. Poder automatizar vários processos diretamente a partir dos seus repositórios aliado à boas práticas no GitHub Actions ajudam muito na rotina de trabalho. 

Para otimizar ainda mais o seu fluxo de trabalho, vamos conhecer no artigo de hoje 10 boas práticas e dicas que vão facilitar o uso da ferramenta e a vida de devs no dia a dia de trabalho. Confira abaixo!

1. Criar workflows eficientes

Um workflow eficiente é aquele que realiza a tarefa pela qual ele foi criado no menor tempo possível, ou seja, um workflow otimizado.

Para isso, é preciso usar o mínimo de configurações possíveis para executar aquela tarefa. Por exemplo, se seu workflow for executado em um contêiner, certifique-se de usar uma imagem leve do Docker, como alpine, e instale o mínimo de ferramentas possível para reduzir o tempo de execução do workflow, desde a inicialização até o final da execução.

Da mesma forma, evite usar workflows com dependências inúteis no contexto do projeto (copiado de outro lugar), pois vão atrasar a execução do workflow. Inclusive, vale a pena conferir se o comando ou a ferramenta que você precisa já não está instalado por padrão no runner do GitHub que está usando.

Dica da dica do GitHub Actions

Outra otimização interessante é sobre os triggers usados nos workflows. Deixar triggers genéricos como on: push ou on: pull_request para rodar para cada um desses eventos pode gerar execuções (runs) de workflows desnecessárias. 

Neste caso, pode ser interessante usar o subtipo paths para garantir que o workflow só seja executado quando for alterar alguns arquivos específicos. Por exemplo, não compensa executar o workflow validando os testes unitários do seu software caso tenham sido alterados apenas arquivos do repositório não relacionados a eles.

Certifique-se também de aproveitar o mecanismo de cache do GitHub sempre que puder, isso vai te fazer ganhar minutos de acordo com a quantidade de dependências que seu projeto usa.

Caso você precise testar ou validar algo em diversas plataformas ou linguagens, avalie usar o conceito de matrix nos seus workflows, pois com poucas configurações, você consegue executar vários workflows em paralelo (já ouviu falar de DRY?).

Nesse exemplo, estas 15 linhas permitem gerar 3 x 4 = 12 workflows em paralelo.

Fazendo 4 testes em cada uma das 3 plataformas, para cada versão do python informada na matrix.

2. Usar fluxos de trabalho reutilizáveis

É frequente ter várias etapas de nossos workflows que se repetem em diversos fluxos de trabalho. Da mesma forma que no desenvolvimento de software, ter implementação duplicada torna seu código difícil de manter, por ser desnecessariamente grande, adicionar dívida técnica extra, ou simplesmente ser uma perda de tempo que poderia ter sido melhor gasta.

Recentemente, o GitHub Actions permitiu usar workflow reutilizáveis. Um fluxo de trabalho reutilizável é como qualquer outro workflow do GitHub Actions, com uma diferença importante: ele inclui um trigger workflow_call.

Permitindo acesso

Além disso, é possível tornar esses workflows acessíveis em toda a sua organização. Depois de adicionar o trigger workflow_call, para certificar-se de que os repositórios em sua organização tenham acesso a ele, é preciso ir nas configurações do seu repositório, selecionar Actions e habilitar o acesso aos repositórios em sua organização. Conforme imagem abaixo (fonte):

Captura de tela com os acessos de um repositório. Em inglês, está escrito “Acess” e três opções: “Not accessible”, “Accessible by any repository in the organization” e “Accessible by any repository in the enterprise”. A imagem indica que opte pela segunda opção e clique em “Save”.

No entanto, existem algumas limitações:

  • Você não pode se referir a um fluxo de trabalho reutilizável que esteja em um repositório privado. Neste caso, somente outros fluxos de trabalho nesse repositório privado poderão usá-lo.
  • Os fluxos de trabalho reutilizáveis não podem chamar outros fluxos de trabalho reutilizáveis.

3. Concorrência

O GithHub Actions é gratuito e com poucos limites quando usado em repositórios públicos. Porém, em repositórios privados, existem muitas restrições a respeitar. Uma delas está relacionada ao tempo de uso dos runners do Github Actions, que tem um limite de 2000 minutos por mês.

Consequentemente, uma boa prática é evitar que workflows duplicados rodem em paralelo. Hoje, existe no GitHub Actions uma configuração nativa de concorrência.

Por exemplo, usando a implementação abaixo no seu workflow:

concurrency:
 group: ${{ github.workflow }}-${{ github.ref }}
 cancel-in-progress: true


Você vai garantir que o workflow nunca será executado em paralelo para a mesma branch, cancelando o workflow run anterior, privilegiando a execução com o código atualizado.

Isso pode fazer bastante diferença somando todas as ocorrências onde um workflow pode ser executado duas ou mais vezes, porque vários eventos da mesma branch iniciaram ele ou porque um novo workflow iniciou enquanto o build anterior ainda não tinha finalizado (tornando o run anterior obsoleto).

Mais dicas sobre concorrência

Uma outra maneira de limitar a quantidade de minutos que nossos workflows, em particular nas situações em que não queremos que o CI seja executado, é usar mensagem nos seus commits contendo as strings:

  • skip ci
  • ci skip
  • no ci
  • skip actions,
  • actions skip

Assim, os fluxos de trabalho geralmente acionados nos eventos push ou pull_request serão ignorados.

4. Segurança: Segredos

Um dos recursos mais poderosos do GitHub Actions é o uso de segredos criptografados. É possível armazenar segredos com segurança nas configurações do seu repositório e fornecê-los como entradas ou variáveis de ambiente para suas ações a qualquer momento.

A recomendação aqui é óbvia, mas não custa nada lembrar: não use segredos hardcoded em seus workflows (seja privado ou público), defina-os manualmente nas configurações do repositório e acesse-os usando variáveis de ambiente ou inputs.

Nota: Outra boa prática, é limitar ao máximo quem tem acesso aos segredos e a execução dos workflows, também chamado de Principle of least privilege (PLP). Pois é possível um usuário malicioso imprimir os segredos em um workflow se ele quiser. 

5. Segurança: Avaliar vulnerabilidades

Quando desenvolvemos, se tem uma coisa que queremos evitar é subir vulnerabilidades no nosso código. Felizmente, existem algumas ferramentas que podem nos ajudar a verificar problemas de segurança e vulnerabilidades em nossos códigos (e dependências de terceiros) antes de aprovar novas contribuições.

Exemplos:

  • Snyk (SCA – Software Composition Analysis);
  • SonarCloud (SAST – Static Application Security Testing);
  • Horusec (SAST – Static Application Security Testing);
  • OWASP ZAP (DAST – Dynamic Application Security Testing).

Essas ferramentas também podem ser usadas no GitHub Actions. Inclusive, segue um workflow de exemplo:

6. Segurança: Usar o hash do commit em vez da tag

As tags podem ser forçadas a qualquer momento, mas se o repositório de uma ação que você usa em seus workflows estiver comprometida, a tag que você usa pode ser forçada via push com uma versão maliciosa, que pode até mesmo enviar os segredos de repositório para um servidor de terceiros.

O ideal é sempre avaliar o código fonte do repositório da ação para essa determinada tag e, em seguida, usar o hash do commit SHA1 associado, pois é quase impossível falsificar um novo commit com o hash exato.

Para obter o hash do commit de uma tag específica, siga o caminho: ir para a página Releases do repositório, clicar no hash SHA1 curto abaixo do nome da tag e copiar o hash completo da URL.

Por exemplo, aqui nesta ação pessoal git-commit-push:

Captura de tela da área de “tags”, na “v1.3” e com a opção “205c043” selecionada.

Captura de tela da parte de “Merge branch ‘main’” e selecionada a parte com o hash do commit.


Mudar:

– uses: GuillaumeFalourd/git-commit-push@v1.3

Para:

– uses: GuillaumeFalourd/git-commit-push@205c043bca2f932f7a48a28a8d619ba30eb84baf

7. Segurança: Substituir pull_request_target por pull_request quando possível

Sabiam que o evento pull_request_target concede a um PR acesso a um token do GitHub com permissão de escrita em seu repositório? 

Tem que tomar bastante cuidado com isso, pois expõe seu código à modificação por um terceiro que simplesmente precisaria abrir um PR em seu repositório para efetuar ações maliciosas

O evento pull_request é mais seguro, e se você não estiver usando ainda, avalie onde usar o evento pull_request_target e faça adequações caso seja necessário.

8. Aplicar regras de validação de Pull Request

Com o GitHub Actions, é possível obrigar uma Pull Request passar por vários checks (workflows) antes de poder ser “mergeada”, ou seja, passar pelo merge… ser mesclada.

Para isso, é preciso ir em Settings => Branches => Add Rule

Captura de tela com os passos: settings, branches e add rule.

Nesta página, selecione Require status checks to pass before merging (Exigir que as verificações de status sejam aprovadas antes da fazer o merge) e selecionamos tudo abaixo dela. 

Aparecerão todos os workflows necessários para habilitar no merge – no caso aqui abaixo, existe apenas um workflow build-test.

Captura de tela ainda na página de settings e branches, agora com as caixas de “require status checks to pass before merging”, “requise branches to be up date before merging” e “build-test” selecionadas.

Para Branch name pattern (Padrão de nome de branch), insira main e crie a regra. 

Depois, se você voltar para a página de solicitação da Pull Request, verá que nenhuma PR pode ser “mergeada” antes que os testes sejam aprovados (a menos, é claro, que você tenha privilégios de administração do espaço).

Captura de tela com o aviso “Some checks haven’t” completed yet” e que o “request” está aguardando aprovação.

9. Fazer limpeza frequente dos artefatos

Como falado no item 3 sobre concorrência, o GitHub fornece uma quantidade generosa de tempo de compilação gratuito para todos os repositórios e organizações. O armazenamento, no entanto, é muito mais limitado – conforme imagem abaixo. 

Texto alternativo: Tabela com três colunas e seis linhas. Nas colunas, em ordem, aparecem os tópicos “product”, “storage” e “minutes (per mounth)”. A ordem das informações das linhas são: GitHug Free - 500 MB - 2,000; GitHub Pro - 1GB - 3,000; GitHug Free for organizations - 500 MB - 2,000; GitHub Team - 2 GB - 10,000; GitHub Enterprise Cloud - 50 GB - 50,000.

Se você deseja armazenar artefatos para todos os seus workflows de CI/CD (o que pode ser prático para teste e repetibilidade), esse valor é facilmente atingido.

Nota: O GitHub cobra US$ 0,25/GB para armazenamento além dos 2 GB incluídos.

O problema é que quando o GitHub Actions foi lançado originalmente, não havia como excluir um artefato para liberar armazenamento — você precisava esperar até 90 dias para expirar automaticamente.

Felizmente, isso mudou com o tempo e existe hoje uma API que pode auxiliar a apagar artefatos dos seus repositórios. E, claro, algumas ações foram criadas pela comunidade para fazer isso sob demanda.

Aqui está um exemplo de um workflow que rodaria diariamente e removeria os artefatos criados a mais de 7 dias no repositório:

10. Use actions de debug para testar seus workflows

Testar um workflow no GitHub Actions pode ser trabalhoso e, frequentemente, cheguei a precisar usar dezenas de commits até chegar no resultado que eu esperava nos meus repositórios.

Felizmente, alguém criou essa action: action/upterm

Essa action usa upterm e tmux para oferecer uma maneira direta de interagir com o host no qual as ações estão executadas.

É possível usar ela da seguinte forma:

name: CI
on: [push]
jobs:
 build:
  runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup upterm session
      uses: lhotari/action-upterm@d23c2722bdab893785c9fbeae314cbf080645bd7

Essa action gera uma chave ssh para se conectar no host

Nota: Lembrando o passo a passo para adicionar uma nova chave SSH para sua conta do Github

É possível obter essa chave abrindo a guia Checks na execução do workflow e rolar até a etapa dessa action no job. O workflow estará aguardando o usuário se conectar para ele poder efetuar as operações desejadas pelo seu terminal.

Bônus: Também existe a possibilidade de testar seus workflows localmente usando Act.

Conclusão

Última dica: Usar uma action do Github é a mesma coisa do que usar uma biblioteca como dependência do seu projeto. As actions do Github no Github Marketplace são repositórios públicos de código aberto e nem sempre são apoiados por grandes empresas.

A maioria dessas actions realiza operações simples que você pode verificar olhando o código fonte do repositório, mas sempre é possível que o proprietário configure coisas maliciosas dentro da implementação. Por essa razão, fique atento na hora de escolher uma ou outra ação/biblioteca, é preciso ser cauteloso e verificar o código e suas eventuais vulnerabilidades antes de usá-los para seus próprios projetos.

Nota: Seja ainda mais cauteloso se precisar informar o Personal Access Token (PAT) como variável de entrada da action.

É isso por hoje! Lembrando que para quem ainda está descobrindo a ferramenta, temos no blog vários outros artigos explicando como fazer algumas operações no GitHub Actions.

A documentação oficial do GitHub também contém um artigo sobre Boas práticas de segurança para usar recursos do GitHub Actions, que recomendo a leitura. O artigo fala a respeito de script injections, self-hosted runners, cross repository access, entre outras dicas.

Se quiser aprofundar o uso da ferramenta com alguns exemplos também, seguem aqui dois repositórios pessoais que podem ser úteis. O primeiro com algumas provas de conceitos de workflows. Já o segundo com algumas ações práticas no dia a dia.

Gostou do conteúdo sobre boas práticas de Github Actions? Então deixe seu comentário!

Referências

Capa do artigo sobre boas práticas de GitHub Actions. Na foto, uma pessoa está digitando em seu teclado, aparecendo somente parte do corpo. O resto da imagem é composto por um monitor, um headphone e uma mesa, ao fundo está uma janela.
foto Guillaume Falourd
Back-end Developer
Zupper tentando transformar o complexo em simples através de conteúdos diversificados, com intuito de impactar o mercado de TI e as pessoas ao seu redor da melhor forma possível.

Artigos relacionados

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.