Pipeline CI com Validação

João ChiroliJoão Chiroli
7 min read

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

  1. Criar Novo Projeto:

  2. 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.

  3. Configurar Detalhes do Projeto:

  4. Nome do Projeto: Insira "Projeto Pessoal" como nome do projeto.

  1. Acesse Repositórios -> Importar Repositório -> Clonar URL: https://github.com/joaochiroli/Devops-Challenge

  1. 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

  1. Criar a Branch feature

    1. Clique na branch main → clique em seguida em new branch → crie a branch feature
  2. Criar Pipeline:

    1. Vá até a aba Pipelines → Criar Pipeline → Integre sua Pipeline com o Azure Repos

    2. 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:

  1. Vá para o repositório → Branches

  2. Clique no botão ... ao lado da branch mainBranch policies

  3. Ative:

    • ✔️ Require a minimum number of reviewers

    • ✔️ Check for linked work items

    • ✔️ Build validation → Selecione o pipeline YAML criado (deixe como obrigatório

  1. 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

  1. Vá em Pipelines → clique no pipeline → ⚙️ View YAML → Copie o Status Badge Markdown

  2. Adicione ao seu README.md:

mdCopiarEditar![Build Status](https://dev.azure.com/<organization>/<project>/_apis/build/status/<pipeline-name>?branchName=main)
  1. Depois de adicionar no README.md basta fazer o commit:

  2. 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

  1. Criar um Azure Artifacts feed no seu projeto DevOps com o nome Projeto Pessoal

  2. 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'
  1. Detalhe o vstsFeedPublish é o ID do meu feed no Azure Artifact ou seja, no seu caso será uma ID diferente.

  2. Agora salva e executa sua pipeline.

  3. 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"})

    1. Neste caso vá até seu feed → Clique na engrenagem no canto superior direito → Permissão → Add User/Group → Contributor → <Nome_do_Projeto_Service_Build>
  4. 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.

  5. Esta publicação é incremental, ou seja, cada nova execução irá gerar um novo artefato.

  6. 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

  1. Agora só basta ir até Azure Repos → Pull Request → Aprovar a PR e fazer o Merge com a branch main

    1. Arquivo azure-pipelines.yml completo:
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

  1. 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
  1. 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'
  1. Execute a Pipeline

  2. 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'
  1. Execute a pipeline

  1. 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ão 0.1.3 já tiver sido publicada no feed, será necessário atualizar o package.json para 0.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'
    
0
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

João Chiroli
João Chiroli