Gerenciando repositórios no Github “como código” com Terraform — Parte 2
No artigo anterior entendemos as motivações e os primeiros passos para automatizar e gerenciar os repositórios do Github com código. Agora o que nos espera são algumas tarefas um pouco mais avançadas, bem como uma importante menção ao gerenciamento de estado. As novas funcionalidades que eu pretendo adicionar ao nosso projeto são:
- Adicionar um mecanismo de criação de repositórios
- Garantir os acessos aos repositórios em diferentes níveis de acordo com os grupos.
Na minha organização existem as seguintes regras:
- Todas as engenheiras pertencem a um Time da organização, e tem acesso de leitura e escrita de Pull Requests
- Todas as admins, além de terem permissões de leitura e escrita de PRs, têm o papel de
mantainers
nos times de Engineers e Admins. - Além disso, repositórios têm as seguintes características: são criados com um branch default, são todos privados, após o merge as branches são automaticamente deletadas, issues estão habilitados, entre outros.
- Por fim, admins têm permissão de admin no grupo, enquanto engineers têm permissão de push.
Criando mais um grupo
Para estender a lógica que já criamos anteriormente, o primeiro que irei fazer é adicionar também um grupo de admins junto ao grupo de engineers.
Dica: Se você quiser, pode sempre rodar um terraform plan
a cada mudança para verificar que está tudo indo como planejado.
Após criar os grupos, é hora de adicionar as pessoas!
Adicionando pessoas aos grupos
O primeiro que vou fazer é criar uma lista de usuários que são admins e engineers. Na definição do módulo, declaro as duas listas:
Pela primeira vez teremos variáveis dentro do módulo team então também crio um arquivo chamado variables.tf
dentro da pasta team, com o seguinte conteúdo:
É hora de declarar o resource que faz a inserção dos usuários no time correspondente. O nome do resource é github_team_membership.
Ao final desta etapa, se você rodar terraform plan
e terraform apply
, já deveria ter os seus times corretamente populados com os usuários declarados no main.tf.
Dica: para adicionar pessoas a times, elas precisam estar na organização do projeto previamente. Se você rodar este comando e a pessoa não estiver no projeto, além de não aparecer no time, será enviado um convite a ela, que ficará aguardando no modo pendente.
Agora que temos times que contém usuários neles, vamos criar repositórios!
Criando repositórios
Seguindo o padrão da última funcionalidade, vou criar um módulo à parte para cada repositório que eu quiser criar. Para isso, vou definir o módulo dentro do main.tf na raiz e criar um diretório com o nome project, que também irá conter um arquivo main.tf.
Assim ficará a definição do módulo:
Para declarar o resource que faz a criação de repositórios, usamos o github_repository.
- name: nome do repositório no Github.
- description: a própria description que acompanha o repositório quando você acessa através da UI.
- visibility: define se o repositório será privado ou público.
Perceba que name e description vêm de variáveis. Assim como fizemos anteriormente, vamos declarar as variáveis dentro do diretório do módulo, e defini-las dentro do módulo recém criado. Fica assim:
Já é possível rodar terraform plan
e ver que o seu repositório já vai ser criado! O último passo é dar acessos baseados nos grupos e usuários criados anteriormente. Aproveite para rodar também o terraform apply
como foi feito anteriormente, para aplicar todas as mudanças até aqui.
Concedendo acesso dos grupos de usuário no repositório criado
Por padrão, quando um repositório no Github é criado, a pessoa que criou fica com acesso de maintainer e dependendo da configuração da organização, ninguém mais tem acesso.
O que queremos atingir com esse passo é que toda vez que um repositório é criado, todo mundo do grupo de engineers
tem acesso para fazer push e todo mundo do grupo de admins
tem acesso de admin.
Pela primeira vez, teremos um resource que depende do resultado de um outro resource para ser aplicado. Quando criamos o grupo admins
, a este grupo foi atribuído um id, e é este id que precisamos na hora de dizer que as pessoas do grupo de admins
terá acesso de admin ao repositório.
O primeiro passo é expôr os ids dos grupos criados. Para isso, vamos criar dentro do diretórioteam
os outputs.
Neste caso, engineers-team
e admins-team
são os nomes dos resources que eu dei quando criei o time. Lendo a documentação, eu concluí que dos 3 atributos exportados neste resource, o slug é suficiente para mim, então ele foi o único atributo que exportei.
O próximo passo é definir estes atributos como variável do meu módulo project
. Adicione ao final do arquivo project/variables.tf
as seguintes variáveis:
Dentro do módulo do repositório, declare as variáveis que conterão o nome dos times.
Dica: Repare a maneira como os valores exportados através do output são referenciados: module.[nome-do-modulo].[nome-da-variavel-definida-no-output].
Agora é só criar o resource que irá fazer a associação! O resource é o github_team_repository.
Agora está tudo pronto para rodar o terraform plan
e terraform apply
e tudo deveria funcionar como esperado!
O legal é que criando repositórios e concedendo acessos dessa maneira, não corre o risco de deixar ninguém de fora, e também não necessariamente quem cria o repositório tem acesso de admin a ele. Ao rodar este último comando, se a pessoa que está criando o repositório não é admin, ela "perde" sua permissão de admin para ter a permissão de push somente, o que é mais do que suficiente na grande maioria dos casos.
Gerenciamento de estados
Se você já trabalhou com Terraform antes, entende como funciona o gerenciamento de estados. Caso este tema seja novo para você, visite este artigo antes de colocar todo esse aprendizado que vimos aqui em produção. É muito importante entender como guardar o estado das alterações que fazemos num lugar centralizado e acessível.
Conclusão
Enquanto eu escrevia este artigo, eu escrevia o código junto. Neste repositório do Github você encontra o código completo. Se você chegou até aqui, espero que tenha se divertido tanto quanto eu 😄
Se ficou alguma dúvida ou se você tem alguma sugestão, escreve seu comentário aqui. Até a próxima!