Condividi tramite


Informazioni di riferimento sull'utilizzo dei modelli

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

I modelli consentono di definire contenuto riutilizzabile, logica e parametri nelle pipeline YAML. Per usare i modelli in modo efficace, è necessario avere una conoscenza di base dei concetti chiave di Azure Pipelines, ad esempio fasi, passaggi e processi.

I modelli consentono di velocizzare lo sviluppo. Ad esempio, è possibile avere una serie di stesse attività in un modello e quindi includere il modello più volte in diverse fasi della pipeline YAML.

I modelli consentono anche di proteggere la pipeline. Quando un modello controlla ciò che è consentito in una pipeline, il modello definisce la logica che deve essere seguita da un altro file. Ad esempio, è possibile limitare le attività consentite per l'esecuzione. Per questo scenario, è possibile usare un modello per impedire a un utente di eseguire correttamente un'attività che viola i criteri di sicurezza dell'organizzazione.

Esistono due tipi di modelli: include ed estende.

  • Include modelli che consentono di inserire contenuto riutilizzabile con un modello. Se un modello viene usato per includere contenuto, funziona come una direttiva di inclusione in molti linguaggi di programmazione. Il contenuto di un file viene inserito in un altro file.
  • Estende il controllo modello che cosa è consentito in una pipeline. Quando un modello estende controlla ciò che è consentito in una pipeline, il modello definisce la logica che deve essere seguita da un altro file.

Per sfruttare appieno i vantaggi dei modelli, è consigliabile usare anche espressioni di modello e parametri di modello.

Limiti imposti

I modelli e le espressioni di modello possono causare una crescita esponenziale delle dimensioni e della complessità di una pipeline. Per evitare la crescita in fuga, Azure Pipelines impone i limiti seguenti:

  • Non è possibile includere più di 100 file YAML separati (direttamente o indirettamente)
  • Non è possibile avere più di 20 livelli di annidamento dei modelli (modelli che includono altri modelli)
  • Non più di 10 megabyte di memoria utilizzata durante l'analisi di YAML (in pratica, questo è in genere compreso tra 600 KB - 2 MB di YAML su disco, a seconda delle funzionalità specifiche usate)

Usare i modelli per definire la logica una sola volta e quindi riutilizzarla più volte. I modelli combinano il contenuto di più file YAML in una singola pipeline. È possibile passare parametri in un modello dalla pipeline padre.

Estendere da un modello

Per aumentare la sicurezza, è possibile imporre che una pipeline si estenda da un modello specifico. Il file start.yml definisce il parametro buildSteps, che viene quindi usato nella pipeline azure-pipelines.yml. In start.yml, se un buildStep oggetto viene passato con un passaggio di script, viene rifiutato e la compilazione della pipeline ha esito negativo. Quando si estende da un modello, è possibile aumentare la sicurezza aggiungendo un'approvazione del modello richiesta.

# File: start.yml
parameters:
- name: buildSteps # the name of the parameter is buildSteps
  type: stepList # data type is StepList
  default: [] # default value of buildSteps
stages:
- stage: secure_buildstage
  pool:
    vmImage: windows-latest
  jobs:
  - job: secure_buildjob
    steps:
    - script: echo This happens before code 
      displayName: 'Base: Pre-build'
    - script: echo Building
      displayName: 'Base: Build'

    - ${{ each step in parameters.buildSteps }}:
      - ${{ each pair in step }}:
          ${{ if ne(pair.value, 'CmdLine@2') }}:
            ${{ pair.key }}: ${{ pair.value }}       
          ${{ if eq(pair.value, 'CmdLine@2') }}: 
            # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
            '${{ pair.value }}': error         

    - script: echo This happens after code
      displayName: 'Base: Signing'
# File: azure-pipelines.yml
trigger:
- main

extends:
  template: start.yml
  parameters:
    buildSteps:  
      - bash: echo Test #Passes
        displayName: succeed
      - bash: echo "Test"
        displayName: succeed
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - task: CmdLine@2
        inputs:
          script: echo "Script Test"
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - script: echo "Script Test"

Estendere da un modello con risorse

È anche possibile usare extends per estendere da un modello nella pipeline di Azure che contiene risorse.

# File: azure-pipelines.yml
trigger:
- none

extends:
  template: resource-template.yml
# File: resource-template.yml
resources:
  pipelines:
  - pipeline: my-pipeline 
    source: sourcePipeline

steps:
- script: echo "Testing resource template"

Inserire un modello

È possibile copiare il contenuto da un FILE YAML e riutilizzarlo in un YAML diverso. La copia del contenuto da un YAML a un'altra consente di evitare di dover includere manualmente la stessa logica in più posizioni. Il include-npm-steps.yml modello di file contiene i passaggi riutilizzati in azure-pipelines.yml.

Nota

I file modello devono esistere nel file system all'inizio di un'esecuzione della pipeline. Non è possibile fare riferimento ai modelli in un artefatto.

# File: templates/include-npm-steps.yml

steps:
- script: npm install
- script: yarn install
- script: npm run compile
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference
- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference

Riutilizzo dei passaggi

È possibile inserire un modello per riutilizzare uno o più passaggi tra diversi processi. Oltre ai passaggi del modello, ogni processo può definire altri passaggi.

# File: templates/npm-steps.yml
steps:
- script: npm install
- script: npm test
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: macOS
  pool:
    vmImage: 'macOS-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: echo This script runs before the template's steps, only on Windows.
  - template: templates/npm-steps.yml  # Template reference
  - script: echo This step runs after the template's steps.

Riutilizzo del processo

Analogamente ai passaggi, i processi possono essere riutilizzati con i modelli.

# File: templates/jobs.yml
jobs:
- job: Ubuntu
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference

Quando si usano più processi, ricordarsi di rimuovere il nome del processo nel file modello, in modo da evitare conflitti

# File: templates/jobs.yml
jobs:
- job: 
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job:
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference

Riutilizzo della fase

Le fasi possono anche essere riutilizzate con i modelli.

# File: templates/stages1.yml
stages:
- stage: Angular
  jobs:
  - job: angularinstall
    steps:
    - script: npm install angular
# File: templates/stages2.yml
stages:
- stage: Build
  jobs:
  - job: build
    steps:
    - script: npm run build
# File: azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Install
  jobs: 
  - job: npminstall
    steps:
    - task: Npm@1
      inputs:
        command: 'install'
- template: templates/stages1.yml # Template reference
- template: templates/stages2.yml # Template reference

Modelli di processo, fase e passaggio con parametri

Nei modelli seguenti:

  • templates/npm-with-params.yml definisce due parametri: name e e vmImage crea un processo con il parametro name per il nome del processo e il parametro vmImage per l'immagine della macchina virtuale.
  • La pipeline (azure-pipelines.yml) fa riferimento al modello tre volte, ognuno con valori di parametro diversi che fanno riferimento ai nomi del sistema operativo e delle immagini della macchina virtuale.
  • La pipeline compilata viene eseguita in un'immagine di macchina virtuale diversa e denominata in base al sistema operativo specificato. Ogni processo esegue i passaggi di test npm install e npm.
# File: templates/npm-with-params.yml

parameters:
- name: name  # defaults for any parameters that aren't specified
  default: ''
- name: vmImage
  default: ''

jobs:
- job: ${{ parameters.name }}
  pool: 
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

Quando si utilizza il modello nella pipeline, specificare i valori per i parametri del modello.

# File: azure-pipelines.yml

jobs:
- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Linux
    vmImage: 'ubuntu-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: macOS
    vmImage: 'macOS-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Windows
    vmImage: 'windows-latest'

Preparare i modelli con più parametri

Nei modelli seguenti:

  • Il stage-template.yml modello definisce quattro parametri: stageName, jobName, vmImagee scriptPath, tutti di tipo string. Il modello crea una fase usando il parametro per impostare il stageName nome della fase, definisce un processo con jobNamee include un passaggio per eseguire uno script.
  • La pipeline, azure-pipeline.yml, quindi definisce dinamicamente fasi e processi usando i parametri ed esegue un processo che esegue uno script, build-script.sh.
# stage-template.yml

parameters:
  - name: stageName
    type: string
  - name: jobName
    type: string
  - name: vmImage
    type: string
  - name: scriptPath
    type: string

stages:
  - stage: ${{ parameters.stageName }}
    jobs:
      - job: ${{ parameters.jobName }}
        pool:
          vmImage: ${{ parameters.vmImage }}
        steps:
          - script: ./${{ parameters.scriptPath }}
# azure-pipelines.yml
trigger:
- main

stages:
- template: stage-template.yml
  parameters:
    stageName: 'BuildStage'
    jobName: 'BuildJob'
    scriptPath: 'build-script.sh' # replace with script in your repository
    vmImage: 'ubuntu-latest'

Modelli con passaggi e parametri

È anche possibile usare i parametri con modelli di passaggio o di fase.

Nei modelli seguenti:

  • Il modello (templates/steps-with-params.yml) definisce un parametro denominato runExtendedTests con un valore predefinito false.
  • La pipeline (azure-pipelines.yml) viene eseguita npm test e npm test --extended perché il runExtendedTests parametro è true.
# File: templates/steps-with-params.yml

parameters:
- name: 'runExtendedTests'  # defaults for any parameters that aren't specified
  type: boolean
  default: false

steps:
- script: npm test
- ${{ if eq(parameters.runExtendedTests, true) }}:
  - script: npm test --extended

Quando si utilizza il modello nella pipeline, specificare i valori per i parametri del modello.

# File: azure-pipelines.yml

steps:
- script: npm install

- template: templates/steps-with-params.yml  # Template reference
  parameters:
    runExtendedTests: 'true'

Nota

I parametri scalari senza un tipo specificato vengono considerati come stringhe. Ad esempio, eq(true, parameters['myparam']) restituirà true, anche se il myparam parametro è la parola false, se myparam non viene esplicitamente reso boolean. Le stringhe non vuote vengono cast in true in un contesto booleano. Tale espressione può essere riscritta per confrontare in modo esplicito le stringhe: eq(parameters['myparam'], 'true').

I parametri non sono limitati alle stringhe scalari. Vedere l'elenco dei tipi di dati. Ad esempio, usando il object tipo :

# azure-pipelines.yml
jobs:
- template: process.yml
  parameters:
    pool:   # this parameter is called `pool`
      vmImage: ubuntu-latest  # and it's a mapping rather than a string


# process.yml
parameters:
- name: 'pool'
  type: object
  default: {}

jobs:
- job: build
  pool: ${{ parameters.pool }}

Riutilizzo delle variabili

Le variabili possono essere definite in un file YAML e incluse in un altro modello. Questo può essere utile se si desidera archiviare tutte le variabili in un unico file. Se si usa un modello per includere variabili in una pipeline, il modello incluso può essere usato solo per definire le variabili. È possibile usare i passaggi e la logica più complessa quando si esegue l'estensione da un modello. Usare i parametri anziché le variabili quando si vuole limitare il tipo.

In questo esempio la variabile favoriteVeggie è inclusa in azure-pipelines.yml.

# File: vars.yml
variables:
  favoriteVeggie: 'brussels sprouts'
# File: azure-pipelines.yml

variables:
- template: vars.yml  # Template reference

steps:
- script: echo My favorite vegetable is ${{ variables.favoriteVeggie }}.

Modelli di variabile con parametro

È possibile passare parametri alle variabili con i modelli. In questo esempio si passa il DIRECTORY parametro a una RELEASE_COMMAND variabile.

# File: templates/package-release-with-params.yml

parameters:
- name: DIRECTORY 
  type: string
  default: "." # defaults for any parameters that specified with "." (current directory)

variables:
- name: RELEASE_COMMAND
  value: grep version ${{ parameters.DIRECTORY }}/package.json | awk -F \" '{print $4}'  

Quando si utilizza il modello nella pipeline, specificare i valori per i parametri del modello.

# File: azure-pipelines.yml

variables: # Global variables
  - template: package-release-with-params.yml # Template reference
    parameters:
      DIRECTORY: "azure/checker"

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Release_Stage 
  displayName: Release Version
  variables: # Stage variables
  - template: package-release-with-params.yml  # Template reference
    parameters:
      DIRECTORY: "azure/todo-list"
  jobs: 
  - job: A
    steps: 
    - bash: $(RELEASE_COMMAND) #output release command

Estendere da un modello e usare un modello di inclusione con variabili

Uno scenario comune consiste nell'avere una pipeline con fasi per lo sviluppo, il test e la produzione che usa sia un modello per le variabili che un modello estende per fasi o processi.

Nell'esempio seguente viene variables-template.yml definito un set di variabili di macchina virtuale che vengono quindi usate in azure-pipeline.yml.

# variables-template.yml

variables:
- name: devVmImage
  value: 'ubuntu-latest'
- name: testVmImage
  value: 'ubuntu-latest'
- name: prodVmImage
  value: 'ubuntu-latest'

Il file seguente definisce stage-template.yml una configurazione di fase riutilizzabile con tre parametri (name, vmImage, steps) e un processo denominato Build.

# stage-template.yml
parameters:
- name: name
  type: string
  default: ''
- name: vmImage
  type: string
  default: ''
- name: steps
  type: stepList
  default: []

stages:
- stage: ${{ parameters.name }}
  jobs:
  - job: Build
    pool:
      vmImage: ${{ parameters.vmImage }}
    steps: ${{ parameters.steps }}

La pipeline seguente, azure-pipelines.yml, importa le variabili da variables-template.ymle quindi usa il stage-template.yml modello per ogni fase. Ogni fase (Sviluppo, Test, Prod) viene definita con lo stesso modello, ma con parametri diversi, portando alla coerenza tra le fasi, consentendo al tempo stesso la personalizzazione. La fase Prod include una variabile di ambiente come esempio di un elemento che è possibile usare per l'autenticazione.

# azure-pipelines.yml
trigger:
- main

variables:
- template: variables-template.yml

stages:
- template: stage-template.yml
  parameters:
    name: Dev
    vmImage: ${{ variables.devVmImage }}
    steps:
      - script: echo "Building in Dev"
- template: stage-template.yml
  parameters:
    name: Test
    vmImage: ${{ variables.testVmImage }}
    steps:
      - script: echo "Testing in Test"
- template: stage-template.yml
  parameters:
    name: Prod
    vmImage: ${{ variables.prodVmImage }}
    steps:
      - script: echo "Deploying to Prod"
        env:
          SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Percorsi dei modelli di riferimento

I percorsi dei modelli possono essere un percorso assoluto all'interno del repository o rispetto al file che esegue l'inclusione.

Per usare un percorso assoluto, il percorso del modello deve iniziare con ./ Tutti gli altri percorsi vengono considerati relativi.

Ecco un esempio di gerarchia annidata.

|
+-- fileA.yml
|
+-- dir1/
     |
     +-- fileB.yml
     |
     +-- dir2/
          |
          +-- fileC.yml

Quindi, in fileA.yml è possibile fare riferimento fileB.yml e fileC.yml in questo modo.

steps:
- template: dir1/fileB.yml
- template: dir1/dir2/fileC.yml

Se fileC.yml è il punto di partenza, è possibile includere fileA.yml e fileB.yml in questo modo.

steps:
- template: ../../fileA.yml
- template: ../fileB.yml

Quando fileB.yml è il punto di partenza, è possibile includere fileA.yml e fileC.yml in questo modo.

steps:
- template: ../fileA.yml
- template: dir2/fileC.yml

In alternativa, fileB.yml potrebbe fare riferimento a fileA.yml e fileC.yml usare percorsi assoluti come questo.

steps:
- template: /fileA.yml
- template: /dir1/dir2/fileC.yml

Uso di altri repository

È possibile mantenere i modelli in altri repository. Si supponga, ad esempio, di avere una pipeline di base che si vuole usare tutte le pipeline dell'app. È possibile inserire il modello in un repository principale e quindi farvi riferimento da ogni repository dell'app:

# Repo: Contoso/BuildTemplates
# File: common.yml
parameters:
- name: 'vmImage'
  default: 'ubuntu-22.04'
  type: string

jobs:
- job: Build
  pool:
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

È ora possibile riutilizzare questo modello in più pipeline. Usare la resources specifica per specificare la posizione del repository principale. Quando si fa riferimento al repository principale, usare @ e il nome assegnato in resources.

# Repo: Contoso/LinuxProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates

jobs:
- template: common.yml@templates  # Template reference
# Repo: Contoso/WindowsProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates
      ref: refs/tags/v1.0 # optional ref to pin to

jobs:
- template: common.yml@templates  # Template reference
  parameters:
    vmImage: 'windows-latest'

Per type: github, name è <identity>/<repo> come negli esempi precedenti. Per type: git (Azure Repos), name è <project>/<repo>. Se il progetto si trova in un'organizzazione Azure DevOps separata, è necessario configurare una connessione al servizio di tipo Azure Repos/Team Foundation Server con accesso al progetto e includerla in YAML:

resources:
  repositories:
  - repository: templates
    name: Contoso/BuildTemplates
    endpoint: myServiceConnection # Azure DevOps service connection
jobs:
- template: common.yml@templates

I repository vengono risolti una sola volta, all'avvio della pipeline. Successivamente, la stessa risorsa viene usata per la durata della pipeline. Vengono usati solo i file modello. Una volta espansi completamente i modelli, la pipeline finale viene eseguita come se fosse stata definita interamente nel repository di origine. Ciò significa che non è possibile usare script dal repository del modello nella pipeline.

Se si vuole usare una particolare versione fissa del modello, assicurarsi di aggiungere a un oggetto ref. refs sono rami (refs/heads/<name>) o tag (refs/tags/<name>). Se si vuole aggiungere un commit specifico, creare prima di tutto un tag che punta a tale commit, quindi aggiungere a tale tag.

Nota

Se non viene specificato alcun ref valore, per impostazione predefinita la pipeline usa refs/heads/main.

È anche possibile aggiungere a un commit specifico in Git con il valore SHA per una risorsa del repository. Il valore SHA è un hash checksum di 40 caratteri che identifica in modo univoco il commit.

resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/BuildTemplates
      ref: 1234567890abcdef1234567890abcdef12345678

È anche possibile usare @self per fare riferimento al repository in cui è stata trovata la pipeline originale. Ciò è utile per l'uso nei extends modelli se si vuole fare riferimento al contenuto nel repository della pipeline di estensione. Ad esempio:

# Repo: Contoso/Central
# File: template.yml
jobs:
- job: PreBuild
  steps: []

  # Template reference to the repo where this template was
  # included from - consumers of the template are expected
  # to provide a "BuildJobs.yml"
- template: BuildJobs.yml@self

- job: PostBuild
  steps: []
# Repo: Contoso/MyProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/Central

extends:
  template: template.yml@templates
# Repo: Contoso/MyProduct
# File: BuildJobs.yml
jobs:
- job: Build
  steps: []

Domande frequenti

Come usare le variabili all'interno dei modelli?

In alcuni casi può essere utile impostare i parametri sui valori in base alle variabili. I parametri vengono espansi all'inizio dell'elaborazione di una pipeline in modo che non tutte le variabili siano disponibili. Per informazioni sulle variabili predefinite disponibili nei modelli, vedere Usare variabili predefinite.

In questo esempio le variabili Build.SourceBranch predefinite e Build.Reason vengono usate in condizioni in template.yml.

# File: azure-pipelines.yml
trigger:
- main

extends:
  template: template.yml
# File: template.yml
steps:
- script: echo Build.SourceBranch = $(Build.SourceBranch) # outputs refs/heads/main
- script: echo Build.Reason = $(Build.Reason) # outputs IndividualCI
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: 
  - script: echo I run only if Build.SourceBranch = refs/heads/main 
- ${{ if eq(variables['Build.Reason'], 'IndividualCI') }}: 
  - script: echo I run only if Build.Reason = IndividualCI 
- script: echo I run after the conditions