Zadání úloh v kanálu

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Kanál můžete uspořádat do úloh. Každý kanál má alespoň jednu úlohu. Úloha je řada kroků, které se sekvenčně spouští jako jednotka. Jinými slovy, úloha je nejmenší jednotkou práce, kterou je možné naplánovat ke spuštění.

Informace o klíčových konceptech a komponentách, které tvoří kanál, najdete v tématu Klíčové koncepty pro nové uživatele Azure Pipelines.

Azure Pipelines nepodporuje prioritu úlohy pro kanály YAML. Pokud chcete řídit, kdy se úlohy spustí, můžete zadat podmínky a závislosti.

Definování jedné úlohy

V nejjednodušším případě má kanál jednu úlohu. V takovém případě nemusíte klíčové slovo explicitně používat job , pokud nepoužíváte šablonu. Kroky v souboru YAML můžete zadat přímo.

Tento soubor YAML má úlohu, která běží na agentu hostovaného Microsoftem a výstupech Hello world.

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

V této úloze můžete zadat více vlastností. V takovém případě můžete použít job klíčové slovo.

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

Váš kanál může mít více úloh. V takovém případě použijte jobs klíčové slovo.

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

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

Váš kanál může mít několik fází, z nichž každý má více úloh. V takovém případě použijte stages klíčové slovo.

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

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

Úplná syntaxe pro zadání úlohy je:

- 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

Úplná syntaxe pro zadání úlohy je:

- 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

Pokud primárním záměrem vaší úlohy je nasazení aplikace (na rozdíl od sestavení nebo otestování aplikace), můžete použít speciální typ úlohy označované jako úloha nasazení.

Syntaxe úlohy nasazení je:

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

I když můžete přidat kroky pro úlohy nasazení v nástroji job, doporučujeme místo toho použít úlohu nasazení. Úloha nasazení má několik výhod. Můžete například nasadit do prostředí, které zahrnuje výhody, jako je zobrazení historie nasazených prostředků.

Typy úloh

Úlohy můžou být různé typy v závislosti na tom, kde běží.

  • Úlohy fondu agentů běží na agentovi ve fondu agentů.
  • Úlohy serveru běží na Azure DevOps Serveru.
  • Úlohy kontejneru se běží v kontejneru v agentovi ve fondu agentů. Další informace o výběru kontejnerů najdete v tématu Definování úloh kontejneru.
  • Úlohy fondu agentů běží na agentovi ve fondu agentů.
  • Úlohy serveru běží na Azure DevOps Serveru.

Úlohy fondu agentů

Jedná se o nejběžnější typ úloh, které běží na agentu ve fondu agentů.

  • Když používáte agenty hostované Microsoftem, každá úloha v kanálu získá nového agenta.
  • Pomocí požadavků u agentů v místním prostředí určete, jaké schopnosti musí agent spouštět vaši úlohu. Stejný agent můžete získat pro po sobě jdoucí úlohy v závislosti na tom, jestli ve fondu agentů existuje více než jeden agent, který odpovídá požadavkům vašeho kanálu. Pokud je ve vašem fondu jenom jeden agent, který odpovídá požadavkům kanálu, kanál počká, dokud tento agent nebude dostupný.

Poznámka:

Požadavky a možnosti jsou navržené pro použití s agenty v místním prostředí, aby se úlohy mohly shodovat s agentem, který splňuje požadavky úlohy. Při použití agentů hostovaných Microsoftem vyberete image agenta, která odpovídá požadavkům úlohy, takže i když je možné přidat funkce do agenta hostovaného Microsoftem, nemusíte používat funkce s agenty hostovanými Microsoftem.

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

Nebo více požadavků:

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

Přečtěte si další informace o možnostech agenta.

Úlohy serveru

Úlohy v úloze serveru jsou orchestrovány a spouštěny na serveru (Azure Pipelines nebo TFS). Úloha serveru nevyžaduje agenta ani žádné cílové počítače. V úloze serveru se teď podporuje jenom několik úkolů. Maximální doba pro úlohu serveru je 30 dnů.

Podporované úlohy bez agentů

V současné době jsou pro úlohy bez agentů podporovány pouze následující úlohy:

Vzhledem k tomu, že jsou úlohy rozšiřitelné, můžete přidat další úlohy bez agentů pomocí rozšíření. Výchozí časový limit pro úlohy bez agentů je 60 minut.

Úplná syntaxe pro zadání úlohy serveru je:

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

Můžete také použít zjednodušenou syntaxi:

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

Závislosti

Když v jedné fázi definujete více úloh, můžete mezi nimi zadat závislosti. Kanály musí obsahovat alespoň jednu úlohu bez závislostí. Ve výchozím nastavení se úlohy kanálu YAML Azure DevOps spouští paralelně, pokud není nastavená dependsOn hodnota.

Poznámka:

Každý agent může současně spustit pouze jednu úlohu. Pokud chcete paralelně spustit více úloh, musíte nakonfigurovat více agentů. Potřebujete také dostatek paralelních úloh.

Syntaxe pro definování více úloh a jejich závislostí je:

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

Ukázkové úlohy, které se sestavují postupně:

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

Ukázkové úlohy, které se vytvářejí paralelně (bez závislostí):

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

Příklad ven ventilátoru:

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

Příklad ventilátoru:

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

Podmínky

Můžete zadat podmínky, za kterých se každá úloha spouští. Ve výchozím nastavení se úloha spustí, pokud nezávisí na žádné jiné úloze nebo na všech úlohách, na kterých závisí, jestli jsou dokončené a úspěšné. Toto chování můžete přizpůsobit vynucením spuštění úlohy, i když předchozí úloha selže nebo zadáte vlastní podmínku.

Příklad spuštění úlohy na základě stavu spuštění předchozí úlohy:

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

Příklad použití vlastní podmínky:

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

Můžete určit, že se úloha spustí na základě hodnoty výstupní proměnné nastavené v předchozí úloze. V tomto případě můžete použít pouze proměnné nastavené v přímo závislých úlohách:

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

Časové limity

Abyste se vyhnuli zabírání prostředků, když úloha nereaguje nebo čeká příliš dlouho, je vhodné nastavit limit doby, po kterou může vaše úloha běžet. Pomocí nastavení časového limitu úlohy určete limit pro spuštění úlohy v minutách. Nastavení hodnoty na nulu znamená, že úloha může běžet:

  • Navždy na agentech v místním prostředí
  • 360 minut (6 hodin) na agentech hostovaných Microsoftem s veřejným projektem a veřejným úložištěm
  • 60 minut na agentech hostovaných Microsoftem s privátním projektem nebo privátním úložištěm (pokud není placená další kapacita )

Období časového limitu začíná při spuštění úlohy. Nezahrnuje čas, kdy je úloha zařazená do fronty nebo čeká na agenta.

Umožňuje timeoutInMinutes nastavit limit pro dobu provádění úlohy. Pokud není zadáno, výchozí hodnota je 60 minut. Po 0 zadání se použije maximální limit (popsaný výše).

Umožňuje cancelTimeoutInMinutes nastavit limit pro čas zrušení úlohy, když je úloha nasazení nastavena tak, aby běžela, pokud předchozí úloha selhala. Pokud není zadáno, výchozí hodnota je 5 minut. Hodnota by měla být v rozsahu od 1 do 35790 minut.

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

Časové limity mají následující úroveň priority.

  1. U agentů hostovaných Microsoftem jsou úlohy omezené na dobu, po kterou se můžou spouštět na základě typu projektu a jestli běží pomocí placené paralelní úlohy. Po uplynutí intervalu časového limitu úlohy hostované Microsoftem se úloha ukončí. U agentů hostovaných Microsoftem nemůžou úlohy běžet déle, než je tento interval, bez ohledu na vypršení časových limitů na úrovni úloh zadaných v úloze.
  2. Časový limit nakonfigurovaný na úrovni úlohy určuje maximální dobu trvání spuštění úlohy. Po uplynutí časového limitu na úrovni úlohy se úloha ukončí. Pokud je úloha spuštěná na agentu hostovaného Microsoftem, nastavení časového limitu na úrovni úlohy na interval větší než časový limit na úrovni předdefinované úlohy hostované Microsoftem nemá žádný vliv a použije se časový limit úlohy hostované Microsoftem.
  3. Časový limit pro každý úkol můžete nastavit také jednotlivě – viz možnosti řízení úkolů. Pokud časový limit na úrovni úlohy uplynul před dokončením úkolu, je spuštěná úloha ukončena, i když je úkol nakonfigurovaný s delším časovým limitem.

Konfigurace více úloh

Z jedné úlohy, kterou vytvoříte, můžete paralelně spouštět více úloh na více agentech. Mezi některé příklady patří:

  • Sestavení s více konfiguracemi: Můžete paralelně sestavit více konfigurací. Můžete například vytvořit aplikaci Visual C++ pro obě debug i release konfigurace na obou x86 x64 platformách. Další informace najdete v tématu Visual Studio Build – více konfigurací pro více platforem.

  • Nasazení s více konfiguracemi: Můžete paralelně spouštět více nasazení, například do různých geografických oblastí.

  • Vícekonfigurační testování: Můžete paralelně spustit test více konfigurací.

  • Více konfigurací vždy vygeneruje aspoň jednu úlohu, i když je proměnná s více konfiguracemi prázdná.

Strategie matrix umožňuje vícenásobně odesílat úlohu s různými sadami proměnných. Značka maxParallel omezuje množství paralelismu. Následující úloha se odešle třikrát s hodnotami umístění a prohlížeče nastaveným podle zadaného nastavení. Současně však běží jenom dvě úlohy.

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

Poznámka:

Názvy konfigurací matice (například US_IE výše) musí obsahovat pouze základní písmena latinky (A-Z, a-z), číslice a podtržítka (_). Musí začínat písmenem. Musí mít také 100 znaků nebo méně.

K vygenerování matice je také možné použít výstupní proměnné. To může být užitečné, pokud potřebujete generovat matici pomocí skriptu.

matrix přijímá výraz modulu runtime obsahující řetězecifikovaný objekt JSON. Tento objekt JSON při rozbalení musí odpovídat syntaxi matice. V následujícím příkladu jsme pevně naprogramovali řetězec JSON, ale může ho vygenerovat skriptovací jazyk nebo program příkazového řádku.

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

Krájení

Úlohu agenta lze použít ke paralelnímu spuštění sady testů. Můžete například spustit velkou sadu 1 000 testů na jednom agentu. Nebo můžete použít dva agenty a spustit na každém z nich paralelně 500 testů.

Aby bylo možné použít řezy, měly by být úkoly v úloze dostatečně inteligentní, aby porozuměly řezu, do které patří.

Úloha Visual Studio Test je jednou z takových úloh, která podporuje řezy testů. Pokud jste nainstalovali více agentů, můžete určit, jak se úloha Visual Studio Test spustí paralelně na těchto agentech.

Strategie parallel umožňuje úlohu duplikovat mnohokrát. System.JobPositionInPhase Proměnné a System.TotalJobsInPhase přidají se do každé úlohy. Proměnné se pak dají použít ve vašich skriptech k rozdělení práce mezi úlohy. Viz Paralelní a více spuštění pomocí úloh agenta.

Následující úloha se odešle pětkrát s hodnotami System.JobPositionInPhase a System.TotalJobsInPhase nastavenými odpovídajícím způsobem.

jobs:
- job: Test
  strategy:
    parallel: 5

Proměnné úloh

Pokud používáte YAML, můžete v úloze zadat proměnné. Proměnné lze předat vstupům úkolů pomocí syntaxe makra $(variableName) nebo přistupovat ve skriptu pomocí proměnné fáze.

Tady je příklad definování proměnných v úloze a jejich použití v rámci úkolů.

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"

Informace o použití podmínky naleznete v tématu Zadání podmínek.

Pracovní prostor

Když spustíte úlohu fondu agentů, vytvoří v agentu pracovní prostor. Pracovní prostor je adresář, ve kterém stáhne zdroj, spustí kroky a vytvoří výstupy. Na adresář pracovního prostoru můžete v úloze odkazovat pomocí Pipeline.Workspace proměnné. V tomto případě se vytvoří různé podadresáře:

  • Build.SourcesDirectory je místo, kde úkoly stahuje zdrojový kód aplikace.
  • Build.ArtifactStagingDirectory je místo, kde úkoly stahují artefakty potřebné pro kanál nebo nahrávají artefakty před jejich publikováním.
  • Build.BinariesDirectory je místo, kde úkoly zapisují své výstupy.
  • Common.TestResultsDirectory je místo, kde úkoly nahrávají výsledky testů.

$(Common.TestResultsDirectory) Před každým sestavením se $(Build.ArtifactStagingDirectory) vždy odstraní a znovu vytvoří.

Když kanál spustíte na agentovi v místním prostředí, ve výchozím nastavení se žádný z podadresářů jiný než $(Build.ArtifactStagingDirectory) a $(Common.TestResultsDirectory) nevyčistí se mezi dvěma po sobě jdoucími spuštěními. V důsledku toho můžete provádět přírůstková sestavení a nasazení za předpokladu, že se úlohy implementují, aby se tyto úlohy využily. Toto chování můžete přepsat pomocí workspace nastavení úlohy.

Důležité

Možnosti čištění pracovního prostoru platí jenom pro agenty v místním prostředí. Úlohy se vždy spouštějí na novém agentu s agenty hostovanými Microsoftem.

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

Když zadáte jednu z clean možností, budou interpretovány takto:

  • outputs: Před spuštěním nové úlohy odstraňte Build.BinariesDirectory .
  • resources: Před spuštěním nové úlohy odstraňte Build.SourcesDirectory .
  • all: Před spuštěním nové úlohy odstraňte celý Pipeline.Workspace adresář.
  jobs:
  - deployment: MyDeploy
    pool:
      vmImage: 'ubuntu-latest'
    workspace:
      clean: all
    environment: staging

Poznámka:

V závislosti na možnostech vašeho agenta a požadavcích kanálu se každá úloha může směrovat na jiného agenta ve vašem místním fondu. V důsledku toho můžete získat nového agenta pro následná spuštění kanálu (nebo fáze nebo úlohy ve stejném kanálu), takže čištění není zárukou, že následné spuštění, úlohy nebo fáze budou mít přístup k výstupům z předchozích spuštění, úloh nebo fází. Můžete nakonfigurovat možnosti agenta a požadavky na kanály tak, aby určily, kteří agenti se používají ke spuštění úlohy kanálu, ale pokud ve fondu není jenom jeden agent, který splňuje požadavky, není zaručeno, že následné úlohy budou používat stejného agenta jako předchozí úlohy. Další informace naleznete v tématu Zadání požadavků.

Kromě čištění pracovního prostoru můžete také nakonfigurovat čištění tak , že v uživatelském rozhraní nastavení kanálu nakonfigurujete nastavení Vyčistit . Pokud je nastavení Vyčistit pravdivé, což je také jeho výchozí hodnota, je ekvivalentem zadání clean: true pro každý krok rezervace ve vašem kanálu. Když zadáte clean: true, spustíte git clean -ffdx git reset --hard HEAD ho před načtením Gitu. Konfigurace nastavení Vyčistit:

  1. Upravte kanál, zvolte ...a vyberte Aktivační události.

    Úpravy aktivačních událostí

  2. Vyberte YAML, Získat zdroje a nakonfigurujte požadované nastavení Vyčistit . Výchozí hodnota je true.

    Čisté nastavení.

Stažení artefaktů

Tento příklad souboru YAML publikuje artefakt WebSite a pak stáhne artefakt do $(Pipeline.Workspace). Úloha Nasazení se spustí pouze v případě, že je úloha sestavení úspěšná.

# 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()

Informace o použití funkce dependsOn a podmínky naleznete v tématu Zadání podmínek.

Přístup k tokenu OAuth

Skriptům spuštěným v úloze můžete povolit přístup k aktuálnímu tokenu zabezpečení Azure Pipelines nebo TFS OAuth. Token se dá použít k ověření v rozhraní REST API služby Azure Pipelines.

Token OAuth je vždy dostupný pro kanály YAML. Musí být explicitně namapován na úkol nebo krok pomocí env. Tady je příklad:

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)

Co bude dál