Alura > Cursos de Front-end > Cursos de Angular > Conteúdos de Angular > Primeiras aulas do curso Angular e GitHub Actions: aplique CI/CD no seu Design System

Angular e GitHub Actions: aplique CI/CD no seu Design System

Automatizando com GitHub Actions - Apresentação

Boas-vindas a mais um curso de Angular com design system! Meu nome é Antonio Evaldo, e serei a pessoa instrutora que irá te acompanhar ao longo desta jornada.

Audiodescrição: Antonio se descreve como um homem branco, com bigode e cavanhaque pretos, cabelos cacheados pretos e volumosos na altura dos ombros, e olhos castanho-escuros. Ele usa óculos de armação arredondada preta, veste uma camisa preta, e está sentado em frente a uma parede clara iluminada em gradiente rosa e azul com alguns quadros.

O que vamos aprender?

Teremos como base o design system desenvolvido ao longo desta formação para a empresa fictícia Alfabit. Para isso, trabalharemos no Storybook, que contém os componentes de:

A partir de agora, vamos avançar e começar a automatizar alguns processos relacionados ao desenvolvimento desses componentes em uma empresa real.

Por exemplo: processos como test e lint serão automatizados com o GitHub Actions. Mostraremos no VS Code os arquivos criados para isso.

No VS Code, temos uma pasta chamada ".github", que contém uma subpasta chamada "workflows". Nela, criaremos três arquivos, um para cada automação. São eles:

Em ci.yml, automatizamos as tarefas de teste de unidade e lint dos nossos projetos. Outro arquivo será o chromatic.yml, que automatizará a publicação do Storybook e os testes visuais.

Assim, não precisaremos realizar essas tarefas manualmente.

Por fim, abordaremos a sigla CD de Continuous Delivery (em português, entrega contínua), automatizando a entrega e publicação dos pacotes no npm.

Utilizaremos comandos do Nx no processo, e o resultado terá vários fluxos (ou workflows) do GitHub Actions, com execuções de todos esses fluxos de trabalho, como o CI, o Chromatic e o Publish.

Por exemplo: no fluxo de CI, ao abrir a etapa de execução do comando npx nx affected -t lint test --exclude=alfabit, encontraremos tarefas como lint e test sendo executadas.

Primeiro, aprenderemos a automatizar tarefas comuns, como lint e test. Na sequência, entenderemos como automatizar o Chromatic junto ao monorepo Nx.

Também abordaremos a automatização da publicação de componentes no npm. Ao longo do curso, focaremos na otimização dos processos, pois é crucial economizar recursos e tempo de execução em CI/CD. Discutiremos bastante sobre otimização, pois isso pode economizar custos para a empresa.

Conclusão

Ao final deste curso, você conseguirá aplicar a cultura de CI/CD na sua empresa, automatizando recursos e obtendo todos esses benefícios.

Observação: para melhor acompanhamento do conteúdo do curso, é importante ter familiaridade e conhecimentos básicos sobre Angular, Nx, Storybook e GitHub Actions.

Tudo preparado para começar? Esperamos você no próximo vídeo!

Automatizando com GitHub Actions - Executando lint e testes dos projetos

Atualmente, temos o design system da empresa fictícia Alfabit, trabalhado com quatro componentes: typography, button, input e modal.

No entanto, queremos abordar questões relacionadas a construção de código e criação de novos componentes do design system, considerando um ambiente real onde colaboramos com outras pessoas e realizamos outras tarefas, como lint e testes de unidade e integração dos componentes.

Por enquanto, ainda não aprendemos a executar essas tarefas especificamente para os quatro componentes desenvolvidos no projeto, mas vamos explorar isso agora.

Executando lint e testes dos projetos

Acessando o arquivo project.json

Com o VS Code aberto, usaremos o atalho "Ctrl + P" para localizar o arquivo project.json do projeto de botão (libs\ui\button) e analisar a seção targets.

project.json:

// código omitido

"targets": {
  "build": {
    "executor": "@nx/angular:package",
    "outputs": ["{workspaceRoot}/dist/{projectRoot}"],
    "options": {
      "project": "libs/ui/button/ng-package.json"
    },
    "configurations": {
      "production": {
        "tsConfig": "libs/ui/button/tsconfig.lib.prod.json"
      },
      "development": {
        "tsConfig": "libs/ui/button/tsconfig.lib.json"
      }
    },
    "defaultConfiguration": "production"
  },
  "test": {
    "executor": "@nx/jest:jest",
    "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
    "options": {
      "jestConfig": "libs/ui/button/jest.config.ts"
    }
  },
  "lint": {
    "executor": "@nx/eslint:lint"
  }
}

Entre esses alvos, temos a tarefa de build, que já conhecemos, e outras duas tarefas que não utilizamos nos cursos anteriores: test e lint.

Com nossos conhecimentos de Nx, podemos executar ambas as tarefas utilizando o comando nx run e indicando qual tarefa de qual projeto queremos executar.

Executando múltiplas tarefas simultaneamente

Para executar múltiplas tarefas simultaneamente, podemos usar o comando nx run-many, que nos permite especificar quais tarefas queremos executar em vários projetos. Precisamos informar ao comando quais tarefas queremos executar, utilizando a flag -t para especificar lint e test.

nx run-many -t lint test

Além disso, existe uma flag interessante desse comando: a --exclude, que permite excluir algum projeto da execução das tarefas. Podemos, por exemplo, excluir o projeto alfabit, que não estamos utilizando. O comando atualizado ficaria assim:

nx run-many -t lint test --exclude=alfabit

Ao pressionar "Enter", ele executa os alvos lint e test para cinco projetos:

Corringindo as tarefas de lint

Alguns erros de lint foram detectados, como um problema no pacote tslib, que não foi utilizado pelo projeto button. Podemos clicar no caminho do arquivo package.json de button no terminal para abrir o local do erro.

Em dependencies, temos o pacote tslib, que não é utilizado diretamente pelo código do projeto de button. Essa dependência é adicionada automaticamente quando o Nx constrói o projeto, e isso ocorre para todas as bibliotecas Angular.

No terminal, podemos verificar que esse erro também está presente em outros projetos, como typography, input, modal e storybook-host.

Das dez tarefas executadas, cinco falharam, que são justamente as de lint. Por outro lado, as tarefas de teste de unidade passaram. Vamos corrigir as tarefas de lint que falharam para executar o comando novamente. No arquivo package.json de button, vamos excluir o pacote tslib:

package.json (libs > ui > button):

{
  "name": "@alfabit-alura/button",
  "version": "2.1.0",
  "peerDependencies": {
    "@angular/common": "^17.3.0",
    "@angular/core": "^17.3.0"
  },
  "dependencies": {
    "@alfabit-alura/typography": "2.1.0"
  },
  "sideEffects": false,
  "publishConfig": {
    "access": "public"
  }
}

Após salvar, podemos corrigir os erros nos outros arquivos package.json:

package.json (libs > ui > input):

{
  "name": "@alfabit-alura/input",
  "version": "2.1.0",
  "peerDependencies": {
    "@angular/common": "^17.3.0",
    "@angular/core": "^17.3.0"
  },
  "sideEffects": false,
  "publishConfig": {
    "access": "public"
  }
}

package.json (libs > ui > modal):

{
  "name": "@alfabit-alura/modal",
  "version": "2.1.0",
  "peerDependencies": {
    "@angular/common": "^17.3.0",
    "@angular/core": "^17.3.0"
  },
  "dependencies": {
    "@alfabit-alura/typography": "2.1.0"
  },
  "sideEffects": false,
  "publishConfig": {
    "access": "public"
  }
}

package.json (libs > ui > typography):

{
  "name": "@alfabit-alura/typography",
  "version": "2.1.0",
  "peerDependencies": {
    "@angular/common": "^17.3.0",
    "@angular/core": "^17.3.0"
  },
  "sideEffects": false,
  "publishConfig": {
    "access": "public"
  }
}

package.json (libs > ui > storybook-host):

{
  "name": "@alfabit/ds-storybook",
  "version": "0.0.1",
  "sideEffects": false
}

No input, removemos a seção dependencies inteira, pois havia apenas o tslib. Em modal, assim como em button, removemos o pacote tslib das dependências. No typography, também removemos a seção dependencies inteira. Por fim, em storybook-host, removemos tanto a seção dependencies quanto a peerDependencies, pois são desnecessárias.

Executando múltiplas tarefas

Agora, podemos voltar ao terminal e executar novamente o comando nx run-many.

Dica! Podemos usar a seta para cima para resgatar o último comando.

Ao pressionar "Enter", algumas tarefas são executadas a partir do cache. Agora, todas as tarefas foram executadas com sucesso: lint e test para os 5 projetos.

Conclusão

Aprendemos a utilizar o novo comando nx run-many para agilizar algumas etapas do nosso cotidiano como pessoas desenvolvedoras.

No próximo vídeo, vamos conferir como automatizar essas tarefas!

Automatizando com GitHub Actions - Criando primeiro workflow com GitHub Actions

Anteriormente, conhecemos o comando nx run-many para executar várias tarefas de projetos diferentes do monorepo simultaneamente, economizando um tempo valioso no nosso dia a dia.

Agora, vamos imaginar outra situação. Suponha que trabalhamos no time da Alfabit e estamos desenvolvendo um novo componente. Nessa etapa, realizamos o commit do código, fazemos um push para o GitHub, subimos o código e, por fim, compartilhamos com o restante da equipe.

No entanto, esquecemos de executar o comando nx run-many para verificar se o novo código estava correto. Se esquecermos de executar os testes ou o lint, podemos levar um bug para a produção, por exemplo. Para não depender apenas da memória, quais são as alternativas possíveis?

Criando o primeiro workflow

Discutindo sobre esse tipo de problema, vamos abordar bastante a questão da cultura, na metodologia do CI/CD (integração contínua/entrega contínua).

Nessa cultura, está a automação de algumas tarefas para evitar esse tipo de problema, em que esquecemos de executar comandos que a equipe considera essenciais para o fluxo de trabalho.

Criando um arquivo de workflow

Para começar a implementar a automação da execução de comandos no monorepo, utilizaremos o GitHub Actions junto com o Nx. Primeiramente, precisamos criar um arquivo de workflow para ser reconhecido pelo GitHub Actions. O Nx possui um gerador para isso, evitando a necessidade de escrever esse arquivo de workflow do zero.

Executamos esse gerador acessando a aba "Nx Console" no menu à esquerda do VS Code. Na seção de comandos comuns do Nx, encontramos o "Generate (UI)".

Vamos clicar nessa opção e digitar ci-workflow na barra superior. O gerador do plugin @nx/workspace será exibido. Ao teclar "Enter", uma nova tela perguntará o nome do workflow. Manteremos o nome CI, que vem de Continuous Integration. No campo "CI provider", selecionaremos github, pois é o que será utilizado neste curso.

Feito isso, podemos clicar no botão "Generate" no canto superior direito. O terminal abrirá para executar o gerador no monorepo, criará um arquivo na pasta ".github > workflows", chamado ci.yml, e atualizará o tsconfig.base.json.

Analisando o arquivo ci.yml

Agora, vamos abrir o arquivo ci.yml no menu explorador à esquerda para analisá-lo e entender como ele funciona antes de utilizá-lo efetivamente.

ci.yml:

name: CI

on:
  push:
    branches:
      - master
  pull_request:

permissions:
  actions: read
  contents: read

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      # - uses: nrwl/nx-set-shas@v4

      - run: npx nx run-many -t lint test build

Refatorando o código de ci.yml

Na primeira linha, temos o nome do workflow (name), que é CI. Em seguida, a sintaxe on do GitHub Actions indica quando o workflow deve ser acionado.

Atualmente, ele está configurado para ser executado quando houver um push na branch master. No entanto, vamos alterar o nome padrão master para main, que é o nome da nossa branch no repositório, tanto local quanto remoto.

O workflow também está configurado para ser acionado quando houver um pull request (pull_request). Por simplicidade, removeremos essa linha para manter o acionamento apenas em pushes da branch main.

# código omitido

on:
  push:
    branches:
      - main

# código omitido

Abaixo, temos as permissões de leitura e de conteúdo, que são para outras tarefas nas quais não focaremos agora. Na sequência, temos as definições de jobs.

Primeiramente, temos um job chamado main, mas vamos dar um nome mais descritivo a ele. Para isso, adicionaremos a opção name: Test and lint, pois queremos automatizar a execução dos comandos de teste e lint.

# código omitido

jobs:
  main:
    name: Test and lint

# código omitido

Abaixo, runs-on define em qual máquina o workflow será executado: nesse caso, em ubuntu-latest. Em seguida, temos os passos (steps) do workflow.

Os primeiros passos são convencionais e bem utilizados. O primeiro utiliza a actions/checkout@v4 para clonar o código do repositório.

Após o primeiro passo, o segundo faz o setup do Node, utilizando a versão v4. O parâmetro with define a node-version 20 e utiliza o cache do npm.

O próximo passo é executar npm ci, que é o comando clean install do npm, apropriado para ambientes de CI, como o GitHub Actions.

Por fim, executamos o comando npx nx run-many -t lint test --exclude=alfabit, em vez de npx nx affected -t lint test build definido por padrão. É importante manter o npx, pois no GitHub Actions, o Nx não estará instalado globalmente.

# código omitido

- run: npx nx run-many -t lint test --exclude=alfabit

Realizando o commit de ci.yml

Uma vez salvas as alterações, precisamos fazer o commit desse novo arquivo. Para isso, vamos abrir a parte do Git no VS Code e inserir a seguinte mensagem:

ci: adiciona workflow para lint e test

Com isso, o arquivo ci.yml é adicionado, enquanto o tsconfig.base.json não sofre nenhuma alteração. Após clicar no botão "Commit" e confirmar com o VS Code, podemos clicamos no botão "Sync Changes", confirmando novamente o commit.

Isso equivale a executar git commit e git push no terminal.

git commit
git push

Acessando o repositório no GitHub

Agora, vamos abrir o repositório remoto do monorepo no GitHub. Após atualizar a página, surge um círculo laranja ao lado do nome do commit que fizemos push.

Ao clicar nesse círculo, uma frase em inglês informa que alguns cheques não foram completados ainda. O workflow chamado CI está rodando o job Test and lint, acionado no evento de push. Ele está em execução no momento.

À direita, temos o link "Details". Podemos clicar nele para abrir a execução do job. Na interface do GitHub Actions, encontramos a sequência de passos que conferimos anteriormente: o "Set up job", actions/checkout@v4, actions/setup-node@v4, e o comando npm ci.

Finalmente, chegamos à parte mais interessante: o comando npx nx run-many -t lint test --exclude=alfabit. Ele executa o comando e, no terminal, temos a mesma saída que tivemos localmente no computador. Ele executou as 10 tarefas para os nossos 5 projetos e informou que o Nx rodou com sucesso essas tarefas. Após isso, realizou algumas ações de limpeza no repositório.

Expandindo o comando nx run modal:lint, por exemplo, temos a informação de que todos os arquivos passaram no lint. No test do storybook-host, ele não encontrou testes, então passou. Todas as tarefas foram executadas com sucesso.

Conclusão

Conseguimos automatizar a execução das tarefas no push do código na branch main. Dessa forma, começamos a implementar o CI/CD no nosso monorepo!

Sobre o curso Angular e GitHub Actions: aplique CI/CD no seu Design System

O curso Angular e GitHub Actions: aplique CI/CD no seu Design System possui 153 minutos de vídeos, em um total de 54 atividades. Gostou? Conheça nossos outros cursos de Angular em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Angular acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas