← Blog

Templates do Azure Pipelines para MuleSoft: um fluxo de entrega, muitas aplicações

Referência: azure-devops-mulesoft-pipelines (templates, ADRs) · mulesoft-orders-api (consumidor)

Um time com trinta aplicações Mule não deveria ter trinta cópias do mesmo pipeline. Quando o processo de entrega muda — uma checagem nova, um ambiente novo, uma correção como a do artigo anterior — ele deve mudar num lugar só, e cada aplicação escolhe quando adotar a mudança. Os templates do Azure Pipelines permitem isso, desde que o repositório esteja organizado para isso.

Dois repositórios

  • Repositório de templates — o processo de entrega. Versionado com tags (v1.0.0, v1.0.1, v1.1.0).
  • Repositório da aplicação — a app Mule e um azure-pipelines.yml de dez linhas que estende uma versão com tag dos templates.
resources:
  repositories:
  - repository: templates
    type: github
    endpoint: github.com_brunosouzas
    name: brunosouzas/azure-devops-mulesoft-pipelines
    ref: refs/tags/v1.1.0

extends:
  template: templates/stages/gitflow.yml@templates
  parameters:
    nextVersionBump: minor

Fixar numa tag é a parte importante. Uma mudança nos templates nunca altera o pipeline de uma aplicação até ela mudar o ref. Durante este projeto, o job de release foi corrigido na v1.0.1 e um smoke test entrou na v1.1.0; a aplicação adotou cada uma por um pull request normal.

Usar extends, e não template: dentro de stages:, é proposital: a aplicação não consegue acrescentar passos antes ou depois do fluxo governado, o que importa quando os templates carregam controles que todo mundo precisa rodar.

Organização dos templates

templates/
  stages/gitflow.yml         ponto de entrada: quais stages rodam, a partir do branch
  jobs/ci.yml                build e empacotamento
  jobs/publish-snapshot.yml  develop → Exchange
  jobs/release.yml           Maven release na main
  jobs/deploy.yml            deploy de uma versão do Exchange no CloudHub 2.0
  steps/setup-maven.yml      Java 17, cache do Maven, settings.xml
docs/adr/                    os motivos de cada escolha

Stages decidem quando, jobs decidem o quê, steps são as peças reutilizáveis. Decisões que ficariam na cabeça de alguém — por que o release roda na main, por que nada é reconstruído por ambiente — viram ADRs ao lado do código.

Segredos sem secure files

O Maven precisa de credenciais para o Exchange. Uma abordagem comum guarda um settings.xml inteiro como secure file. Os templates geram o arquivo durante a execução, a partir de um variable group:

- bash: |
    cat > "${SETTINGS_PATH}" <<XML
    <settings>
      <servers>
        <server>
          <id>anypoint-exchange-v3</id>
          <username>~~~Client~~~</username>
          <password>${ANYPOINT_CLIENT_ID}~?~${ANYPOINT_CLIENT_SECRET}</password>
        </server>
      </servers>
    </settings>
    XML
  env:
    ANYPOINT_CLIENT_ID: $(ANYPOINT_CLIENT_ID)
    ANYPOINT_CLIENT_SECRET: $(ANYPOINT_CLIENT_SECRET)

~~~Client~~~ com clientId~?~clientSecret é a forma de o Exchange aceitar um Connected App no lugar de um usuário. O Connected App precisa de Exchange Contributor, dos escopos de deploy do Runtime Manager e de acesso a cada ambiente de destino. O segredo fica no variable group vg-00-anypoint-platform, marcado como secreto, então aparece mascarado nos logs — e variáveis secretas precisam ser mapeadas explicitamente em env, como acima.

Por que o MUnit não está neste pipeline

O MUnit roda no runtime Enterprise do Mule, que o Maven baixa do repositório Enterprise da MuleSoft. O acesso vem com a assinatura de cliente, e as credenciais pertencem a esse cliente.

Este é um projeto pessoal e público. Eu poderia ter usado as credenciais de um empregador — protegidas num secure file, ninguém as veria —, mas isso seria usar a licença dele fora do negócio dele. Então o pipeline faz o build com -DskipMunitTests, o MUnit roda localmente antes de cada pull request (mvn clean test, seis testes, 100% de cobertura) e o template de PR pede essa verificação. Num pipeline de empresa, a mudança são duas linhas: fornecer as credenciais do repositório Enterprise e tirar a flag. O ADR 4 registra a decisão.

Vale confirmar que o resto funciona sem essas credenciais. Empacotar a app com um settings.xml vazio e um repositório Maven local vazio dá certo: só o MUnit precisa do repositório Enterprise.

Uma falha enganosa do MUnit

Ao escrever os testes locais, a suíte se recusou a subir. O primeiro erro do log era:

[global.xml:15]: Connection is not secure. Should use `HTTPS`

Isso é um aviso das validações do conector HTTP, e aparece também em projetos saudáveis. O erro real estava na linha seguinte: um teste chamado create-order, com o mesmo nome de um flow. Os testes MUnit compartilham o namespace global da aplicação. Com prefixo nos nomes dos testes (test-create-order), a suíte roda.

Projeto privado, evidência pública

A Microsoft não permite mais que esta organização crie projetos públicos no Azure DevOps, então o projeto é privado. A evidência continua pública: cada execução é reportada ao GitHub como um check no commit ou no pull request, e os badges de status no README podem ser lidos sem login.

Checklist

  • O pipeline de cada aplicação é um extends enxuto de uma versão com tag dos templates?
  • Os templates podem mudar sem alterar silenciosamente todas as aplicações?
  • As credenciais são geradas durante a execução, a partir de variáveis secretas mapeadas explicitamente em env?
  • As decisões por trás dos templates estão escritas ao lado deles?