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:
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.
publishConfig
: Essa chave instrui onpm
(ouyarn
) 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"
}
}
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 umPATCH
, ex: 1.0.0 → 1.0.1). -
feat:
para novas funcionalidades (gera umMINOR
, ex: 1.0.0 → 1.1.0). -
BREAKING CHANGE:
no rodapé do commit para mudanças que quebram a compatibilidade (gera umMAJOR
, 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"
]
}
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 }}
Vamos analisar os pontos-chave:
-
permissions
: Concedi as permissões necessárias para que o workflow possa criar releases (contents: write
) e publicar pacotes (packages: write
). -
setup-node
: Configurei o Node.js para usar o registro do GitHub Packages. -
working-directory
: Como meu código-fonte fica em um subdiretórioapp/
, usei essa opção para rodar os comandos no lugar certo. -
env
: Osemantic-release
precisa de um token para autenticar no GitHub e no registro npm. Eu usei osecrets.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
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
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)