在管道中指定作业

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 中的生成管道不支持作业。

注意

必须安装 Update 2,以在 TFS 2017 的发布管道中使用作业。 生成管道中的作业在 Azure Pipelines TFS 2018.2 及更高版本中可用。

定义单个作业

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

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

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 ,但我们建议你改为使用部署 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。

详细了解 代理功能

服务器作业

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

无代理作业支持的任务

目前,无代理作业仅支持下列任务:

因为任务是可扩展的,所以你可以使用扩展添加更多无代理任务。 无代理作业的默认超时为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

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

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

多作业配置

通过创作的单个作业,可以在多个代理上并行运行多个作业。 一些示例如下:

  • 多配置生成: 可以并行生成多个配置。 例如,可以 debugrelease 在和平台上构建和配置 Visual C++ 应用 x86x64 。 若要了解详细信息,请参阅为多个平台 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 对象必须与 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 任务上载其测试结果的位置。

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

如果在 自承载代理上运行管道,则默认情况下,除和外的任何子目录 $(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 在运行新作业之前删除整个目录。
  jobs:
  - deployment: deploy
    pool:
      vmImage: 'ubuntu-latest'
    workspace:
      clean: all
    environment: staging

注意

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

除了工作区清理以外,还可以通过在 "管道设置" UI 中配置 " 清除 " 设置来配置清理。 当 " 清除 " 设置为 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-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。

后续步骤