Monorepo com Yarn Workspaces + Vue.js + Node.js + Typescript + Github Actions — PARTE 2

Como vimos na última postagem, aprendemos a criar um boilerplate para projetos monorepo utilizando as tecnologias do título (os packages são meramente ilustrativos, a grande ideia esta na organização desse nível de complexibilidade de monorepo).

Agora iremos finalizar implementando uma rotina de CI (Continuous Integration) vinculado com o nosso sistema de versionamento. Irei descomplicar ao máximo estruturas com o Github Actions para objetivos como este.

Antes de mais nada, o que é Github Actions?

Essa feature do nosso querido Github nos permite automatizar fluxos de entrega de nossos softwares.

Para tal, é importante que o versionamento do projeto esteja sendo hosteado no próprio Github.

Sintetizadamente, com ele conseguimos desencadear tarefas automatizadas em certos eventos que estão integrados em nosso dia a dia, sendo eles: Pull request, Push, Merge, etc…

Para ver as informações direto da fonte, acesse o site dessa feature clicando aqui.

Alterando a antiga "master" pra main

Antes de mais nada, vamos alterar nossa branch principal para main, em respeito a iniciativa que esta rolando na comunidade iniciada pelo mestre Linus Torvalds; Para informações detalhadas, de uma olhada nesse video do grande Jeferson clicando aqui.

Va no root do projeto e siga a imagem:

1.0 — Setando no repositório local a branch main

Pós isso, acesse o link de seu repositório no Github.

Se clicarmos em cima do visualizador de branchs, poderemos observar que contém duas, uma sendo a "maldita" e a outra a main.

1.1 — Visualizando as branchs ativas no GitHub

Para resolver isso, iremos acessar a aba Settings em nosso repositório, clicar em Branches e logo em seguida no respectivo ícone para editar; Selecionamos a opção main no select e clicamos em update

1.2 — Realizando o update da main branch

Pra finalizar, voltaremos na aba Code e seguindo o mesmo trajeto da imagem 1.1, clicaremos em View all branches.

Pós, isso, clicamos no ícone para deletar a branch master.

1.3 — Deletando a branch master

Chega de disclaimers, bora pra pratica 👨🏽‍💻

Primeiramente iremos criar dois scripts npm para rodar nossos supostos testes e validar se nosso workflow esta funcionando direito.

Na raiz do projeto, abra o arquivo package.json da maneira que preferir e adicione esse nó "scripts" (linha 8 a 10).

package.json contendo os scripts para rodar testes arbitrários

Feito isso, na raiz do projeto ainda, criaremos uma pasta .github. Dentro da pasta oculta, criaremos outra chamada workflows, que irá conter todas as nossas rotinas de CI do Github Actions.

$ mkdir .github && cd .github && mkdir workflows && cd workflows

💡 Nota¹: Dentro da pasta workflows, você pode adicionar quantos arquivos de CI quiser, só tome cuidado para não extrapolar o plano atual que você tem no Github. Para saber mais sobre o pricing dos planos, acesse a página da feature do Github Actions e desça até o título Simple, pay-as-you-go pricing.

💸 Nota²: 2.000 minutos de uso por mês, pra quem não tem muita noção do que seja, é bastante tempo, até pro uso de uma StartUp.

Dentro dessa pasta iremos criar dois arquivos, cada qual respectivo para cada stack de nosso monorepo. Um terá o nome de ci-server.yml e outro ci-web.yml.

Obs: Os nomes dos arquivos tem que seguir nenhum tipo de regra pra funcionamento.

Workflow de CI pro server package
Workflow de CI pro web package

Os arquivos de workflows são essencialmente arquivos yaml. Arquivos yaml precisam da indentação certa, caso contrário gerará um erro na validação do código.

  1. Definimos um nome pro nosso workflow nas respectivas linhas 1.
  2. No nó "on" definimos em qual ponto no processo o workflow será acionado. Defini que seria quando arquivos do diretório "packages/server/" fossem alterados e fosse feito o push pra branch main.
    Aqui você poderia setar várias configurações em conjunto. Vale lembrar que o "paths" é uma configuração essencial para trabalharmos com monorepo nesse estilo; Com ele que limitamos nosso workflow apenas a stack desejada dentro do projeto.
  3. Em "jobs" defino minha única job chamada "test-routine".
    Aqui podemos setar várias jobs, seguindo o modelo do tópico 2 (e claro, respeitando a indentação).
  4. Em "runs-on" declaro em qual OS quero que rode meu workflow.
  5. Em "strategy" defino que o job rode nas versões 12 e 14 do node. Isso é bem importante pra casos que utilizamos features recentes da linguagem e compilamos pra versões mais aceitas pelas runtimes. Ja teve casos que essa definição testou pra mim se eu tinha configurado o babel corretamente 😂.
  6. A etapa "step" é bem importante. Nela posso declarar o uso de actions escritas por outras pessoas (analogia a libs).
    No primeiro caso utilizo a zcong1993/setup-timezone pra setar o timezone no container do Gihub Actions (importante para blindar alguns testes, ja aconteceu comigo coisas bizarras pela dependência de tempo no projeto 😰.
    Obs¹: Não esqueça de deixar o like ⭐️ na action que estiver usando.
    Obs²: Para ver as opções de uso, acesse o Github Actions Marketplace.
  7. Por fim e não menos importante, declaro qual será o meu fluxo de tarefas específico pro meu projeto. Aqui eu uso o comando "yarn" pra instalar as dependências do projeto e "yarn test:server" pra realizar os testes automatizados da minha aplicação.

As explicações do workflow de web são as mesmas pra esse exemplo.

Feito isso, fazendo o push do código pro repositório no Github e indo na página do mesmo, se clicarmos na tab Actions no menu conseguimos reparar os dois workflows preparados pra rodar!

2.0 — Workflows do Github Actions preparados pra rodar

Pra ver se está tudo certo, fiz uma alteração simples no arquivo de entrada do server e mandei pro repositório em nuvem. Instantaneamente ao lado da listagem de workflows da imagem 2.0 irá aparecer rodando o fluxo que definimos.
Se clicarmos, podemos observar os logs de cada passo que definimos o arquivo yaml.

2.1 — Logs de cada camada definida no workflow.

Conclusão

Finalizamos este com as portas abertas pra criar vários fluxos pelo Github Actions de acordo com nossa necessidade.

O fim dessas duas etapas nos resulta em um boilerplate e um "proto mindset" de aplicações monorepo utilizando essa estrutura, comumente aplicada em projetos hoje em dia.

Referência

Features • GitHub Actions

I write about Architecture and Software Engineering. https://github.com/pedromoraisf 🇧🇷

I write about Architecture and Software Engineering. https://github.com/pedromoraisf 🇧🇷