在管道中指定作业

Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

注意

在 Microsoft Team Foundation Server (TFS) 2018 和更低版本中,生成和发布管道被称为“定义”,运行被称为“生成”,服务连接被称为“服务终结点”,阶段被称为“环境”,而作业被称为“阶段” 。

可以将管道组织到作业中。 每个管道至少有一个作业。 作业是一系列按顺序作为单元运行的步骤。 换句话说,作业是可以计划运行的最小工作单位。

你可以将生成或发布管道整理到作业中。 每个管道至少有一个作业。 作业是一系列按顺序作为单元运行的步骤。 换句话说,作业是可以计划运行的最小工作单位。

注意

必须安装 TFS 2018.2 才能在生成过程中使用作业。 在 TFS 2018 RTM 中,可以在发布部署过程中使用作业。

定义单个作业

最简单的情况下,管道有一个作业。 在这种情况下,除非使用模板,否则无需显式使用job关键字。 可以直接在 YAML 文件中指定步骤。

此 YAML 文件具有在 Microsoft 托管的代理 和输出 Hello world上运行的作业。

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

你可能想要在该作业上指定其他属性。 在这种情况下,可以使用 job 关键字。

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

管道可能有多个作业。 在这种情况下,请使用 jobs 关键字。

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

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

管道可能有多个阶段,每个阶段都有多个作业。 在这种情况下,请使用 stages 关键字。

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

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

指定作业的完整语法为:

- 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

指定作业的完整语法为:

- 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

如果作业的主要目的是部署应用 (而不是生成或测试应用) ,则可以使用称为 部署作业的特殊作业类型。

部署作业的语法为:

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

虽然可以添加部署 job任务的步骤,但建议改用 部署作业。 部署作业有一些好处。 例如,可以部署到环境,其中包括一些好处,例如能够查看已部署内容历史记录。

TFS 不支持 YAML。

作业类型

作业可以是不同类型的作业,具体取决于作业的运行位置。

  • 代理池作业 在代理池中的代理上运行。
  • 服务器作业在Azure DevOps Server上运行。
  • 容器作业 在代理池中的代理上的容器中运行。 有关选择容器的详细信息,请参阅 “定义容器作业”。
  • 代理池作业 在代理池中的代理上运行。
  • 服务器作业在Azure DevOps Server上运行。
  • 代理池作业 在代理池中的代理上运行。 这些作业在生成管道和发布管道中可用。
  • 服务器作业 在 TFS 上运行。 这些作业在生成管道和发布管道中可用。
  • 部署组作业 在部署组中的计算机上运行。 这些作业仅在发布管道中可用。

代理池作业

这些作业是最常见的作业类型,它们在代理池中的代理上运行。

  • 使用 Microsoft 托管的代理时,管道中的每个作业都会获得一个新的代理。
  • 要求 与自承载代理配合使用,指定代理必须具备哪些功能才能运行作业。 对于连续作业,可能会获得相同的代理,具体取决于代理池中是否存在多个与管道需求匹配的代理。 如果池中只有一个与管道需求匹配的代理,则管道将等到此代理可用为止。

注意

需求和功能设计用于自承载代理,以便与满足作业要求的代理匹配。 使用 Microsoft 托管代理时,为符合作业要求的代理选择一个映像,因此,尽管可以将功能添加到 Microsoft 托管的代理,但不需要将功能与 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

或多个要求:

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

TFS 不支持 YAML。

详细了解 代理功能

服务器作业

服务器作业中的任务由服务器 (Azure Pipelines或 TFS) 进行协调和执行。 服务器作业不需要代理或任何目标计算机。 目前,服务器作业仅支持几个任务。

无代理作业支持的任务

目前,对于无代理作业,仅支持以下任务:

由于任务是可扩展的,因此可以使用扩展添加更多的无代理任务。 无代理作业的默认超时时间为 60 分钟。

指定服务器作业的完整语法为:

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

  pool: server

还可以使用简化的语法:

jobs:
- job: string
  pool: server

TFS 不支持 YAML。

依赖项

在单个阶段中定义多个作业时,可以指定它们之间的依赖关系。 Pipelines必须至少包含一个没有依赖项的作业。

注意

每个代理一次只能运行一个作业。 若要并行运行多个作业,必须配置多个代理。 还需要足够的 并行作业

定义多个作业及其依赖项的语法如下:

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

按顺序生成的示例作业:

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

并行生成 (无依赖项的示例作业) :

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

扇出示例:

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

扇入示例:

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

TFS 不支持 YAML。

条件

可以指定每个作业运行的条件。 默认情况下,如果作业不依赖于任何其他作业,或者它依赖的所有作业都已完成并成功,则运行该作业。 可以强制作业运行此行为,即使以前的作业失败或指定自定义条件也是如此。

基于运行上一个作业的状态运行作业的示例:

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

使用 自定义条件的示例:

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

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

可以根据上一个作业中设置的输出变量的值指定作业运行。 在这种情况下,只能使用直接依赖作业中设置的变量:

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

TFS 不支持 YAML。

超时

为了避免在作业无响应或等待太长时占用资源,最好设置允许作业运行多长时间的限制。 使用作业超时设置指定运行作业的分钟数限制。 将值设置为 意味着作业可以运行:

  • 永远在自承载代理上
  • 360 分钟 (6 小时) 使用公共项目和公共存储库的 Microsoft 托管代理
  • 对于具有专用项目或专用存储库的 Microsoft 托管代理的 60 分钟 (,除非为) 支付额外的容量

超时期限从作业开始运行时开始。 它不包括作业排队或正在等待代理的时间。

允许 timeoutInMinutes 为作业执行时间设置限制。 如果未指定,则默认值为 60 分钟。 指定时 0 ,将使用上述) 所述的最大限制 (。

允许 cancelTimeoutInMinutes 在部署任务设置为在上一个任务失败时为作业取消时间设置限制以继续运行。 如果未指定,则默认值为 5 分钟。 该值应介于 135790 分钟之间。

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

TFS 不支持 YAML。

面向 Microsoft 托管代理的作业对运行时间 有额外的限制

还可以单独设置每个任务的超时 - 请参阅 任务控制选项

多作业配置

在创作的单个作业中,可以并行在多个代理上运行多个作业。 示例包括:

  • 多配置生成: 可以并行生成多个配置。 例如,可以为两x86x64debug以及release平台上的配置生成 Visual C++ 应用。 若要了解详细信息,请参阅Visual Studio生成 - 多个平台的多个配置

  • 多配置部署: 可以并行运行多个部署,例如,以不同的地理区域运行。

  • 多配置测试: 可以并行运行测试多个配置。

  • 即使多配置变量为空,多配置也会始终生成至少一个作业。

matrix 策略使作业能够多次调度,并具有不同的变量集。 标记 maxParallel 限制并行度。 以下作业将调度三次,其中指定了“位置”和“浏览器”的值。 但是,只有两个作业同时运行。

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

注意

矩阵配置名称 (如 US_IE 上述) 必须仅包含 A-Z、a-z) 、数字和下划线 ( () _ 的基本拉丁字母字母。 它们必须以字母开头。 此外,它们必须是 100 个字符或更少。

还可以使用 输出变量 生成矩阵。 如果需要使用脚本生成矩阵,这非常有用。

matrix 将接受包含字符串化 JSON 对象的运行时表达式。 展开时,该 JSON 对象必须与矩阵语法匹配。 在下面的示例中,我们硬编码了 JSON 字符串,但它可由脚本语言或命令行程序生成。

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

TFS 不支持 YAML。

切片

代理作业可用于并行运行一组测试。 例如,可以在单个代理上运行包含 1000 个测试的大型套件。 或者,可以使用两个代理并并行运行 500 个测试。

为了利用切片,作业中的任务应该足够聪明,以便了解它们所属的切片。

Visual Studio测试任务是支持测试切片的此类任务。 如果已安装多个代理,可以指定如何对这些代理并行运行Visual Studio测试任务。

parallel 策略使作业可以多次重复。 变量 System.JobPositionInPhaseSystem.TotalJobsInPhase 添加到每个作业。 然后,可以在脚本中使用变量在作业之间划分工作。 请参阅 使用代理作业的并行执行和多个执行

以下作业将调度五次,并相应地设置值System.JobPositionInPhaseSystem.TotalJobsInPhase

jobs:
- job: Test
  strategy:
    parallel: 5

TFS 不支持 YAML。

作业变量

如果使用 YAML,可以在作业上指定变量。 可以使用宏语法 $ (variableName) 传递到任务输入,也可以使用阶段变量在脚本中访问变量。

下面是在作业中定义变量并在任务中使用变量的示例。

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"

TFS 不支持 YAML。

有关使用 条件的信息,请参阅 指定条件

工作区

运行代理池作业时,它会在代理上创建工作区。 工作区是一个目录,在其中下载源、运行步骤并生成输出。 可以使用变量在作业 Pipeline.Workspace 中引用工作区目录。 在此下,将创建各种子目录:

运行代理池作业时,它会在代理上创建工作区。 工作区是一个目录,在其中下载源、运行步骤并生成输出。 可以使用变量在作业 Agent.BuildDirectory 中引用工作区目录。 在此下,将创建各种子目录:

  • Build.SourcesDirectory 是任务下载应用程序的源代码的位置。
  • Build.ArtifactStagingDirectory 是任务在发布之前下载管道或上传项目所需的项目的位置。
  • Build.BinariesDirectory 是任务写入其输出的位置。
  • Common.TestResultsDirectory 是任务上传其测试结果的位置。

$(Common.TestResultsDirectory)每次$(Build.ArtifactStagingDirectory)生成之前,始终会删除并重新创建。

自承载代理上运行管道时,默认情况下,除了在两个连续运行之间未清除的$(Build.ArtifactStagingDirectory)$(Common.TestResultsDirectory)子目录之外,其他任何子目录都不会被清除。 因此,可以执行增量生成和部署,前提是实现任务以使用该任务。 可以使用作业上的设置替代此行为 workspace

重要

工作区清理选项仅适用于自承载代理。 使用 Microsoft 托管代理时,作业始终在新代理上运行。

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

指定其中一个选项 clean 时,它们将解释为:

  • outputs:在运行新作业之前删除 Build.BinariesDirectory
  • resources:在运行新作业之前删除 Build.SourcesDirectory
  • all:在运行新作业之前删除整个 Pipeline.Workspace 目录。
  jobs:
  - deployment: MyDeploy
    pool:
      vmImage: 'ubuntu-latest'
    workspace:
      clean: all
    environment: staging

注意

根据代理功能和管道需求,每个作业都可以路由到自承载池中的其他代理。 因此,可能会为同一管道) 中的后续管道运行 (或阶段或作业获取新的代理,因此 无法 确保后续运行、作业或阶段能够访问先前运行、作业或阶段的输出。 可以配置代理功能和管道要求来指定哪些代理用于运行管道作业,但除非池中只有一个满足需求的代理,否则无法保证后续作业将使用相同的代理与以前的作业。 有关详细信息,请参阅 指定需求

除了工作区清理之外,还可以通过在管道设置 UI 中配置 “清理 ”设置来配置清理。 如果“清理”设置为 true,则等效于为管道中的每个签出步骤指定clean: true。 若要配置 “清理 ”设置,请执行以下操作:

  1. 编辑管道,选择 ...,然后选择 “触发器”。

    Edit triggers.

  2. 选择 YAML获取源并配置所需的 “清理 ”设置。 默认值为 false

    Clean setting.

TFS 不支持 YAML。

项目下载

此示例 YAML 文件发布项目 WebSite ,然后将项目下载到 $(Pipeline.Workspace)。 仅当生成作业成功时,部署作业才会运行。

# 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: $(System.DefaultWorkingDirectory)

  dependsOn: Build
  condition: succeeded()

TFS 不支持 YAML。

有关使用 dependsOn条件的信息,请参阅 指定条件

访问 OAuth 令牌

允许作业中运行的脚本访问当前Azure Pipelines或 TFS OAuth 安全令牌。 令牌可用于对 Azure Pipelines REST API 进行身份验证。

OAuth 令牌始终可用于 YAML 管道。 它必须显式映射到使用 env的任务或步骤中。 下面是一个示例:

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)

TFS 不支持 YAML。

后续步骤