Pipeline CI com Validação


Laboratório 1 – Primeiro Pipeline CI com Validação
Cenário: Um time começa a usar Azure DevOps para um app Node.js.
Tarefas:
Criar pipeline YAML com
npm install
,lint
,test
,build
.Criar stage de Instalação e Build
Exibir badges de status no repositório.
Validação de PRs com lint + testes.
Usar cache
Publicar artefato no Pipeline Artifact
Publicar o artefato no Azure Artifact
Desafio real: Automatizar o mínimo necessário para evitar que código quebrado entre na main.
Pré requisitos
- Azure Devops Account
1️⃣ Step 1: Criar e clonar o Repositório
Criar Novo Projeto:
Ao entrar no painel do Azure DevOps da sua organização, clique no botão "Novo Projeto", geralmente no canto superior direito ou no centro da tela.
Configurar Detalhes do Projeto:
Nome do Projeto: Insira "Projeto Pessoal" como nome do projeto.
- Acesse Repositórios -> Importar Repositório -> Clonar URL: https://github.com/joaochiroli/Devops-Challenge
- Como a intenção é começar um projeto novo do zero e testar algumas habilidades iremos excluir o conteúdo que está no arquivo azure-pipelines.yml
2️⃣ Step 2: Criar pipeline YAML (azure-pipelines.yml
) na branch feature
Criar a Branch feature
- Clique na branch main → clique em seguida em new branch → crie a branch feature
Criar Pipeline:
Vá até a aba Pipelines → Criar Pipeline → Integre sua Pipeline com o Azure Repos
Crie o arquivo
azure-pipelines.yml
:
trigger: none
pr:
branches:
include:
- main
stages:
# Instala, Valida e Publica o Código
- stage: InstallAndValidate
displayName: Install And Validate
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: InstallAndValidate
displayName: 'InstallAndValidate'
steps:
- checkout: self
path: 'src'
displayName: 'Checkout code'
- task: UseNode@1
inputs:
version: '15.x'
displayName: 'Install Node.js'
- task: Cache@2
inputs:
key: 'npm | "$(Agent.OS)" | $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0/package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Cache node_modules'
- script: npm ci
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Install dependencies with ci'
- script: npm run lint
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Linter (ESLint)'
- script: |
npm install --save-dev prettier
npm run prettier
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Formatter (Prettier)'
continueOnError: true
- script: CI=true npm run test
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Test (Jest) CI=true'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
artifact: 'validated-source'
publishLocation: 'pipeline'
displayName: 'Validated Source'
Tarefas:
Criar pipeline YAML com npm install, lint, test, build ✅
Criar stage de Instalação e Build ✅
Exibir badges de status no repositório ❗
Validação de PRs com lint + testes ❗
Usar cache ✅
Publicar artefato no Pipeline Artifact ✅
Publicar o artefato no Azure Artifact❗
3️⃣ Configurar Validação de Pull Request
A configuração pr:
no YAML já cuida disso, mas você pode reforçar no portal:
Vá para o repositório → Branches
Clique no botão
...
ao lado da branchmain
→ Branch policiesAtive:
✔️ Require a minimum number of reviewers
✔️ Check for linked work items
✔️ Build validation → Selecione o pipeline YAML criado (deixe como obrigatório
Tarefas:
Criar pipeline YAML com
npm install
,lint
,test
,build
✅Criar stage de Instalação e Build ✅
Exibir badges de status no repositório ❗
Validação de PRs com lint + testes ✅
Usar cache ✅
Publicar artefato no Pipeline Artifact ✅
Publicar o artefato no Azure Artifact❗
4️⃣ Exibir badges de status no repositório
Vá em Pipelines → clique no pipeline → ⚙️
View YAML
→ Copie o Status Badge MarkdownAdicione ao seu
README.md
:
mdCopiarEditar
Depois de adicionar no README.md basta fazer o commit:
Tarefas:
Criar pipeline YAML com
npm install
,lint
,test
,build
✅Criar stage de Instalação e Build ✅
Exibir badges de status no repositório ✅
Validação de PRs com lint + testes ✅
Usar cache ✅
Publicar artefato no Pipeline Artifact ✅
Publicar o artefato no Azure Artifact❗
5️⃣ Publicar o artefato no Azure Artifact
Criar um Azure Artifacts feed no seu projeto DevOps com o nome Projeto Pessoal
Adicionar a seguinte task no seu arquivo
azure-pipelines.yml
:
- task: UniversalPackages@0
inputs:
command: 'publish'
publishDirectory: '$(Build.ArtifactStagingDirectory)'
feedsToUsePublish: 'internal'
vstsFeedPublish: 'ee03fcac-046a-4290-b5f4-79508dd47b04/82dd1496-0532-4c69-b3e0-feb482096c20'
vstsFeedPackagePublish: 'validated-source'
versionOption: 'patch'
Detalhe o vstsFeedPublish é o ID do meu feed no Azure Artifact ou seja, no seu caso será uma ID diferente.
Agora salva e executa sua pipeline.
No meu caso, tive o seguinte problema: User 'b83dcc85-38ca-4958-b336-c89e9ffbca0d' lacks permission to complete this action. You need to have 'AddPackage'.","@i":"c2baee9b","@l":"Error","SourceContext":"ArtifactTool.Program","UtcTimestamp":"2025-05-19 17:05:49.785Z"})
- Neste caso vá até seu feed → Clique na engrenagem no canto superior direito → Permissão → Add User/Group → Contributor → <Nome_do_Projeto_Service_Build>
Execute sua pipeline e você irá encontrar um novo artefato gerado no seu feed, neste caso é um artefato de patch mas você pode alterar esta opção.
Esta publicação é incremental, ou seja, cada nova execução irá gerar um novo artefato.
Tarefas:
Criar pipeline YAML com
npm install
,lint
,test
,build
✅Criar stage de Instalação e Build ✅
Exibir badges de status no repositório ✅
Validação de PRs com lint + testes ✅
Usar cache ✅
Publicar artefato no Pipeline Artifact ✅
Publicar o artefato no Azure Artifact ✅
6️⃣ Merge com a branch main
Agora só basta ir até Azure Repos → Pull Request → Aprovar a PR e fazer o Merge com a branch main
- Arquivo
azure-pipelines.yml
completo:
- Arquivo
trigger: none
pr:
branches:
include:
- main
stages:
# Instala, Valida e Publica o Código
- stage: InstallAndValidate
displayName: Install And Validate
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: InstallAndValidate
displayName: 'InstallAndValidate'
steps:
- checkout: self
path: 'src'
displayName: 'Checkout code'
- task: UseNode@1
inputs:
version: '15.x'
displayName: 'Install Node.js'
- task: Cache@2
inputs:
key: 'npm | "$(Agent.OS)" | $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0/package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Cache node_modules'
- script: npm ci
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Install dependencies with ci'
- script: npm run lint
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Linter (ESLint)'
- script: |
npm install --save-dev prettier
npm run prettier -- --write
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Formatter (Prettier)'
continueOnError: true
- script: CI=true npm run test
workingDirectory: $(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0
displayName: 'Test (Jest) CI=true'
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
artifact: 'build-artifact'
publishLocation: 'pipeline'
displayName: 'Validated Source'
- task: UniversalPackages@0
inputs:
command: 'publish'
publishDirectory: '$(Build.ArtifactStagingDirectory)'
feedsToUsePublish: 'internal'
vstsFeedPublish: 'ee03fcac-046a-4290-b5f4-79508dd47b04/82dd1496-0532-4c69-b3e0-feb482096c20'
vstsFeedPackagePublish: 'validated-source'
versionOption: patch
7️⃣ Bônus - Publicar o artefato no Azure Artifact no formato .npmrc
- Vá até o arquivo .npmrc na raiz do projeto e coloque as seguintes informações de acordo com o seu feed:
registry=https://pkgs.dev.azure.com/joaochiroli123/ee03fcac-046a-4290-b5f4-79508dd47b04/_packaging/ProjetoPessoal/npm/registry/
engine-strict=true
- Altere também
azure-pipelines.yml
:
- task: Npm@1
inputs:
command: 'publish'
workingDir: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
publishRegistry: 'useFeed'
publishFeed: 'ee03fcac-046a-4290-b5f4-79508dd47b04/82dd1496-0532-4c69-b3e0-feb482096c20'
Execute a Pipeline
Provavelmente vai dar um erro dizendo que o arquivo package.json está com uma flag private habilitada o que você pode fazer é adicionar o script abaixo que irá remover o private do seu arquivo de configuração:
- script: |
echo "🔧 Removendo 'private' de package.json após o npm ci"
sed -i '/"private": true,/d' package.json
cat package.json
workingDirectory: '$(Build.SourcesDirectory)/assessment-cc-sre-kubernetes-sr-01/codebase/rdicidr-0.1.0'
displayName: '🔧 Remoção do campo private após instalação'
- Execute a pipeline
Observação: Quando você realiza a publicação de pacotes do tipo npm no Azure Artifacts, o processo é diferente da publicação via Universal Packages.
No caso do npm, o Azure utiliza a versão definida no arquivo
package.json
. Isso significa que, se a versão0.1.3
já tiver sido publicada no feed, será necessário atualizar opackage.json
para0.1.4
(ou superior) para que a nova publicação seja aceita. Caso contrário, a pipeline falhará com erro de versão duplicada.Para evitar esse tipo de falha, você pode alterar o valor da versão manualmente ou automatizar a atualização da versão dentro da própria pipeline, utilizando comandos como
npm version patch
. Essa abordagem garante um controle incremental e contínuo das versões publicadas, evitando conflitos.Exemplo de script incremental:
- script: | echo "Versão atual:" node -p "require('./package.json').version" npm version patch --no-git-tag-version echo "Nova versão:" node -p "require('./package.json').version" workingDirectory: $(Pipeline.Workspace)/validated-source displayName: 'Incrementar versão patch no package.json'
Subscribe to my newsletter
Read articles from João Chiroli directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
