Desafio 13: GitHub Packages e Azure Artifacts
Este desafio compara o GitHub Packages e o Azure Artifacts lado a lado.
Habilidades do exame
- Recomendar ferramentas de gerenciamento de pacotes incluindo GitHub Packages e Azure Artifacts
- Projetar e implementar feeds e views de pacotes para pacotes locais e upstream
Cenário
A Contoso Ltd possui 15 microsserviços que compartilham 4 bibliotecas internas (auth-sdk, logging-sdk, data-models e api-contracts). Atualmente, as equipes copiam código-fonte entre repositórios. O VP de Engenharia deseja uma solução centralizada de gerenciamento de pacotes com:
- Hospedagem privada de pacotes
- Verificação de vulnerabilidades em dependências
- Controle de acesso por equipe
- Suporte para pacotes npm e NuGet
Seu trabalho é avaliar tanto o GitHub Packages quanto o Azure Artifacts, configurar cada plataforma e recomendar a melhor opção para o ecossistema multi-linguagem da Contoso.
Tarefas
Tarefa 1: Configurar GitHub Packages (npm)
Passo 1: Criar o projeto da biblioteca
mkdir contoso-auth-sdk && cd contoso-auth-sdk
npm init -y
Edite o package.json para definir o escopo do pacote para sua organização GitHub:
{
"name": "@contoso/auth-sdk",
"version": "1.0.0",
"description": "Contoso internal authentication SDK",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/contoso/auth-sdk.git"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com"
}
}
Passo 2: Configurar autenticação
Crie um arquivo .npmrc na raiz do projeto para apontar para o GitHub Packages:
@contoso:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
Gere um token de acesso pessoal com os escopos read:packages e write:packages:
gh auth token
Ou defina o token como variável de ambiente:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Passo 3: Publicar o pacote
npm publish
Verifique se o pacote existe:
gh api /orgs/contoso/packages/npm/auth-sdk
Passo 4: Consumir o pacote em outro projeto
No repositório do microsserviço consumidor, crie um .npmrc:
@contoso:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
Instale o pacote:
npm install @contoso/auth-sdk
Passo 5: Definir visibilidade e permissões do pacote
Defina o pacote como interno (visível para todos os membros da organização):
gh api --method PUT /orgs/contoso/packages/npm/auth-sdk/visibility \
-f visibility=internal
Conceda acesso de escrita a uma equipe específica:
gh api --method PUT /orgs/contoso/packages/npm/auth-sdk/teams/backend-team \
-f permission=write
Passo 6: Publicar a partir do GitHub Actions
Crie .github/workflows/publish.yml:
name: Publish package
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://npm.pkg.github.com/
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Tarefa 2: Configurar Azure Artifacts (npm e NuGet)
Passo 1: Criar um feed do Azure Artifacts
az artifacts feed create \
--name contoso-packages \
--organization https://dev.azure.com/contoso \
--project ContosoServices \
--scope project
Passo 2: Configurar fontes upstream
Adicione o npmjs.com como fonte upstream para que pacotes públicos sejam proxeados através do seu feed:
az rest --method post \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/upstreamsources?api-version=7.1-preview.1" \
--body '{
"name": "npmjs",
"protocol": "npm",
"location": "https://registry.npmjs.org/",
"upstreamSourceType": "public"
}'
Adicione o upstream do nuget.org:
az rest --method post \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/upstreamsources?api-version=7.1-preview.1" \
--body '{
"name": "nuget.org",
"protocol": "nuget",
"location": "https://api.nuget.org/v3/index.json",
"upstreamSourceType": "public"
}'
Passo 3: Publicar um pacote npm no Azure Artifacts
Configure o .npmrc para o feed do Azure Artifacts:
registry=https://pkgs.dev.azure.com/contoso/ContosoServices/_packaging/contoso-packages/npm/registry/
always-auth=true
//pkgs.dev.azure.com/contoso/ContosoServices/_packaging/contoso-packages/npm/registry/:_authToken=${AZURE_DEVOPS_PAT}
Publique:
npm publish
Passo 4: Publicar um pacote NuGet no Azure Artifacts
Crie uma fonte NuGet:
dotnet nuget add source \
"https://pkgs.dev.azure.com/contoso/ContosoServices/_packaging/contoso-packages/nuget/v3/index.json" \
--name contoso-packages \
--username contoso \
--password $AZURE_DEVOPS_PAT \
--store-password-in-clear-text
Empacote e publique uma biblioteca .NET:
dotnet pack --configuration Release --output ./nupkgs
dotnet nuget push ./nupkgs/*.nupkg \
--source contoso-packages \
--api-key az
Passo 5: Definir permissões do feed
Conceda à equipe backend acesso de contribuidor (pode publicar e consumir):
az rest --method patch \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/permissions?api-version=7.1-preview.1" \
--body '[{
"identityDescriptor": "Microsoft.TeamFoundation.Identity;S-1-9-xxx",
"role": "contributor"
}]'
Funções de feed no Azure Artifacts:
- Reader: Pode consumir pacotes do feed
- Collaborator: Pode consumir pacotes e salvar pacotes de fontes upstream
- Contributor: Pode publicar novos pacotes e versões
- Owner: Controle total incluindo exclusão do feed e gerenciamento de permissões
Passo 6: Criar views (pré-lançamento e lançamento)
az rest --method post \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/views?api-version=7.1-preview.1" \
--body '{
"name": "prerelease",
"type": "implicit",
"visibility": "private"
}'
az rest --method post \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/views?api-version=7.1-preview.1" \
--body '{
"name": "release",
"type": "implicit",
"visibility": "organization"
}'
Promova uma versão de pacote para a view de release:
az rest --method post \
--uri "https://pkgs.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/npm/@contoso/auth-sdk/versions/1.0.0?api-version=7.1-preview.1" \
--body '{
"views": { "op": "add", "path": "/views/-", "value": "release" }
}'
Tarefa 3: Configurar fontes upstream
Fontes upstream permitem que seu feed privado faça proxy de registros públicos. Quando um desenvolvedor solicita um pacote que não existe localmente, o feed o busca na fonte upstream configurada e o armazena em cache.
Passo 1: Entender o comportamento das fontes upstream
- Primeira solicitação: O pacote é buscado do upstream e salvo no feed local
- Solicitações subsequentes: O pacote é servido do cache do feed local
- Se o upstream ficar offline, os pacotes em cache permanecem disponíveis
- Novas versões do upstream são buscadas sob demanda
Passo 2: Configurar ordem de prioridade
Fontes upstream são avaliadas em ordem de prioridade. Coloque seu feed interno primeiro para que pacotes internos tenham precedência sobre pacotes públicos com o mesmo nome:
az rest --method patch \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages?api-version=7.1-preview.1" \
--body '{
"upstreamSources": [
{
"name": "contoso-shared",
"protocol": "npm",
"location": "https://pkgs.dev.azure.com/contoso/_packaging/shared-libs/npm/registry/",
"upstreamSourceType": "internal"
},
{
"name": "npmjs",
"protocol": "npm",
"location": "https://registry.npmjs.org/",
"upstreamSourceType": "public"
}
]
}'
Passo 3: Testar a resolução upstream
Instale um pacote público através do seu feed:
npm install lodash --registry https://pkgs.dev.azure.com/contoso/ContosoServices/_packaging/contoso-packages/npm/registry/
Verifique se ele foi armazenado em cache no seu feed consultando o conteúdo do feed no Azure DevOps ou via API:
az rest --method get \
--uri "https://feeds.dev.azure.com/contoso/ContosoServices/_apis/packaging/feeds/contoso-packages/npm/packages?api-version=7.1-preview.1"
Exercícios de quebra e conserto
Cenário: Publicação de pacote falha com 403
Um desenvolvedor relata que não consegue publicar no GitHub Package Registry. O erro é:
npm ERR! 403 Forbidden - PUT https://npm.pkg.github.com/@contoso/auth-sdk
Diagnostique e corrija o problema. Causas comuns:
- Permissão
packages: writeausente no workflow - Nome do pacote não corresponde ao escopo do proprietário do repositório
.npmrcapontando para o registro errado- Token não possui o escopo
write:packages
Mostrar solução
Causa 1: Permissões ausentes no workflow do GitHub Actions
O arquivo de workflow deve declarar explicitamente permissões de escrita de pacotes:
permissions:
contents: read
packages: write
Sem isso, o GITHUB_TOKEN assume permissão somente leitura para pacotes em workflows acionados por pull requests de forks.
Causa 2: Incompatibilidade de escopo do pacote
O GitHub Packages exige que o escopo do pacote (@contoso/) corresponda ao proprietário do repositório. Verifique o nome do pacote:
cat package.json | grep name
# Deve retornar: "@contoso/auth-sdk" onde "contoso" corresponde à org/usuário dono do repo
Corrija atualizando o package.json:
{
"name": "@contoso/auth-sdk"
}
Causa 3: Configuração incorreta do .npmrc
Verifique qual registro o npm está usando:
npm config get registry
cat .npmrc
Certifique-se de que o .npmrc contenha:
@contoso:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
Causa 4: Token sem os escopos necessários
Verifique os escopos do token:
gh auth status
Se estiver usando um PAT clássico, regenere com o escopo write:packages. Se estiver usando um PAT de granularidade fina, certifique-se de que o token tenha permissões de escrita de pacotes para o repositório alvo.
Para testar com um token novo:
gh auth refresh --scopes write:packages,read:packages
export GITHUB_TOKEN=$(gh auth token)
npm publish
Verificação de conhecimento
1. Quais tipos de pacote o GitHub Packages suporta?
2. Qual é o número máximo de fontes upstream em um único feed do Azure Artifacts?
3. Uma empresa precisa de verificação de vulnerabilidades de pacotes integrada ao pipeline. Qual solução oferece isso nativamente?
4. O que acontece quando um pacote em uma fonte upstream do Azure Artifacts é consumido pela primeira vez?
Limpeza
Remova o pacote do GitHub:
gh api --method DELETE /orgs/contoso/packages/npm/auth-sdk
Se a exclusão por versão for necessária:
# List versions
gh api /orgs/contoso/packages/npm/auth-sdk/versions
# Delete a specific version
gh api --method DELETE /orgs/contoso/packages/npm/auth-sdk/versions/PACKAGE_VERSION_ID
Exclua o feed do Azure Artifacts:
az artifacts feed delete \
--name contoso-packages \
--organization https://dev.azure.com/contoso \
--project ContosoServices \
--yes
Remova a configuração local do npm:
rm .npmrc
dotnet nuget remove source contoso-packages
Remova os diretórios locais do projeto:
rm -rf contoso-auth-sdk