在管道中指定作业

Azure Pipelines | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018 | TFS 2017

备注

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

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

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

备注

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

可以将发布管道组织到作业中。 每个发布管道至少具有一个作业。 此版本的 TFS 中的生成管道不支持作业。

备注

必须在 TFS 2017 的发布管道中安装 Update 2 来使用作业。 生成管道中的作业在 Azure Pipelines、TFS 2018.2 和更新版本中可用。

定义单个作业

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

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

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

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

jobs:
- job: myJob
  timeoutInMinutes: 10
  pool:
    vmImage: 'ubuntu-16.04'
  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 托管的代理功能。

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。

依赖项

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

备注

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

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

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: 'vs2017-win2016'
  steps:
  - script: echo hello from Windows
- job: macOS
  pool:
    vmImage: 'macOS-10.14'
  steps:
  - script: echo hello from macOS
- job: Linux
  pool:
    vmImage: 'ubuntu-16.04'
  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

YAML 版本在 TFS 上尚不可用。

条件

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

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

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

YAML 版本在 TFS 上尚不可用。

超时

为避免在作业无响应或等待时间太长时占用资源,最好设置允许运行作业的时间限制。 使用 "作业超时" 设置来指定运行作业的限制(以分钟为单位)。 如果将该值设置为 ,则表示作业可以运行:

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

当作业开始运行时,将开始超时。 它不包括作业排队或等待代理的时间。

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

cancelTimeoutInMinutes如果上一个任务已失败,则在部署任务设置为保持运行状态时,允许设置作业取消时间限制。 如果未指定,则默认值为5分钟。

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 托管代理的作业对它们可能运行的时间有 额外限制

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

多作业配置

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

  • 多配置生成: 可以并行生成多个配置。 例如,可以 debug release 在和平台上构建和配置 Visual C++ 应用 x86 x64 。 若要了解详细信息,请参阅 Visual Studio Build-多个平台的多个配置

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

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

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 对象必须与 matrixing 语法匹配。 在下面的示例中,我们已对 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.JobPositionInPhase将变量和 System.TotalJobsInPhase 添加到每个作业。 然后,可以在脚本中使用变量来在作业之间划分工作。 使用代理作业查看并行和多个执行

以下作业将被调度5次, 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 任务上载其测试结果的位置。

如果在 自承载代理 上运行管道,则默认情况下,在两次连续运行之间不会清理任何子目录。 因此,你可以执行增量生成和部署,前提是实施任务来利用该任务。 您可以使用作业上的设置重写此行为 workspace

重要

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

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

指定其中一个 clean 选项时,这些选项将按如下方式解释:

  • outputsBuild.BinariesDirectory 在运行新作业之前删除。
  • resourcesBuild.SourcesDirectory 在运行新作业之前删除。
  • allPipeline.Workspace 在运行新作业之前删除整个目录。

$(Build.ArtifactStagingDirectory)``$(Common.TestResultsDirectory)始终会在每次生成之前删除和重新创建,而不考虑任何这些设置。

  jobs:
  - deployment: deploy
    pool:
      vmImage: 'Ubuntu-16.04'
    workspace:
      clean: all
    environment: staging

备注

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

除了工作区清理以外,还可以通过在 "管道设置" UI 中配置 " 清除 " 设置来配置清理。 当 " 清除 " 设置为 true 时,它等效于为 clean: true 管道中的每个 结帐 步骤指定。 若要配置 清理 设置:

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

    编辑触发器。

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

    清理设置。

TFS 目前尚不支持 YAML。

项目下载

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

# test and upload my code as an artifact named WebSite
jobs:
- job: Build
  pool:
    vmImage: 'ubuntu-16.04'
  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-16.04'
  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。

后续步骤