Integração com Azure DevOps

Status: prova de conceito validada com dados reais (02/09/2026) — script funcional, testado de ponta a ponta contra o board de verdade (https://dev.azure.com/group-software/PartnerBank). Ainda não está conectado a nenhum gatilho automático do Cypress (ver "O que falta" no fim).

Por que existe

Ideia original: ter uma forma automática de ligar o board do Azure DevOps (onde vivem as Tasks/Bugs/Validations do time) com a suíte Cypress — ler o que precisa ser testado, e eventualmente criar/comentar itens a partir de um resultado de teste. Hoje resolve a parte de "cola" (ler/comentar/criar no Azure); a parte de "julgamento" (decidir sozinho quando algo é um bug novo de verdade, sem alguém pedir) fica pra depois — motivo detalhado em "O que falta".

Onde mora

Autenticação (PAT) — cuidado real já encontrado

Usa Basic Auth (base64(':' + PAT)). Duas coisas que já morderam durante os testes:

  1. A organização restringe criação de PAT por allowlist (Organization Settings → Policies → Restrict personal access token (PAT) creation) — nem todo usuário (mesmo Project Administrator) consegue gerar o próprio token sozinho. Precisa ser adicionado à "Allow list" por quem tem acesso a essa tela.
  2. O PAT usado define de QUEM é a ação — todo comentário/criação aparece no Azure como tendo sido feito pela pessoa dona do token, não de quem rodou o script. Confirmado na prática: um teste usando um PAT específico gerou itens/comentários atribuídos à pessoa dona daquele token, não a quem executou o comando.

O PAT nunca é colado em chat/memória — mesma regra de totpSecret/apiKey do Postman neste projeto.

As 4 funções

lerWorkItem(id) — leitura, sempre segura

Devolve título, tipo, estado, área, sprint, responsável e descrição de um item real. Não muda nada no Azure.

comentarWorkItem(id, texto) — publica, só com confirmação

Posta um comentário. Achado importante: a API do Azure DevOps grava o comentário como format: "html" sempre — ela não converte markdown (**negrito**) sozinha. Quando alguém digita direto na caixa de comentário do site, é o navegador que converte antes de mandar pra API. Mandar **texto** cru pela API faz aparecer literal (**texto**), sem negrito, e quebras de linha simples (\n) colapsam num parágrafo só (HTML ignora \n solto).

formatarComentarioEstruturado({ ... }) — o modelo padrão do time

Monta um comentário já em HTML de verdade, no formato usado pelo time (visto num comentário real do Leonardo): Motivo do retorno / Comportamento esperado / Comportamento encontrado / Passos para reproduzir / Exemplo. Usar esta função em vez de montar a string na mão.

criarWorkItem(tipo, titulo, descricao, camposExtras, opcoes) — publica, só com confirmação

Cria um item novo. tipo precisa ser um dos tipos reais do projeto — confirmado por consulta direta à API (GET .../_apis/wit/workitemtypes): Bug, Task, User Story, Validation, Epic, Feature, entre outros. descricao tem a mesma pegadinha de HTML do comentário. camposExtras aceita qualquer campo (System.IterationPath, System.Tags, etc.). opcoes.paiId cria já vinculado como filho de um item existente.

Sinalização de origem (decisão do usuário, 03/09/2026): todo item criado por este script leva (Cypress) no final do título, sempre — automático, sem precisar pedir a cada vez. Ex.: título "Criação de story automática pelo cypress" vira "Criação de story automática pelo cypress (Cypress)". Objetivo: qualquer pessoa olhando o board consegue distinguir de longe o que veio dessa automação do que foi criado manualmente.

⚠️ Cuidado de hierarquia, achado na prática: o Taskboard do Sprint só renderiza bem 2 níveis (item de backlog — User Story/Bug — na linha de cima, Task como card embaixo). Criar um Bug como filho de uma Task (3º nível) faz a Task sumir da visualização do Taskboard — o vínculo continua correto nos dados (confirmado via API), só a tela não sabe desenhar 3 níveis. Preferir Bug como irmão da User Story (os dois filhos diretos da mesma Story/Feature), não filho da Task.

trocarPai(id, novoPaiId) — publica, só com confirmação

Corrige o pai de um item já criado — remove a relação de hierarquia atual (se tiver) e aponta pra um novo pai. Usado justamente pra corrigir o caso acima (Bug filho de Task → Bug filho de Story).

Fluxo de teste real, ponta a ponta (02/09/2026)

Usando a Task real 25706 ("Não permitir a geração de boletos para conta matriz (administradora)", Sprint 28) como base:

  1. lerWorkItem(25706) — leu título/descrição/estado reais.
  2. Avaliação (manual, eu lendo a descrição): bati com o bug já rastreado em cypress/e2e/casos_de_teste/boletoRegressao.cy.js (path atual — em 02/09/2026, antes da reformulação de 09/09/2026, esse spec morava em regressao/) — "vermelho de propósito" até o produto corrigir.
  3. Rodei boletoRegressao.cy.js de verdade contra homologação: 7 passando, 1 falhando — o cenário do próprio bug ainda falha (API ainda aceita GUID de Administradora, deveria rejeitar). Ou seja: mesmo a Task estando em estado "Testing", a correção não está efetiva em homolog.
  4. comentarWorkItem(25706, ...) — postou esse resultado real na Task (formato antigo, sem formatarComentarioEstruturado — já corrigido pras próximas vezes).
  5. Depois, cadeia de teste isolada pra validar criação + vínculo, sem misturar com a 25706: criarWorkItem('User Story', ...)26922, criarWorkItem('Task', ..., { paiId: 26922 })26923, criarWorkItem('Bug', ..., { paiId: 26923 })26924, depois trocarPai(26924, 26922) pra corrigir a hierarquia (ver aviso do Taskboard acima). Hierarquia final confirmada via API: 26922 → { 26923, 26924 } (Task e Bug como irmãos).

O que falta (de propósito, ainda não construído)