Condividi tramite


Specificare i processi della pipeline

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

È possibile organizzare la pipeline in processi. Ogni pipeline ha almeno un processo. Un processo è una serie di passaggi eseguiti in sequenza come unità. In altre parole, un processo è l'unità di lavoro più piccola che può essere pianificata per l'esecuzione.

Per informazioni sui concetti chiave e sui componenti che costituiscono una pipeline, vedere Concetti chiave per i nuovi utenti di Azure Pipelines.

Azure Pipelines non offre supporto per la priorità dei lavori nelle pipeline YAML. Per controllare quando vengono eseguiti i processi, è possibile specificare condizioni e dipendenze.

Definire un singolo processo

Nel caso più semplice, una pipeline ha un singolo processo. In tal caso, non è necessario usare in modo esplicito la job parola chiave a meno che non si usi un modello. È possibile specificare direttamente i passaggi nel file YAML.

Questo file YAML include un processo eseguito in un agente ospitato da Microsoft e restituisce Hello world.

pool:
  vmImage: 'ubuntu-latest'
steps:
- bash: echo "Hello world"

Potrebbe essere necessario specificare più proprietà in tale processo. In tal caso, è possibile usare la job parola chiave .

jobs:
- job: myJob
  timeoutInMinutes: 10
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello world"

La pipeline potrebbe avere più processi. In tal caso, usare la jobs parola chiave .

jobs:
- job: A
  steps:
  - bash: echo "A"

- job: B
  steps:
  - bash: echo "B"

La pipeline può avere più fasi, ognuna con più attività. In tal caso, usare la stages parola chiave .

stages:
- stage: A
  jobs:
  - job: A1
  - job: A2

- stage: B
  jobs:
  - job: B1
  - job: B2

La sintassi completa per specificare un processo è:

- job: string  # name of the job, A-Z, a-z, 0-9, and underscore
  displayName: string  # friendly name to display in the UI
  dependsOn: string | [ string ]
  condition: string
  strategy:
    parallel: # parallel strategy
    matrix: # matrix strategy
    maxParallel: number # maximum number simultaneous matrix legs to run
    # note: `parallel` and `matrix` are mutually exclusive
    # you may specify one or the other; including both is an error
    # `maxParallel` is only valid with `matrix`
  continueOnError: boolean  # 'true' if future jobs should run even if this job fails; defaults to 'false'
  pool: pool # agent pool
  workspace:
    clean: outputs | resources | all # what to clean up before the job runs
  container: containerReference # container to run this job inside
  timeoutInMinutes: number # how long to run the job before automatically cancelling
  cancelTimeoutInMinutes: number # how much time to give 'run always even if cancelled tasks' before killing them
  variables: { string: string } | [ variable | variableReference ] 
  steps: [ script | bash | pwsh | powershell | checkout | task | templateReference ]
  services: { string: string | container } # container resources to run as a service container

La sintassi completa per specificare un processo è:

- job: string  # name of the job, A-Z, a-z, 0-9, and underscore
  displayName: string  # friendly name to display in the UI
  dependsOn: string | [ string ]
  condition: string
  strategy:
    parallel: # parallel strategy
    matrix: # matrix strategy
    maxParallel: number # maximum number simultaneous matrix legs to run
    # note: `parallel` and `matrix` are mutually exclusive
    # you may specify one or the other; including both is an error
    # `maxParallel` is only valid with `matrix`
  continueOnError: boolean  # 'true' if future jobs should run even if this job fails; defaults to 'false'
  pool: pool # agent pool
  workspace:
    clean: outputs | resources | all # what to clean up before the job runs
  container: containerReference # container to run this job inside
  timeoutInMinutes: number # how long to run the job before automatically cancelling
  cancelTimeoutInMinutes: number # how much time to give 'run always even if cancelled tasks' before killing them
  variables: { string: string } | [ variable | variableReference ] 
  steps: [ script | bash | pwsh | powershell | checkout | task | templateReference ]
  services: { string: string | container } # container resources to run as a service container
  uses: # Any resources (repos or pools) required by this job that are not already referenced
    repositories: [ string ] # Repository references to Azure Git repositories
    pools: [ string ] # Pool names, typically when using a matrix strategy for the job

Se lo scopo principale del processo è distribuire l'app (anziché compilare o testare l'app), è possibile usare un tipo speciale di processo denominato processo di distribuzione.

La sintassi per un processo di distribuzione è:

- deployment: string        # instead of job keyword, use deployment keyword
  pool:
    name: string
    demands: string | [ string ]
  environment: string
  strategy:
    runOnce:
      deploy:
        steps:
        - script: echo Hi!

Sebbene sia possibile aggiungere passaggi per le attività di distribuzione in un job, è consigliabile usare invece un processo di distribuzione. Un processo di distribuzione offre alcuni vantaggi. Ad esempio, è possibile eseguire la distribuzione in un ambiente, che include vantaggi come la possibilità di visualizzare la cronologia di ciò che è stato distribuito.

Tipi di processi

I processi possono essere di tipi diversi, a seconda della posizione in cui vengono eseguiti.

  • I processi del pool di agenti vengono eseguiti in un agente in un pool di agenti.
  • I processi del server vengono eseguiti in Azure DevOps Server.
  • I processi contenitore vengono eseguiti in un contenitore su un agente in un pool di agenti. Per altre informazioni sulla scelta dei contenitori, vedere Definire i processi del contenitore.
  • I processi del pool di agenti vengono eseguiti in un agente in un pool di agenti.
  • I processi del server vengono eseguiti in Azure DevOps Server.

Processi del pool di agenti

I compiti del pool di agenti sono i compiti più comuni. Questi processi vengono eseguiti su un agente all'interno di un pool di agenti. È possibile specificare il pool in cui eseguire il processo ed è anche possibile specificare le richieste per specificare le funzionalità necessarie per l'esecuzione del processo da parte di un agente. Gli agenti possono essere ospitati da Microsoft o autogestiti. Per altre informazioni, vedere gli agenti di Azure Pipelines .

  • Quando si usano agenti ospitati da Microsoft, a ogni job in una pipeline viene assegnato un nuovo agente.
  • Quando utilizzi agenti self-hosted, è possibile usare richieste per specificare quali funzionalità un agente deve avere per eseguire l'attività lavorativa. Puoi ottenere lo stesso agente per incarichi consecutivi, a condizione che nel tuo pool di agenti ci siano più agenti che soddisfano le esigenze della tua pipeline. Se nel pool è presente un solo agente che corrisponde alle richieste della pipeline, la pipeline attende fino a quando l'agente non è disponibile.

Nota

Le richieste e le funzionalità sono progettate per l'uso con agenti self-hosted in modo che i processi possano essere confrontati con un agente che soddisfi i requisiti del processo. Quando si usano agenti ospitati da Microsoft, si seleziona un'immagine per l'agente che soddisfa i requisiti del compito. Anche se è possibile aggiungere funzionalità a un agente ospitato da Microsoft, non è necessario usare le funzionalità con gli agenti ospitati da Microsoft.

pool:
  name: myPrivateAgents    # your job runs on an agent in this pool
  demands: agent.os -equals Windows_NT    # the agent must have this capability to run the job
steps:
- script: echo hello world

O più richieste:

pool:
  name: myPrivateAgents
  demands:
  - agent.os -equals Darwin
  - anotherCapability -equals somethingElse
steps:
- script: echo hello world

Altre informazioni sulle funzionalità dell'agente.

Processi server

Il server orchestra ed esegue attività all'interno di un job server. Un processo del server non richiede un agente o un computer di destinazione. In un processo del server sono supportate solo alcune attività. Il tempo massimo per un processo server è di 30 giorni.

Attività supportate dai processi senza agente

Attualmente sono supportate solo le attività seguenti per i processi senza agente:

Poiché le attività sono estendibili, è possibile aggiungere altre attività senza agente usando le estensioni. Il timeout predefinito per i processi senza agente è 60 minuti.

La sintassi completa per specificare un processo del server è:

jobs:
- job: string
  timeoutInMinutes: number
  cancelTimeoutInMinutes: number
  strategy:
    maxParallel: number
    matrix: { string: { string: string } }

  pool: server # note: the value 'server' is a reserved keyword which indicates this is an agentless job

È anche possibile usare la sintassi semplificata:

jobs:
- job: string
  pool: server # note: the value 'server' is a reserved keyword which indicates this is an agentless job

Dipendenze

Quando si definiscono più processi in una singola fase, è possibile specificare le dipendenze tra di esse. Le pipeline devono contenere almeno un processo senza dipendenze. Per impostazione predefinita, i processi della pipeline YAML di Azure DevOps vengono eseguiti in parallelo, a meno che il dependsOn valore non sia impostato.

Nota

Ogni agente può eseguire un solo processo alla volta. Per eseguire più processi in parallelo, è necessario configurare più agenti. Sono necessari anche processi paralleli sufficienti.

La sintassi per la definizione di più processi e le relative dipendenze è:

jobs:
- job: string
  dependsOn: string
  condition: string

Processi di esempio che compilano in sequenza:

jobs:
- job: Debug
  steps:
  - script: echo hello from the Debug build
- job: Release
  dependsOn: Debug
  steps:
  - script: echo hello from the Release build

Processi di esempio compilati in parallelo (nessuna dipendenza):

jobs:
- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: echo hello from Windows
- job: macOS
  pool:
    vmImage: 'macOS-latest'
  steps:
  - script: echo hello from macOS
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - script: echo hello from Linux

Esempio di fan-out:

jobs:
- job: InitialJob
  steps:
  - script: echo hello from initial job
- job: SubsequentA
  dependsOn: InitialJob
  steps:
  - script: echo hello from subsequent A
- job: SubsequentB
  dependsOn: InitialJob
  steps:
  - script: echo hello from subsequent B

Esempio di fan-in:

jobs:
- job: InitialA
  steps:
  - script: echo hello from initial A
- job: InitialB
  steps:
  - script: echo hello from initial B
- job: Subsequent
  dependsOn:
  - InitialA
  - InitialB
  steps:
  - script: echo hello from subsequent

Condizioni

È possibile specificare le condizioni in base alle quali eseguire ogni processo. Per impostazione predefinita, un processo viene eseguito se non dipende da altri processi o se tutti i processi da cui dipende sono stati completati con successo. È possibile personalizzare questo comportamento forzando l'esecuzione di un processo anche se un processo precedente ha esito negativo o specificando una condizione personalizzata.

Esempio per eseguire un processo in base allo stato di esecuzione di un processo precedente:

jobs:
- job: A
  steps:
  - script: exit 1

- job: B
  dependsOn: A
  condition: failed()
  steps:
  - script: echo this will run when A fails

- job: C
  dependsOn:
  - A
  - B
  condition: succeeded('B')
  steps:
  - script: echo this will run when B runs and succeeds

Esempio di utilizzo di una condizione personalizzata:

jobs:
- job: A
  steps:
  - script: echo hello

- job: B
  dependsOn: A
  condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/main'))
  steps:
  - script: echo this only runs for master

È possibile specificare che un processo viene eseguito in base al valore di una variabile di output impostata in un processo precedente. In questo caso, è possibile usare solo le variabili impostate in processi dipendenti direttamente:

jobs:
- job: A
  steps:
  - script: "echo '##vso[task.setvariable variable=skipsubsequent;isOutput=true]false'"
    name: printvar

- job: B
  condition: and(succeeded(), ne(dependencies.A.outputs['printvar.skipsubsequent'], 'true'))
  dependsOn: A
  steps:
  - script: echo hello from B

Timeout

Per evitare di occupare risorse quando il processo non risponde o è in attesa per troppo tempo, è possibile impostare un limite sulla durata del processo. Usare l'impostazione di timeout del processo per specificare il limite in minuti per l'esecuzione del processo. L'impostazione del valore su zero indica che il processo può essere eseguito:

  • Per sempre sugli agenti self-hosted
  • Per 360 minuti (6 ore) sugli agenti ospitati da Microsoft con un progetto pubblico e un repository pubblico
  • Per 60 minuti sugli agenti ospitati da Microsoft con un progetto privato o un repository privato (a meno che non venga pagata capacità aggiuntiva)

Il periodo di timeout inizia all'avvio dell'esecuzione del processo. Non include il momento in cui il processo è in coda o è in attesa di un agente.

timeoutInMinutes consente di impostare un limite per il tempo di esecuzione del processo. Se non specificato, il valore predefinito è 60 minuti. Quando si specifica 0, viene usato il limite massimo.

cancelTimeoutInMinutes consente di impostare un limite per l'ora di annullamento del processo quando l'attività di distribuzione è impostata per continuare l'esecuzione se un'attività precedente non è riuscita. Se non specificato, il valore predefinito è 5 minuti. Il valore deve essere compreso tra 1 e 35790 minuti.

jobs:
- job: Test
  timeoutInMinutes: 10 # how long to run the job before automatically cancelling
  cancelTimeoutInMinutes: 2 # how much time to give 'run always even if cancelled tasks' before stopping them

I timeout hanno il livello di precedenza seguente.

  1. Negli agenti ospitati da Microsoft, i processi sono limitati per quanto tempo possono essere eseguiti in base al tipo di progetto e se vengono eseguiti usando un processo parallelo a pagamento. Quando è trascorso l'intervallo di timeout del processo ospitato da Microsoft, il processo viene terminato. Negli agenti ospitati da Microsoft i processi non possono essere eseguiti più a lungo di questo intervallo, indipendentemente dai timeout a livello di processo specificati nel processo.
  2. Il timeout configurato a livello di processo specifica la durata massima per l'esecuzione del processo. Quando viene trascorso l'intervallo di timeout a livello di processo, il processo viene terminato. Quando il processo viene eseguito in un agente ospitato da Microsoft, l'impostazione del timeout a livello di processo maggiore del timeout predefinito a livello di processo ospitato da Microsoft non ha alcun effetto.
  3. È anche possibile impostare il timeout per ogni attività singolarmente. Vedere le opzioni di controllo delle attività. Se l'intervallo di timeout a livello di processo è trascorso prima del completamento dell'attività, il processo in esecuzione viene terminato, anche se l'attività è configurata con un intervallo di timeout più lungo.

Configurazione multi-processo

Da un singolo processo creato, è possibile eseguire più processi su più agenti in parallelo. Alcuni esempi includono:

  • Compilazioni con più configurazioni: è possibile compilare più configurazioni in parallelo. Ad esempio, è possibile compilare un'app Visual C++ per entrambe debug le configurazioni e release in entrambe x86 le piattaforme e x64 . Per altre informazioni, vedere Compilazione di Visual Studio - più configurazioni per più piattaforme.

  • Distribuzioni con più configurazioni: è possibile eseguire più distribuzioni in parallelo, ad esempio in aree geografiche diverse.

  • Test con più configurazioni: è possibile eseguire test di più configurazioni in parallelo.

  • La multiconfigurazione genera sempre almeno un job, anche se una variabile di multiconfigurazione è vuota.

La matrix strategia consente di inviare più volte un processo, con set di variabili diversi. Il maxParallel tag limita la quantità di parallelismo. Il processo seguente viene inviato tre volte con i valori di Location e Browser impostati come specificato. Tuttavia, solo due processi vengono eseguiti contemporaneamente.

jobs:
- job: Test
  strategy:
    maxParallel: 2
    matrix: 
      US_IE:
        Location: US
        Browser: IE
      US_Chrome:
        Location: US
        Browser: Chrome
      Europe_Chrome:
        Location: Europe
        Browser: Chrome

Nota

I nomi di configurazione della matrice (ad esempio US_IE nell'esempio) devono contenere solo lettere alfabetici latine di base (A - Z, a - z), numeri e caratteri di sottolineatura (_). Devono iniziare con una lettera. Inoltre, devono essere di almeno 100 caratteri.

È anche possibile usare le variabili di output per generare una matrice. Questo metodo può essere utile se è necessario generare la matrice usando uno script.

matrix accetta un'espressione di runtime contenente un oggetto JSON stringato. L'oggetto JSON, se espanso, deve corrispondere alla sintassi di matrice. Nell'esempio seguente, la stringa JSON è stata codificata manualmente, ma puoi generarla con un linguaggio di scripting o un programma da riga di comando.

jobs:
- job: generator
  steps:
  - bash: echo "##vso[task.setVariable variable=legs;isOutput=true]{'a':{'myvar':'A'}, 'b':{'myvar':'B'}}"
    name: mtrx
  # This expands to the matrix
  #   a:
  #     myvar: A
  #   b:
  #     myvar: B
- job: runner
  dependsOn: generator
  strategy:
    matrix: $[ dependencies.generator.outputs['mtrx.legs'] ]
  steps:
  - script: echo $(myvar) # echos A or B depending on which leg is running

Sezionamento

È possibile usare un processo dell'agente per eseguire un gruppo di test in parallelo. Ad esempio, è possibile eseguire un ampio insieme di 1.000 test su un singolo agente. In alternativa, è possibile usare due agenti ed eseguire 500 test su ognuno in parallelo.

Per applicare il sezionamento, le attività nel processo devono essere sufficientemente intelligenti da comprendere la sezione a cui appartengono.

L'attività Test di Visual Studio è un'attività di questo tipo che supporta il sezionamento dei test. Se sono stati installati più agenti, è possibile specificare il modo in cui l'attività test di Visual Studio viene eseguita in parallelo su questi agenti.

La parallel strategia consente di duplicare un processo più volte. Le variabili System.JobPositionInPhase e System.TotalJobsInPhase vengono aggiunte a ogni processo. Le variabili possono quindi essere usate all'interno degli script per dividere il lavoro tra i processi. Vedere Parallel and multiple execution using agent jobs (Parallel and multiple execution using agent jobs).

Il processo seguente viene inviato cinque volte con i valori di System.JobPositionInPhase e System.TotalJobsInPhase impostato in modo appropriato.

jobs:
- job: Test
  strategy:
    parallel: 5

Variabili di processo

Se si usa YAML, è possibile specificare variabili nel processo. Le variabili possono essere passate agli input dell'attività usando la sintassi della macro $(variableName) o accessibili all'interno di uno script usando la variabile di fase.

Di seguito è riportato un esempio di definizione delle variabili in un processo e dell'uso all'interno delle attività.

variables:
  mySimpleVar: simple var value
  "my.dotted.var": dotted var value
  "my var with spaces": var with spaces value

steps:
- script: echo Input macro = $(mySimpleVar). Env var = %MYSIMPLEVAR%
  condition: eq(variables['agent.os'], 'Windows_NT')
- script: echo Input macro = $(mySimpleVar). Env var = $MYSIMPLEVAR
  condition: in(variables['agent.os'], 'Darwin', 'Linux')
- bash: echo Input macro = $(my.dotted.var). Env var = $MY_DOTTED_VAR
- powershell: Write-Host "Input macro = $(my var with spaces). Env var = $env:MY_VAR_WITH_SPACES"

Per informazioni sull'uso di una condizione, vedere Specificare le condizioni.

Area di lavoro

Quando si esegue un processo del pool di agenti, viene creata un'area di lavoro nell'agente. L'area di lavoro è una directory in cui scarica l'origine, esegue i passaggi e produce output. È possibile fare riferimento alla directory dell'area di lavoro nel processo usando Pipeline.Workspace la variabile . In questo caso vengono create varie sottodirectory:

  • Build.SourcesDirectory è dove le attività scaricano il codice sorgente dell'applicazione.
  • Build.ArtifactStagingDirectory è la posizione in cui le attività scaricano gli artefatti necessari per la pipeline o caricano gli artefatti prima della pubblicazione.
  • Build.BinariesDirectory è dove le attività scrivono i relativi output.
  • Common.TestResultsDirectory è dove le attività caricano i risultati dei test.

Le $(Build.ArtifactStagingDirectory) e le $(Common.TestResultsDirectory) vengono sempre eliminate e ricreate prima di ogni compilazione.

Quando si esegue una pipeline in un agente self-hosted, per impostazione predefinita, nessuna delle sottodirectory diverse da $(Build.ArtifactStagingDirectory) e $(Common.TestResultsDirectory) viene pulita tra due esecuzioni consecutive. Di conseguenza, è possibile eseguire compilazioni e distribuzioni incrementali, se le attività vengono implementate per usarle. È possibile eseguire l'override di questo comportamento usando l'impostazione workspace nel processo.

Importante

Le opzioni di pulizia dell'area di lavoro sono applicabili solo per gli agenti self-hosted. I processi vengono sempre eseguiti in un nuovo agente con agenti ospitati da Microsoft.

- job: myJob
  workspace:
    clean: outputs | resources | all # what to clean up before the job runs

Quando si specifica una delle clean opzioni, queste vengono interpretate come segue:

  • outputs: elimina Build.BinariesDirectory prima di eseguire un nuovo processo.
  • resources: elimina Build.SourcesDirectory prima di eseguire un nuovo processo.
  • all: eliminare l'intera Pipeline.Workspace directory prima di eseguire un nuovo processo.
  jobs:
  - deployment: MyDeploy
    pool:
      vmImage: 'ubuntu-latest'
    workspace:
      clean: all
    environment: staging

Nota

A seconda delle funzionalità dell'agente e dei carichi di pipeline, ogni processo può essere instradato a un agente diverso nel pool gestito internamente. Di conseguenza, è possibile ottenere un nuovo agente per le esecuzioni successive della pipeline (o fasi o processi nella stessa pipeline). Pertanto, il fatto che non ci sia pulizia tra e non garantisce che le esecuzioni, i processi o le fasi successive possano accedere agli output di esecuzioni, processi o fasi precedenti. È possibile configurare le funzionalità dell'agente e le richieste di pipeline per determinare quali agenti verranno utilizzati per eseguire un job della pipeline. Tuttavia, a meno che nel pool non sia presente un solo agente che soddisfi le richieste, non esiste alcuna garanzia che i processi successivi usino lo stesso agente dei processi precedenti. Per altre informazioni, vedere Specificare le richieste.

Oltre alla pulizia dell'area di lavoro, è anche possibile configurare la pulizia configurando l'impostazione Pulisci nell'interfaccia utente delle impostazioni della pipeline. Quando l'impostazione Pulisci è true, che è anche il valore predefinito, equivale a specificare clean: true per ogni passaggio di estrazione nella pipeline. Quando si specifica clean: true, esegui git clean -ffdx seguito da git reset --hard HEAD prima di git fetch. Per configurare l'impostazione Pulisci :

  1. Modificare la pipeline, scegliere ...e selezionare Trigger.

    Modificare i trigger.

  2. Selezionare YAML, Recupera origini e configurare l'impostazione Pulisci desiderata. Il valore predefinito è true.

    Impostazione pulita.

Download artefatto

Questo file YAML di esempio pubblica l'artefatto WebSite e quindi scarica l'artefatto in $(Pipeline.Workspace). Il processo Distribuisci viene eseguito solo se il processo di compilazione ha esito positivo.

# test and upload my code as an artifact named WebSite
jobs:
- job: Build
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - script: npm test
  - task: PublishBuildArtifacts@1
    inputs:
      pathtoPublish: '$(System.DefaultWorkingDirectory)'
      artifactName: WebSite

# download the artifact and deploy it only if the build job succeeded
- job: Deploy
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - checkout: none #skip checking out the default repository resource
  - task: DownloadBuildArtifacts@0
    displayName: 'Download Build Artifacts'
    inputs:
      artifactName: WebSite
      downloadPath: $(Pipeline.Workspace)

  dependsOn: Build
  condition: succeeded()

Per informazioni sull'uso di dependsOn e condizione, vedere Specificare le condizioni.

Accesso al token OAuth

È possibile consentire agli script in esecuzione in un processo di accedere al token di sicurezza OAuth di Azure Pipelines corrente. Il token può essere usato per eseguire l'autenticazione all'API REST di Azure Pipelines.

Il token OAuth è sempre disponibile per le pipeline YAML. Deve essere mappato in modo esplicito all'attività o al passaggio usando env. Ecco un esempio:

steps:
- powershell: |
    $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$($env:SYSTEM_DEFINITIONID)?api-version=4.1-preview"
    Write-Host "URL: $url"
    $pipeline = Invoke-RestMethod -Uri $url -Headers @{
      Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
    }
    Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
  env:
    SYSTEM_ACCESSTOKEN: $(system.accesstoken)

Passaggi successivi