La branca main de Contoso ja està protegida per directives, però una d'elles apunta al buit: la compilació amb validació exigeix que una canalització doni el vistiplau abans de fusionar, i aquesta canalització encara no existeix. Sense ella, les altres directives comproven formalitats —hi ha dues aprovacions, hi ha un element de treball vinculat— però ningú no ha verificat el més elemental: que el codi compila i que les proves passen.

Aquesta lliçó construeix aquest verificador. Azure Pipelines executa, a cada canvi proposat i a cada fusió, la mateixa seqüència repetible de restaurar, compilar, provar, analitzar i empaquetar. El resultat és un artefacte —el paquet exacte que després es desplegarà— i un veredicte binari en pocs minuts. Aquí ens ocupem només de construir i verificar; portar aquest artefacte a Azure és la lliçó següent.

Contingut

  1. Què és la integració contínua i quin problema elimina
  2. Agents, grups i els seus costos reals
  3. Canalitzacions YAML davant de les clàssiques per interfície
  4. Anatomia d'un azure-pipelines.yml, línia a línia
  5. Les tasques imprescindibles i la memòria cau de dependències
  6. Variables, grups de variables i Key Vault
  7. Plantilles de canalització reutilitzables
  8. Validació de sol·licituds de canvi i matriu de treballs
  9. Artefactes, diagnòstic d'errades i insígnia d'estat
  10. Errors Comuns i Consells
  11. Exercicis
  12. Conclusió

  1. Què és la integració contínua i quin problema elimina

La integració contínua consisteix a fer que cada canvi s'integri amb la feina de tothom i es verifiqui automàticament, diverses vegades al dia. No és «tenir un servidor de compilació»: és una disciplina en què el codi de tothom es junta constantment en lloc d'acumular-se en racons separats.

El problema que elimina té nom: l'infern de la integració. En Diego treballa tres setmanes en el mapa de cabina mentre un altre company refactoritza el model de tarifes; cadascun prova al seu portàtil i tot funciona. En ajuntar-ho apareixen conflictes, incompatibilitats de signatura i una errada que ningú no sap atribuir, justament el divendres del lliurament. El cost d'integrar creix de manera no lineal amb el temps que es triga a fer-ho, i d'aquí la conclusió contraintuïtiva: si integrar fa mal, fes-ho més vegades.

Requisit Què significa Com ho compleix Contoso
Un repositori compartit Una única font de veritat Azure Repos (05-02)
Compilació automàtica Ningú no compila a mà per validar Aquesta canalització
Proves automàtiques El veredicte és objectiu, no una opinió Proves unitàries amb cobertura
Realimentació ràpida Menys de 10 minuts Memòria cau, paral·lelisme, proves ràpides

La regla cultural que ho sosté: si la compilació de main es trenca, arreglar-la és la prioritat número u de l'equip. Una compilació trencada que es tolera durant dies converteix la canalització en soroll que tothom ignora.

  1. Agents, grups i els seus costos reals

Un agent és la màquina que executa els passos. Hi ha dues modalitats, i triar malament costa diners o directament impedeix desplegar:

Agents allotjats per Microsoft Agents autoallotjats
Qui els manté Microsoft Tu
Estat entre execucions Màquina nova i neta sempre Persisteix: memòria cau ràpida, però també brossa
Programari preinstal·lat Catàleg ampli (SDK, Docker, Node) El que instal·lis
Accés a vnet-contoso-pro No Sí
Temps màxim per treball 60 min (gratuït) / 360 min (de pagament) Sense límit
Cost Minuts gratuïts i després per treball paral·lel La VM més el seu manteniment

Avís de cost real: un projecte privat té 1 treball paral·lel allotjat amb 1.800 minuts al mes gratuïts. Un cop esgotats, les execucions es posen a la cua fins al mes següent o cal comprar treballs paral·lels addicionals (uns 40 $/mes cadascun). Els projectes públics tenen 10 treballs paral·lels gratuïts i il·limitats en minuts, cosa que fa venir la temptació de fer públic un repositori: no ho facis per estalviar. Amb agents autoallotjats, el primer treball paral·lel és gratuït i els següents costen uns 15 $/mes, però pagues la màquina virtual i el seu manteniment.

Contoso necessita tots dos. La canalització de compilació (aquesta lliçó) va en agents allotjats: no toca res privat i aprofita imatges sempre actualitzades. La canalització de desplegament (05-04) que actua contra sql-contoso-reservas-pro necessita ser dins de vnet-contoso-pro, perquè aquest servidor ja només és accessible per pe-sql-reservas des que el vam tancar a 02-05: aquí cal un agent autoallotjat a snet-gestion, agrupat al grup pool-contoso-privado.

# Instal.lar un agent autoallotjat en una VM Linux dins de snet-gestion
mkdir ~/agent && cd ~/agent
curl -O https://vstsagentpackage.azureedge.net/agent/3.243.1/vsts-agent-linux-x64-3.243.1.tar.gz
tar zxvf vsts-agent-linux-x64-3.243.1.tar.gz
./config.sh --unattended --url https://dev.azure.com/contoso-airlines \
  --auth pat --token $PAT_AGENT --acceptTeeEula \
  --pool pool-contoso-privado --agent agente-contoso-01
sudo ./svc.sh install && sudo ./svc.sh start   # Servei, per sobreviure als reinicis

La VM de l'agent s'ha d'autenticar contra Azure amb identitat administrada, no amb credencials guardades: el mateix criteri del mòdul 4.

  1. Canalitzacions YAML davant de les clàssiques per interfície

YAML Clàssica (interfície gràfica)
On viu la definició Al repositori, al costat del codi A la base de dades d'Azure DevOps
Versionat i reversió Amb Git: història i branques No versionat
Revisió A la sol·licitud de canvis, com el codi Ningú no revisa un clic
Reutilització Plantilles Grups de tasques
Estat Recomanada Heretada, sense novetats

L'argument decisiu és el primer: si la canalització viu al repositori, un canvi en la manera de compilar passa per la mateixa revisió que un canvi de codi, queda registrat i es pot revertir. Amb la clàssica, algú modifica un pas un dimarts a la tarda, la compilació comença a comportar-se diferent i no hi ha història per consultar. Contoso fa servir YAML exclusivament.

  1. Anatomia d'un azure-pipelines.yml, línia a línia

Aquesta és la canalització contoso-reservas-ci, a l'arrel del repositori:

# Numero de compilacio de cada execucio; disponible com a $(Build.BuildNumber).
# Que hi consti la versio es el que permetra versionar paquets a 05-05.
name: 2.5.$(Date:yyyyMMdd)$(Rev:.r)

trigger:                    # Quins ENVIAMENTS llancen la canalitzacio
  branches:
    include: [ main, releases/* ]
  paths:
    exclude: [ docs/*, README.md ]   # No gastar minuts per canvis de documentacio

pr:                         # Quines SOL.LICITUDS de canvi la llancen: enganxa amb
  branches:                 # la directiva de compilacio amb validacio de 05-02
    include: [ main ]

schedules:                  # Compilacio nocturna: detecta trencaments que no venen
  - cron: "0 2 * * *"       # del teu codi (una dependencia actualitzada, una altra imatge)
    displayName: Compilacio nocturna
    branches: { include: [ main ] }
    always: true            # Executar encara que no hi hagi hagut canvis

pool:
  vmImage: ubuntu-latest    # Agent allotjat per Microsoft

variables:
  - group: vg-contoso-reservas-comun    # Grup de variables compartit (apartat 6)
  - name: rutaSolucio
    value: 'src/Contoso.Reservas.sln'

stages:
  - stage: compilacio
    jobs:
      - job: compilar
        timeoutInMinutes: 20            # Talla l execucio si alguna cosa es penja
        steps:
          - checkout: self
            fetchDepth: 1               # Clon superficial: mes rapid
          - task: UseDotNet@2           # No depenguis del que porti la imatge
            inputs: { packageType: sdk, version: '8.0.x' }
          - script: dotnet restore $(rutaSolucio)
            displayName: Restaurar dependencies
          - script: dotnet build $(rutaSolucio) -c Release --no-restore -warnaserror
            displayName: Compilar
          - script: |
              dotnet test $(rutaSolucio) -c Release --no-build \
                --logger trx --collect:"XPlat Code Coverage" \
                --results-directory $(Agent.TempDirectory)/proves
            displayName: Executar proves unitaries
          - task: PublishTestResults@2
            condition: succeededOrFailed()      # Publicar tambe si han fallat:
            inputs:                             # es quan mes interessa veure-les
              testResultsFormat: VSTest
              testResultsFiles: '$(Agent.TempDirectory)/proves/**/*.trx'
              failTaskOnFailedTests: true       # Sense aixo la canalitzacio queda verda
          - task: PublishCodeCoverageResults@2  # encara que les proves fallin
            condition: succeededOrFailed()
            inputs:
              summaryFileLocation: '$(Agent.TempDirectory)/proves/**/coverage.cobertura.xml'
          - script: |
              dotnet publish src/Contoso.Reservas.Web/Contoso.Reservas.Web.csproj \
                -c Release --no-build -o $(Build.ArtifactStagingDirectory)/web
            displayName: Preparar el paquet desplegable
          - publish: $(Build.ArtifactStagingDirectory)/web
            artifact: web-reservas       # El que 05-04 prendra tal qual

Sobre l'estructura: trigger i pr són els dos desencadenadors d'enviament (trigger: none desactiva l'arrencada automàtica, típic en canalitzacions de desplegament). La jerarquia stages → jobs → steps significa que una etapa és una fase lògica i pot dur aprovacions, un treball s'executa sencer en un agent i uns quants poden anar en paral·lel, i un pas és una acció individual. La diferència entre task i script és que una tasca és un component reutilitzable amb entrades anomenades i versió (@2) mentre que un script és una ordre de shell: fes servir tasques quan aportin alguna cosa real —publicar resultats, autenticar-se— i scripts quan l'ordre sigui clara, perquè són més llegibles i portables. I condition: succeededOrFailed() força un pas encara que l'anterior hagi fallat.

  1. Les tasques imprescindibles i la memòria cau de dependències

Restaurar sempre de manera explícita, sense dependre del que «ja hi havia» a la màquina. Compilar amb -warnaserror, que converteix els avisos en errors; sense això se n'acumulen per centenars i deixen de llegir-se. Provar publicant resultats i cobertura, amb failTaskOnFailedTests: true —i compte amb convertir la cobertura en objectiu: exigir un 90 % produeix proves que recorren codi sense comprovar res—. Publicar l'artefacte, que consagra el principi de construir una vegada, desplegar moltes: el binari validat en desenvolupament és exactament el mateix bit a bit que arribarà a producció; recompilar per entorn introdueix diferències impossibles de rastrejar.

Falta l'anàlisi estàtica, que busca errades i vulnerabilitats abans que existeixin en execució, i la memòria cau, que baixa el temps de restauració de minuts a segons:

          # La clau de la memoria cau es deriva del sistema operatiu i del resum
          # dels fitxers de projecte: si canvia una dependencia, canvia la clau i
          # no es reutilitza una memoria cau obsoleta. Una clau fixa serveix brossa eterna.
          - task: Cache@2
            inputs:
              key: 'nuget | "$(Agent.OS)" | **/*.csproj'
              restoreKeys: 'nuget | "$(Agent.OS)"'
              path: $(NUGET_PACKAGES)

          - script: |
              dotnet format --verify-no-changes            # Estil acordat
              dotnet list package --vulnerable --include-transitive
            displayName: Analisi d estil i de dependencies vulnerables

No posis mai a la memòria cau resultats de compilació, només dependències descarregades.

  1. Variables, grups de variables i Key Vault

On Per a què Visibilitat
variables al YAML Valors no sensibles de la canalització Públic al repositori
Grup de variables a la biblioteca Valors compartits per diverses canalitzacions Projecte, amb permisos
Grup vinculat a Key Vault Secrets No es veuen mai; es resolen en executar

Un secret no s'escriu mai al YAML, que és al repositori i a cada clon; ja vam veure a 05-02 el que costa un secret confirmat. La manera correcta és vincular un grup de variables a kv-contoso-pro:

# Grup normal, per a valors no sensibles
az pipelines variable-group create --name vg-contoso-reservas-comun \
  --variables entorno=comun proyecto=contoso-reservas centro-coste=CC-1042 \
  --authorize false

# Grup vinculat a kv-contoso-pro: els VALORS es queden al magatzem i
# la connexio de servei nomes necessita el rol "Usuari de secrets de Key Vault"
az pipelines variable-group create --name vg-contoso-secretos-pro \
  --variables pasarela-pago-clave="" token-meteo="" --authorize false
variables:
  - group: vg-contoso-secretos-pro     # Els seus valors es llegeixen de kv-contoso-pro

steps:
  - script: ./scripts/prova-integracio.sh
    env:
      TOKEN_METEO: $(token-meteo)      # Els secrets NO s injecten sols a l entorn:
                                       # cal mapar-los expressament

Tres detalls que eviten disgustos. Les variables secretes no s'exposen automàticament com a variables d'entorn; el mapatge explícit amb env: és una protecció deliberada. Azure Pipelines emmascara els secrets als registres, però no és infal·lible: si el teu script imprimeix el valor transformat (en base64, per exemple), l'emmascarament no el reconeix. I --authorize false obliga a autoritzar quines canalitzacions poden fer servir el grup, que és el mínim privilegi aplicat als secrets de compilació: la canalització d'una aplicació de proves no té per què poder llegir la clau de la passarel·la de pagament.

  1. Plantilles de canalització reutilitzables

Contoso té quatre repositoris que compilen igual. Copiar el YAML a cadascun són quatre llocs per actualitzar quan canviï l'SDK. Les plantilles ho resolen. A contoso-infra, fitxer plantillas/compilar-dotnet.yml:

parameters:                       # Tipats: si en falta un d obligatori, ni arrenca
  - { name: rutaSolucio,      type: string }
  - { name: nomArtefacte,     type: string }
  - { name: versioSdk,        type: string,  default: '8.0.x' }
  - { name: executarProves,   type: boolean, default: true }

steps:
  - task: UseDotNet@2
    inputs: { packageType: sdk, version: ${{ parameters.versioSdk }} }
  - script: dotnet restore ${{ parameters.rutaSolucio }}
  - script: dotnet build ${{ parameters.rutaSolucio }} -c Release --no-restore -warnaserror

  # Condicio en temps d expansio: si executarProves es false, aquests passos
  # ni tan sols existeixen a la canalitzacio generada
  - ${{ if eq(parameters.executarProves, true) }}:
    - script: dotnet test ${{ parameters.rutaSolucio }} -c Release --no-build --logger trx
    - task: PublishTestResults@2
      condition: succeededOrFailed()
      inputs: { testResultsFormat: VSTest, testResultsFiles: '**/*.trx', failTaskOnFailedTests: true }

  - publish: $(Build.ArtifactStagingDirectory)
    artifact: ${{ parameters.nomArtefacte }}

Ús des del repositori contoso-api-disponibilidad:

resources:
  repositories:
    - repository: plantillas
      type: git
      name: contoso-reservas/contoso-infra   # projecte/repositori
      ref: refs/tags/plantillas-v1.2         # ANCORAT a una etiqueta, no a main

steps:
  - template: plantillas/compilar-dotnet.yml@plantillas
    parameters:
      rutaSolucio: 'src/Contoso.Api.sln'
      nomArtefacte: 'api-disponibilidad'

El ref ancorat a una etiqueta evita que un canvi a la plantilla trenqui alhora les quatre canalitzacions: l'actualització es fa pujant l'etiqueta, deliberadament. I existeix una variant més estricta, extends, en què la canalització filla no pot afegir passos arbitraris, només omplir els buits previstos:

extends:
  template: plantillas/pipeline-seguro.yml@plantillas
  parameters:
    passosCompilacio:
      - script: dotnet build src/Contoso.Reservas.sln -c Release

extends és el mecanisme amb què un equip de plataforma garanteix que cap canalització no se salti l'anàlisi de seguretat, per molt que algú editi el seu YAML. És l'equivalent en el lliurament a les polítiques de 04-06: no es confia en la bona voluntat, es fa estructuralment impossible.

  1. Validació de sol·licituds de canvi i matriu de treballs

Amb el desencadenador pr definit i la directiva de branca de 05-02 apuntant a aquesta canalització, el cicle es tanca:

graph LR
    A["En Diego envia<br/>feature/1842"] --> B["Obre sol.licitud<br/>de canvis"]
    B --> C["Desencadenador pr:<br/>s executa el CI"]
    C --> D{"Compila i<br/>passen les proves?"}
    D -->|No| E["Estat vermell:<br/>fusio bloquejada"]
    D -->|Si| F["Verd + 2 aprovacions<br/>+ element vinculat"]
    F --> G["Squash sobre main"]
    G --> H["Desencadenador trigger:<br/>CI sobre main"]
    H --> I["Artefacte web-reservas<br/>a punt per a 05-04"]

Quan cal verificar en diverses configuracions, la matriu genera un treball per combinació:

  - job: compatibilitat
    strategy:
      matrix:
        linux_net8:   { imatgeAgent: 'ubuntu-latest',  versioSdk: '8.0.x' }
        windows_net8: { imatgeAgent: 'windows-latest', versioSdk: '8.0.x' }
        linux_net9:   { imatgeAgent: 'ubuntu-latest',  versioSdk: '9.0.x' }
      maxParallel: 2        # Limitat pels treballs paral.lels contractats
    pool:
      vmImage: $(imatgeAgent)
    steps:
      - task: UseDotNet@2
        inputs: { packageType: sdk, version: $(versioSdk) }
      - script: dotnet test src/Contoso.Reservas.sln

maxParallel importa per diners: amb un sol treball paral·lel contractat, una matriu de nou combinacions no va nou vegades més ràpid, va en filera i consumeix nou vegades els minuts.

  1. Artefactes, diagnòstic d'errades i insígnia d'estat

Artefactes de canalització (publish/download) Artefactes de compilació (PublishBuildArtifacts@1)
Rendiment Molt més ràpid, amb deduplicació Lent amb molts fitxers
Emmagatzematge Optimitzat Còpia completa
Estat Recomanat Heretat
- publish: $(Build.ArtifactStagingDirectory)/web    # Publicar a l etapa de compilacio
  artifact: web-reservas
- download: current                                 # Recuperar-lo en una altra etapa
  artifact: web-reservas

Quan una canalització falla, l'ordre de diagnòstic que estalvia hores: (1) llegir el registre del pas que ha fallat, no el resum —l'error real sol ser 30 línies per damunt de l'última línia vermella—; (2) activar els registres de diagnòstic posant la variable system.debug a true en rellançar, que mostra la resolució de variables i les rutes reals, on sol ser el problema; (3) reproduir en local executant exactament les ordres del YAML, perquè el 80 % de les errades «només de la canalització» són diferències d'entorn —una variable que al teu portàtil existeix, un fitxer ignorat per .gitignore que a la teva màquina sí que hi és, o majúscules d'un nom que a Linux importen i a Windows no—; i (4) comprovar permisos si l'errada esmenta autorització: la connexió de servei o el grup de variables probablement no estan autoritzats per a aquesta canalització.

I la insígnia d'estat al README.md, que dóna visibilitat immediata de si main és sa:

[![Estat](https://dev.azure.com/contoso-airlines/contoso-reservas/_apis/build/status/contoso-reservas-ci?branchName=main)](https://dev.azure.com/contoso-airlines/contoso-reservas/_build/latest?definitionId=12&branchName=main)

Errors Comuns i Consells

  • Compilar a cada entorn. Trenca el principi de construir una vegada i desplegar moltes: el binari de producció deixa de ser el que es va provar. Compila una vegada, publica l'artefacte i reutilitza'l.
  • Escriure secrets al YAML. Són al repositori i a cada clon. Grup de variables vinculat a kv-contoso-pro, sempre.
  • Canalitzacions de 40 minuts. Si el veredicte triga més que un cafè, la gent deixa d'esperar-lo i continua treballant sobre codi no verificat. Divideix, posa memòria cau i paral·lelitza fins a baixar de 10 minuts.
  • Tolerar una compilació trencada a main, o conviure amb proves inestables. Tan bon punt el vermell és normal, la canalització deixa de significar res i l'equip aprèn a rellançar sense mirar.
  • continueOnError: true per comoditat. Converteix un pas en decoratiu. Fes-lo servir només mentre ajustes el llindar d'una eina nova, i amb data de caducitat.
  • Plantilles apuntant a main. Un canvi trenca simultàniament totes les canalitzacions. Ancora a etiqueta i versiona les plantilles.
  • Consell: posa timeoutInMinutes a tots els treballs. Un treball penjat consumeix minuts facturables fins al límit de 60 o 360.
  • Consell: exclou docs/* i README.md del desencadenador. És un minut de feina que estalvia minuts d'agent cada mes.

Exercicis

Exercici 1: llegir una canalització i detectar-ne els problemes

Un company proposa aquesta canalització per a Contoso Millas:

trigger:
  branches: { include: ['*'] }
pool: { vmImage: ubuntu-latest }
variables:
  claveApi: 'ak_millas_9f2b7c1d4e'
steps:
  - script: dotnet build src/Millas.sln
  - script: dotnet test src/Millas.sln
    continueOnError: true
  - script: dotnet publish src/Millas.Web -o sortida
  1. Identifica com a mínim cinc problemes.
  2. Enumera els canvis concrets que faries per corregir-los.
  3. Quin és un incident de seguretat i què cal fer a més de corregir el fitxer?

Exercici 2: agents i cost

Contoso afegeix tres canalitzacions: una compila el web, una altra l'API i una altra executa proves d'integració contra sql-contoso-reservas-dev, que té punt privat. Les tres s'executen unes 20 vegades al dia, 12 minuts cadascuna.

  1. Quin tipus d'agent necessita cada canalització i per què?
  2. Estima el consum mensual de minuts allotjats i digues si cap al nivell gratuït.
  3. Proposa dues maneres de reduir la despesa sense renunciar a la verificació.

Exercici 3: dissenyar la reutilització

Els quatre repositoris compilen .NET gairebé igual, però contoso-infra no té proves unitàries (són plantilles de Bicep) i contoso-modelos publica un paquet en lloc d'una aplicació web. Seguretat exigeix que cap canalització no pugui saltar-se l'anàlisi de dependències vulnerables.

  1. Faries servir template o extends? Justifica-ho respecte al requisit de seguretat.
  2. Esbossa els paràmetres de la plantilla.
  3. Com evites que actualitzar-la trenqui les quatre canalitzacions alhora?

Solucions

Solució 1:

  1. (a) Secret al YAML: claveApi és al repositori. (b) trigger sobre totes les branques, que compila cada branca de treball i crema minuts. (c) Falta el desencadenador pr, així que la directiva de compilació amb validació no té res on enganxar-se. (d) continueOnError: true a les proves: la canalització passa encara que fallin. (e) No es publiquen resultats ni cobertura. (f) No es publica cap artefacte: no hi ha res per desplegar després. (g) Falta UseDotNet fixant la versió de l'SDK, així que es depèn del que porti la imatge de l'agent. (h) Sense timeoutInMinutes ni displayName llegibles.
  2. trigger limitat a main més pr: [main]; UseDotNet@2 amb 8.0.x; dotnet restore explícit; compilació amb -warnaserror; dotnet test amb --logger trx --collect:"XPlat Code Coverage"; PublishTestResults@2 amb failTaskOnFailedTests: true i condition: succeededOrFailed(); publicació de cobertura; dotnet publish a $(Build.ArtifactStagingDirectory) seguit de - publish: amb nom d'artefacte; la clau substituïda per un grup de variables vinculat a kv-contoso-pro i mapada amb env:; i timeoutInMinutes: 20.
  3. El secret. A més de treure'l del fitxer cal rotar-lo: és a la història de Git i als registres de totes les execucions anteriors. Després, guardar el valor nou al magatzem i revisar si es va fer servir indegudament. Igual que a 05-02, esborrar no n'hi ha prou.

Solució 2:

  1. Web i API, agents allotjats: no necessiten accés a res privat i es beneficien d'una màquina neta i mantinguda. Les proves d'integració, agent autoallotjat a pool-contoso-privado dins de snet-gestion, perquè sql-contoso-reservas-dev només és accessible pel seu punt privat i un agent allotjat no hi té ruta. L'alternativa serien agents de conjunt d'escalat gestionats dins de la xarxa virtual.
  2. Les dues canalitzacions allotjades sumen 2 × 20 × 12 = 480 minuts al dia, uns 10.500 al mes amb 22 dies laborables. El nivell gratuït són 1.800, així que se supera de llarg; i amb un sol treball paral·lel les execucions a més es posarien a la cua. Caldria contractar treballs paral·lels addicionals (~40 $/mes cadascun).
  3. (a) Memòria cau de dependències i clon superficial, per baixar els 12 minuts a la meitat. (b) Excloure rutes irrellevants del desencadenador i no compilar a cada enviament a branques de treball, sinó a la sol·licitud de canvis. (c) Reservar la matriu completa i les proves lentes per a la compilació nocturna, deixant al cicle ràpid només l'imprescindible. (d) Comparar el cost d'una VM d'agent autoallotjat amb el dels treballs paral·lels, que a aquest volum pot sortir a favor de la VM.

Solució 3:

  1. extends. Amb template la canalització filla inclou la plantilla però pot afegir passos, reordenar-los o senzillament no cridar-la; amb extends està obligada a construir-se al seu damunt i només pot omplir els buits previstos, de manera que l'anàlisi de dependències no es pot ometre editant el YAML. És la diferència entre una recomanació i una regla, la mateixa lògica de les polítiques de 04-06.
  2. rutaSolucio (string, obligatori), nomArtefacte (string), versioSdk (string, per defecte 8.0.x), executarProves (boolean, false per a contoso-infra), tipusSortida (web o paquet, per distingir contoso-modelos) i passosAddicionals (stepList) com a únic buit d'extensió.
  3. Ancorant la referència del repositori de plantilles a una etiqueta (ref: refs/tags/plantillas-v1.2) i versionant les plantilles amb versionat semàntic. Cada repositori puja la seva etiqueta quan li convé, amb la qual cosa un canvi incompatible es prova en un abans de propagar-se. La plantilla viu a contoso-infra, amb les seves directives de branca i la revisió obligatòria de Contoso-Infraestructura.

Conclusió

La branca main de Contoso ja no només està protegida: està verificada. Entens la integració contínua com a disciplina —integrar sovint perquè integrar tard fa mal de manera no lineal— amb els seus quatre requisits i la regla cultural que la sosté: una compilació trencada és la prioritat número u. Saps triar entre agents allotjats, nets i mantinguts per Microsoft, i agents autoallotjats, imprescindibles quan cal arribar a recursos que només existeixen darrere d'un punt privat dins de vnet-contoso-pro; i coneixes els números reals: 1.800 minuts i un treball paral·lel gratuïts per projecte privat, i uns 40 $ al mes per cada treball paral·lel addicional.

Has escrit l'azure-pipelines.yml de contoso-reservas-ci entenent cada peça: trigger amb exclusió de rutes, pr per enganxar amb la directiva de compilació amb validació de 05-02, schedules per a la compilació nocturna que detecta el que es trenca sense que tu toquis res, i la jerarquia stages → jobs → steps amb la diferència entre task i script. A dins hi has posat l'imprescindible —restaurar, compilar amb -warnaserror, provar publicant resultats i cobertura amb failTaskOnFailedTests, analitzar dependències vulnerables i publicar l'artefacte—, ho has accelerat amb una memòria cau la clau de la qual es deriva del manifest, i ho has fet reutilitzable amb plantilles, distingint template d'extends: només extends converteix l'anàlisi de seguretat en una cosa que cap equip no pot ometre. I has mantingut intacta la regla del mòdul 4: cap secret al YAML, tots en un grup de variables vinculat a kv-contoso-pro, mapats explícitament i autoritzats només a les canalitzacions que els necessiten.

El resultat de tot això és un fitxer: l'artefacte web-reservas, compilat una sola vegada, provat i esperant. Però continua esperant: ningú no l'ha portat a app-contoso-reservas-pro, i el desplegament del divendres a la nit continua existint tal qual. A la lliçó següent, Desplegament continu amb entorns i aprovacions, aquest artefacte viatjarà. Crearàs els entorns desarrollo, preproduccion i produccion amb el seu registre de quina versió hi ha a cadascun, posaràs l'aprovació manual de la Marta Ríos i les finestres que impedeixen desplegar un divendres a la tarda, compararàs les estratègies de desplegament i executaràs el blau-verd real de Contoso amb l'intercanvi de la ranura preproduccion que ja coneixes del mòdul 2, amb migracions de base de dades compatibles cap enrere i una reversió que funciona de debò.

Curs d'Azure

Mòdul 1: Introducció a Azure

Mòdul 2: Serveis principals d'Azure

Mòdul 3: Bases de dades d'Azure

Mòdul 4: Seguretat a Azure

Mòdul 5: Azure DevOps

Mòdul 6: Serveis avançats d'Azure

Mòdul 7: Monitoratge i gestió

Mòdul 8: Gestió i optimització de costos

Mòdul 9: Estudis de cas i millors pràctiques

© Copyright 2026. Tots els drets reservats