DEV Community

Cover image for Como Automatizei a Publicação de Pacotes no GitHub Packages
Marcos Vilela
Marcos Vilela

Posted on

Como Automatizei a Publicação de Pacotes no GitHub Packages

Publicar pacotes manualmente é um ritual que pode ser moroso: atualizar a versão no package.json, gerar um changelog, criar uma tag no Git, fazer o build e, finalmente, rodar npm publish. É um processo repetitivo, demorado e, pior de tudo, propenso a erros humanos. Um número de versão errado aqui, um passo esquecido ali, e a confusão estava feita.

Tive essa nova demanda, tarefa. Meu objetivo era simples: ao fazer um merge para a branch main, eu queria que um robô analisasse minhas mudanças, definisse a nova versão, publicasse o pacote no GitHub Packages e criasse uma release bonita, tudo sem intervenção manual.

Neste artigo, vou compartilhar a jornada e o passo a passo de como construí essa automação usando GitHub Actions e Semantic Release.

Passo 1: Preparando o Terreno no package.json

O primeiro passo foi garantir que meu package.json estivesse pronto para a automação e para o GitHub Packages. Duas seções foram cruciais:

  1. Nome com Escopo: Para publicar em um registro privado de uma organização no GitHub, o nome do pacote precisa ter o escopo da organização.

  2. publishConfig: Essa chave instrui o npm (ou yarn) a publicar o pacote no registro correto (o do GitHub Packages) em vez do registro público do npm.

Meu package.json ficou assim:

{
  "name": "@my-org/meu-pacote-incrivel",
  "version": "0.0.0-semver-placeholder",
  "description": "Um pacote que faz coisas incríveis.",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/my-org/meu-pacote-incrivel.git"
  },
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/",
    "access": "restricted"
  }
}
Enter fullscreen mode Exit fullscreen mode

Note o version. Eu o deixei com um placeholder porque o semantic-release cuidaria de atualizá-lo para mim.

Passo 2: O Cérebro da Operação - Semantic Release

O semantic-release é a ferramenta mágica que automatiza todo o processo de versionamento e criação de releases. Ele funciona lendo as mensagens dos seus commits para decidir se a próxima versão será um MAJOR, MINOR ou PATCH, seguindo as regras do Versionamento Semântico.

Para isso, precisei adotar o padrão Conventional Commits. A regra é simples:

  • fix: para correções de bugs (gera um PATCH, ex: 1.0.0 → 1.0.1).
  • feat: para novas funcionalidades (gera um MINOR, ex: 1.0.0 → 1.1.0).
  • BREAKING CHANGE: no rodapé do commit para mudanças que quebram a compatibilidade (gera um MAJOR, ex: 1.0.0 → 2.0.0).

Criei um arquivo .releaserc na raiz do projeto para configurar o semantic-release:

{
  "branches": [
    "main",
    {
      "name": "staging",
      "prerelease": true,
      "channel": "next"
    }
  ],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/github"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Essa configuração diz ao semantic-release para criar releases estáveis a partir da main e pré-releases a partir da staging.

Passo 3: A Esteira de Produção com GitHub Actions

Com o projeto configurado, era hora de criar o workflow do GitHub Actions. Criei um arquivo em .github/workflows/main-workflow.yml que é acionado a cada push na branch main.

O job de publicação é o coração do processo:

# .github/workflows/main-workflow.yml
name: main-workflow

on:
  push:
    branches:
      - main

jobs:
  publish:
    name: Publish Package
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
      issues: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          registry-url: 'https://npm.pkg.github.com'

      - name: Install dependencies
        run: npm install
        working-directory: ./app

      - name: Build package
        run: npm run build
        working-directory: ./app

      - name: Run semantic-release
        run: npx semantic-release
        working-directory: ./app
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Vamos analisar os pontos-chave:

  1. permissions: Concedi as permissões necessárias para que o workflow possa criar releases (contents: write) e publicar pacotes (packages: write).
  2. setup-node: Configurei o Node.js para usar o registro do GitHub Packages.
  3. working-directory: Como meu código-fonte fica em um subdiretório app/, usei essa opção para rodar os comandos no lugar certo.
  4. env: O semantic-release precisa de um token para autenticar no GitHub e no registro npm. Eu usei o secrets.GITHUB_TOKEN, que é um token gerado automaticamente pelo GitHub Actions para cada execução do workflow.

Passo 4: Consumindo o Pacote Publicado

Com o pacote publicado, o último passo era usá-lo em outro projeto. Como o pacote é privado para a minha organização, precisei configurar o projeto consumidor para se autenticar no registro do GitHub Packages.

Para isso, criei um arquivo .npmrc na raiz do projeto consumidor:

@my-org:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=SEU_GITHUB_TOKEN
Enter fullscreen mode Exit fullscreen mode

O SEU_GITHUB_TOKEN deve ser um Personal Access Token (PAT) com a permissão read:packages.

Depois disso, instalar o pacote foi tão simples quanto rodar:

npm install @my-org/meu-pacote-incrivel
Enter fullscreen mode Exit fullscreen mode

O que antes era um processo manual e estressante, agora é um fluxo contínuo, confiável e totalmente automatizado. Cada feat ou fix que chega na main se transforma em uma nova versão publicada, sem que eu precise mover um dedo.

Se você ainda publica pacotes manualmente, eu o encorajo fortemente a investir um tempo para automatizar esse processo. A paz de espírito e o tempo que você economiza para focar no que realmente importa – codificar – valem cada minuto do esforço inicial.

Top comments (0)