Especificar trabalhos no pipeline
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
Você pode organizar seu pipeline em trabalhos. Cada pipeline tem pelo menos um trabalho. Um trabalho é uma série de etapas que são executadas sequencialmente como uma unidade. Em outras palavras, um trabalho é a menor unidade de trabalho que pode ser programada para ser executada.
Para saber mais sobre os principais conceitos e componentes que compõem um pipeline, consulte Conceitos-chave para novos usuários do Azure Pipelines.
O Azure Pipelines não oferece suporte à prioridade de trabalho para pipelines YAML. Para controlar quando os trabalhos são executados, você pode especificar condições e dependências.
Definir um único trabalho
No caso mais simples, um pipeline tem um único trabalho. Nesse caso, você não precisa usar explicitamente a job
palavra-chave, a menos que esteja usando um modelo. Você pode especificar diretamente as etapas em seu arquivo YAML.
Este arquivo YAML tem um trabalho que é executado em um agente hospedado pela Microsoft e saídas Hello world
.
pool:
vmImage: 'ubuntu-latest'
steps:
- bash: echo "Hello world"
Talvez você queira especificar mais propriedades nesse trabalho. Nesse caso, você pode usar a job
palavra-chave.
jobs:
- job: myJob
timeoutInMinutes: 10
pool:
vmImage: 'ubuntu-latest'
steps:
- bash: echo "Hello world"
Seu pipeline pode ter vários trabalhos. Nesse caso, use a jobs
palavra-chave.
jobs:
- job: A
steps:
- bash: echo "A"
- job: B
steps:
- bash: echo "B"
Seu pipeline pode ter vários estágios, cada um com vários trabalhos. Nesse caso, use a stages
palavra-chave.
stages:
- stage: A
jobs:
- job: A1
- job: A2
- stage: B
jobs:
- job: B1
- job: B2
A sintaxe completa para especificar um trabalho é:
- 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
A sintaxe completa para especificar um trabalho é:
- 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 a intenção principal do seu trabalho for implantar seu aplicativo (em vez de criar ou testar seu aplicativo), você poderá usar um tipo especial de trabalho chamado trabalho de implantação.
A sintaxe de um trabalho de implantação é:
- deployment: string # instead of job keyword, use deployment keyword
pool:
name: string
demands: string | [ string ]
environment: string
strategy:
runOnce:
deploy:
steps:
- script: echo Hi!
Embora você possa adicionar etapas para tarefas de implantação em um job
, recomendamos que, em vez disso, use um trabalho de implantação. Um trabalho de implantação tem alguns benefícios. Por exemplo, você pode implantar em um ambiente, o que inclui benefícios como poder ver o histórico do que você implantou.
Tipos de empregos
Os trabalhos podem ser de diferentes tipos, dependendo de onde são executados.
- Os trabalhos de conjunto de agentes são executadas num agente num conjunto de agentes.
- Os trabalhos de servidor são executadas no Azure DevOps Server.
- Os trabalhos de contentor são executadas num contentor num agente num conjunto de agentes. Para obter mais informações sobre como escolher contêineres, consulte Definir trabalhos de contêiner.
Trabalhos no pool de agentes
Esses são os tipos mais comuns de trabalhos e são executados em um agente em um pool de agentes.
- Ao usar agentes hospedados pela Microsoft, cada trabalho em um pipeline recebe um novo agente.
- Use demandas com agentes auto-hospedados para especificar quais recursos um agente deve ter para executar seu trabalho. Você pode obter o mesmo agente para trabalhos consecutivos, dependendo se há mais de um agente em seu pool de agentes que corresponda às demandas do seu pipeline. Se houver apenas um agente em seu pool que corresponda às demandas do pipeline, o pipeline aguardará até que esse agente esteja disponível.
Nota
As demandas e os recursos são projetados para uso com agentes auto-hospedados para que os trabalhos possam ser combinados com um agente que atenda aos requisitos do trabalho. Ao usar agentes hospedados pela Microsoft, você seleciona uma imagem para o agente que corresponde aos requisitos do trabalho, portanto, embora seja possível adicionar recursos a um agente hospedado pela Microsoft, não é necessário usar recursos com agentes hospedados pela 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
Ou várias demandas:
pool:
name: myPrivateAgents
demands:
- agent.os -equals Darwin
- anotherCapability -equals somethingElse
steps:
- script: echo hello world
Saiba mais sobre os recursos do agente.
Trabalhos no servidor
As tarefas em um trabalho de servidor são orquestradas e executadas no servidor (Azure Pipelines ou TFS). Um trabalho de servidor não requer um agente ou nenhum computador de destino. Apenas algumas tarefas são suportadas em um trabalho de servidor agora. O tempo máximo para um trabalho de servidor é de 30 dias.
Tarefas suportadas por trabalhos sem agente
Atualmente, apenas as seguintes tarefas são suportadas imediatamente para trabalhos sem agente:
- Tarefa de atraso
- Invocar a tarefa Azure Function
- Invocar tarefa da API REST
- Tarefa de validação manual
- Tarefa Publicar no Barramento de Serviço do Azure
- Tarefa Consultar Alertas do Azure Monitor
- Tarefa Consultar Itens de Trabalho
Como as tarefas são extensíveis, você pode adicionar mais tarefas sem agente usando extensões. O tempo limite padrão para trabalhos sem agente é de 60 minutos.
A sintaxe completa para especificar um trabalho de servidor é:
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
Você também pode usar a sintaxe simplificada:
jobs:
- job: string
pool: server # note: the value 'server' is a reserved keyword which indicates this is an agentless job
Dependências
Ao definir vários trabalhos em um único estágio, você pode especificar dependências entre eles. Os pipelines devem conter pelo menos um trabalho sem dependências. Por padrão, os trabalhos de pipeline YAML do Azure DevOps são executados em paralelo, a menos que o dependsOn
valor seja definido.
Nota
Cada agente pode executar apenas um trabalho de cada vez. Para executar vários trabalhos em paralelo, você deve configurar vários agentes. Você também precisa de trabalhos paralelos suficientes.
A sintaxe para definir vários trabalhos e suas dependências é:
jobs:
- job: string
dependsOn: string
condition: string
Exemplos de trabalhos que são criados sequencialmente:
jobs:
- job: Debug
steps:
- script: echo hello from the Debug build
- job: Release
dependsOn: Debug
steps:
- script: echo hello from the Release build
Exemplos de trabalhos que são criados em paralelo (sem dependências):
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
Exemplo de 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
Exemplo de 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
Condições
Você pode especificar as condições sob as quais cada tarefa é executada. Por padrão, um trabalho é executado se não depender de nenhum outro trabalho ou se todos os trabalhos dos quais ele depende tiverem sido concluídos e bem-sucedidos. Você pode personalizar esse comportamento forçando a execução de um trabalho mesmo se um trabalho anterior falhar ou especificando uma condição personalizada.
Exemplo para executar um trabalho com base no status de execução de um trabalho anterior:
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
Exemplo de utilização de uma condição personalizada:
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
Você pode especificar que um trabalho seja executado com base no valor de uma variável de saída definida em um trabalho anterior. Nesse caso, você só pode usar variáveis definidas em trabalhos diretamente dependentes:
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
Tempos limite
Para evitar a utilização de recursos quando o trabalho não responde ou aguarda demasiado tempo, o ideal é definir um limite para o tempo de execução do trabalho. Utilize a definição de tempo limite do trabalho para especificar o limite em minutos para executar o trabalho. Definir o valor como zero significa que o trabalho pode ser executado:
- Para sempre em agentes auto-hospedados
- Por 360 minutos (6 horas) em agentes hospedados pela Microsoft com um projeto público e repositório público
- Por 60 minutos em agentes hospedados pela Microsoft com um projeto privado ou repositório privado (a menos que a capacidade adicional seja paga)
O período de tempo limite começa quando o trabalho começa a ser executado. Ele não inclui o tempo que o trabalho está na fila ou aguardando por um agente.
O timeoutInMinutes
permite que um limite seja definido para o tempo de execução do trabalho. Quando não especificado, o padrão é 60 minutos. Quando 0
é especificado, o limite máximo é usado (descrito acima).
O cancelTimeoutInMinutes
permite que um limite seja definido para o tempo de cancelamento do trabalho quando a tarefa de implantação é definida para continuar em execução se uma tarefa anterior falhar. Quando não especificado, o padrão é 5 minutos. O valor deve estar no intervalo de 1 a 35790 minutos.
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
Os tempos limite têm o seguinte nível de precedência.
- Em agentes hospedados pela Microsoft, os trabalhos são limitados em quanto tempo podem ser executados com base no tipo de projeto e se são executados usando um trabalho paralelo pago. Quando o intervalo de tempo limite do trabalho hospedado pela Microsoft expira, o trabalho é encerrado. Em agentes hospedados pela Microsoft, os trabalhos não podem ser executados por mais do que esse intervalo, independentemente de qualquer tempo limite de nível de trabalho especificado no trabalho.
- O tempo limite configurado no nível do trabalho especifica a duração máxima para a execução do trabalho. Quando o intervalo de tempo limite do nível de trabalho expira, o trabalho é encerrado. Se o trabalho for executado em um agente hospedado pela Microsoft, definir o tempo limite do nível do trabalho para um intervalo maior do que o tempo limite de nível de trabalho hospedado pela Microsoft interno não terá efeito e o tempo limite do trabalho hospedado pela Microsoft será usado.
- Você também pode definir o tempo limite para cada tarefa individualmente - consulte as opções de controle de tarefa. Se o intervalo de tempo limite do nível do trabalho decorrer antes da conclusão da tarefa, o trabalho em execução será encerrado, mesmo que a tarefa esteja configurada com um intervalo de tempo limite maior.
Configuração de vários trabalhos
A partir de um único trabalho criado, você pode executar vários trabalhos em vários agentes em paralelo. Alguns exemplos incluem:
Compilações de várias configurações: você pode criar várias configurações em paralelo. Por exemplo, você pode criar um aplicativo Visual C++ para ambas as
debug
configurações erelease
x64
em ambas asx86
plataformas. Para obter mais informações, consulte Visual Studio Build - várias configurações para várias plataformas.Implantações multiconfiguração: você pode executar várias implantações em paralelo, por exemplo, para diferentes regiões geográficas.
Teste de várias configurações: você pode executar várias configurações de teste em paralelo.
A multiconfiguração sempre gerará pelo menos um trabalho, mesmo que uma variável de multiconfiguração esteja vazia.
A matrix
estratégia permite que um trabalho seja despachado várias vezes, com diferentes conjuntos de variáveis. A maxParallel
tag restringe a quantidade de paralelismo. O trabalho a seguir é enviado três vezes com os valores de Localização e Navegador definidos conforme especificado. No entanto, apenas dois trabalhos são executados ao mesmo tempo.
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
Os nomes de configuração da matriz (como US_IE
acima) devem conter apenas letras básicas do alfabeto latino (A-Z, a-z), números e sublinhados (_
).
O nome tem de começar por uma letra.
Além disso, eles devem ter 100 caracteres ou menos.
Também é possível usar variáveis de saída para gerar uma matriz. Isso pode ser útil se você precisar gerar a matriz usando um script.
matrix
aceita uma expressão de tempo de execução contendo um objeto JSON stringified.
Esse objeto JSON, quando expandido, deve corresponder à sintaxe de matriz.
No exemplo abaixo, codificamos a cadeia de caracteres JSON, mas ela pode ser gerada por uma linguagem de script ou programa de linha de 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
Fatiamento
Um trabalho de agente pode ser usado para executar um conjunto de testes em paralelo. Por exemplo, você pode executar um grande conjunto de 1000 testes em um único agente. Ou, você pode usar dois agentes e executar 500 testes em cada um em paralelo.
Para aplicar o fatiamento, as tarefas no trabalho devem ser inteligentes o suficiente para entender a fatia a que pertencem.
A tarefa de teste do Visual Studio é uma dessas tarefas que oferece suporte ao fatiamento de teste. Se você instalou vários agentes, você pode especificar como a tarefa de teste do Visual Studio é executada em paralelo nesses agentes.
A parallel
estratégia permite que um trabalho seja duplicado muitas vezes.
Variáveis System.JobPositionInPhase
e System.TotalJobsInPhase
são adicionadas a cada trabalho. As variáveis podem ser usadas em seus scripts para dividir o trabalho entre os trabalhos.
Consulte Execução paralela e múltipla usando trabalhos de agente.
O trabalho a seguir é despachado cinco vezes com os valores de System.JobPositionInPhase
e System.TotalJobsInPhase
definido adequadamente.
jobs:
- job: Test
strategy:
parallel: 5
Variáveis de trabalho
Se você estiver usando YAML, as variáveis podem ser especificadas no trabalho. As variáveis podem ser passadas para entradas de tarefas usando a sintaxe de macro $(variableName) ou acessadas dentro de um script usando a variável stage.
Aqui está um exemplo de como definir variáveis em um trabalho e usá-las dentro de tarefas.
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"
Para obter informações sobre como usar uma condição, consulte Especificar condições.
Área de trabalho
Quando você executa um trabalho de pool de agentes, ele cria um espaço de trabalho no agente. O espaço de trabalho é um diretório no qual ele baixa a fonte, executa etapas e produz saídas. O diretório do espaço de trabalho pode ser referenciado em seu trabalho usando Pipeline.Workspace
a variável. Sob isso, vários subdiretórios são criados:
Build.SourcesDirectory
é onde as tarefas baixam o código-fonte do aplicativo.Build.ArtifactStagingDirectory
é onde as tarefas baixam artefatos necessários para o pipeline ou carregam artefatos antes de serem publicados.Build.BinariesDirectory
é onde as tarefas escrevem suas saídas.Common.TestResultsDirectory
é onde as tarefas carregam seus resultados de teste.
Os $(Build.ArtifactStagingDirectory)
e $(Common.TestResultsDirectory)
são sempre excluídos e recriados antes de cada compilação.
Quando você executa um pipeline em um agente auto-hospedado, por padrão, nenhum dos subdiretórios além $(Build.ArtifactStagingDirectory)
de e $(Common.TestResultsDirectory)
é limpo entre duas execuções consecutivas. Como resultado, você pode fazer compilações e implantações incrementais, desde que as tarefas sejam implementadas para fazer uso disso. Você pode substituir esse comportamento usando a workspace
configuração no trabalho.
Importante
As opções de limpeza do espaço de trabalho são aplicáveis apenas para agentes auto-hospedados. Os trabalhos são sempre executados em um novo agente com agentes hospedados pela Microsoft.
- job: myJob
workspace:
clean: outputs | resources | all # what to clean up before the job runs
Quando você especifica uma das clean
opções, elas são interpretadas da seguinte forma:
outputs
: ExcluirBuild.BinariesDirectory
antes de executar um novo trabalho.resources
: ExcluirBuild.SourcesDirectory
antes de executar um novo trabalho.all
: Exclua todoPipeline.Workspace
o diretório antes de executar um novo trabalho.
jobs:
- deployment: MyDeploy
pool:
vmImage: 'ubuntu-latest'
workspace:
clean: all
environment: staging
Nota
Dependendo dos recursos do agente e das demandas de pipeline, cada trabalho pode ser roteado para um agente diferente em seu pool auto-hospedado. Como resultado, você pode obter um novo agente para execuções de pipeline subsequentes (ou estágios ou trabalhos no mesmo pipeline), portanto , não limpar não é uma garantia de que execuções, trabalhos ou estágios subsequentes poderão acessar saídas de execuções, trabalhos ou estágios anteriores. Você pode configurar os recursos do agente e as demandas de pipeline para especificar quais agentes são usados para executar um trabalho de pipeline, mas a menos que haja apenas um único agente no pool que atenda às demandas, não há garantia de que os trabalhos subsequentes usarão o mesmo agente que os trabalhos anteriores. Para obter mais informações, consulte Especificar demandas.
Além da limpeza do espaço de trabalho, você também pode configurar a limpeza definindo a configuração Limpar na interface do usuário de configurações do pipeline. Quando a configuração Limpar é true, que também é seu valor padrão, é equivalente a especificar clean: true
para cada etapa de checkout em seu pipeline. Quando você especificar clean: true
, você executará git clean -ffdx
seguido por git reset --hard HEAD
antes da busca do git. Para definir a configuração Limpar :
Edite seu pipeline, escolha ..., e selecione Triggers.
Selecione YAML, Obter fontes e configure a configuração Limpar desejada. O padrão é true.
Download do artefato
Este arquivo YAML de exemplo publica o artefato WebSite
e, em seguida, baixa o artefato para $(Pipeline.Workspace)
. O trabalho Implantar só será executado se o trabalho Construir for bem-sucedido.
# 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()
Para obter informações sobre como usar dependsOn e condition, consulte Especificar condições.
Acesso ao token OAuth
Você pode permitir que scripts executados em um trabalho acessem o token de segurança OAuth do Azure Pipelines ou TFS atual. O token pode ser usado para autenticar na API REST do Azure Pipelines.
O token OAuth está sempre disponível para pipelines YAML.
Ele deve ser explicitamente mapeado na tarefa ou etapa usando env
.
Eis um exemplo:
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)