次の方法で共有


パイプラインの条件

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

この記事では、Azure Pipelines のステージ、ジョブ、またはステップを実行する条件と、さまざまな条件を指定する方法について説明します。 ステージ、ジョブ、およびステップの詳細については、「Azure Pipelines の主要な概念」を参照してください。

  • 既定では、ジョブまたはステージが他のジョブまたはステージに依存していない場合、または、そのすべての依存性が終了し成功した場合に、ジョブまたはステージが実行されます。 この要件は、直接の依存関係だけでなく、間接的な依存関係にも適用され、再帰的に計算されます。

  • 既定では、ジョブ内でまだ何も失敗しておらず、その直前のステップが完了した場合に、ステップは実行されます。

この動作をオーバーライドまたはカスタマイズするには、前の依存関係が失敗した場合でも、ステージ、ジョブ、またはステップを強制的に実行するようにするか、カスタム条件を指定します。

Note

この記事では、YAML パイプラインの機能について説明します。 クラシック パイプラインでは、各タスクの [コントロール オプション] 、およびリリース パイプラインのジョブの [追加オプション でタスクまたはジョブを実行する条件を指定できます。

ステージ、ジョブ、またはステップが実行される条件

パイプライン定義 YAML では、ステージ、ジョブ、またはステップを実行する次の条件を指定できます。

  • 同じエージェント プールで以前の直接および間接の依存関係がすべて成功した場合のみに実行。 エージェント プールが異なる場合、これらのステージまたはジョブは同時に実行されます。 YAML に条件が設定されていない場合は、この条件が既定値になります。

  • 実行が取り消された場合を除き、以前の依存関係が失敗した場合でも実行。 この条件の YAML では succeededOrFailed() を使用します。

  • 実行が取り消された場合も含め、以前の依存関係が失敗した場合でも実行。 この条件の YAML では always() を使用します。

  • 前の依存関係が失敗したときのみ実行。 この条件の YAML では failed() を使用します。

  • カスタム条件。

デフォルトでは、ステージ、ジョブ、およびステップは、すべての直接的および間接的な依存関係が成功した場合に実行されます。 この状態は、condition: succeeded() を指定した場合と同じです。 詳細については、「Succeed Status 関数」を参照してください。

ステージ、ジョブまたはステップの condition プロパティを指定する際は、既定の condition: succeeded() が上書きされます。 独自の条件を指定すると、ビルドがキャンセルされた場合でも、ステージ、ジョブ、またはステップが実行される可能性があります。 記述する条件が親ステージまたはジョブの状態を考慮に入れていることを確認してください。

次の YAML の例は、always()failed() の条件を示しています。 依存関係が失敗した場合やビルドがキャンセルされた場合、最初のジョブのステップが実行されます。 2 番目のジョブは、最初のジョブが失敗した場合にのみ実行されます。

jobs:
- job: Foo

  steps:
  - script: echo Hello!
    condition: always() # this step runs, even if the build is canceled

- job: Bar
  dependsOn: Foo
  condition: failed() # this job runs only if Foo fails

また、条件で変数を設定して使用することもできます。 次の例では、isMain 変数を設定して使用し、Build.SourceBranch として main を指定しています。

variables:
  isMain: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]

stages:
- stage: A
  jobs:
  - job: A1
    steps:
      - script: echo Hello Stage A!

- stage: B
  condition: and(succeeded(), eq(variables.isMain, true))
  jobs:
  - job: B1
    steps:
      - script: echo Hello Stage B!
      - script: echo $(isMain)

重要

条件が評価され、ステージ、ジョブ、またはステップを開始するかどうかが決定されます。 したがって、その作業単位内で実行時に計算されたものは何も使用できません。 たとえば、ランタイム式と $[ ] 構文を使用して変数を設定するジョブがある場合、そのジョブのカスタム条件でその変数を使用することはできません。

カスタム条件

組み込みの条件がニーズを満たさない場合は、カスタム条件を指定できます。 YAML パイプライン定義では、条件を式として記述します。

エージェントは、最も内側の関数から始まり、外側に向かって式を評価します。 最終的な結果は、タスク、ジョブ、またはステージを実行するかどうかを決定するブール値です。 構文の完全なガイドについては、「式」を参照してください。

いずれかの条件により、ビルドがキャンセルされた後でもタスクを実行できる場合は、ユーザーが実行をキャンセルした後にこれらのタスクが完了するのに十分な時間を確保できるように、cancel timeout に適切な値を指定します。

ビルドがキャンセルされたときの条件の結果

ビルドをキャンセルしても、そのすべてのステージ、ジョブ、またはステップの実行が停止するわけではありません。 どのステージ、ジョブ、またはステップが実行を停止するかは、指定した条件とパイプラインの実行のどの時点でビルドをキャンセルしたかによって異なります。 ステージ、ジョブ、またはステップの親がスキップされた場合、タスクは条件に関係なく実行されません。

ステージ、ジョブ、またはステップは、その条件が true と評価されるたびに実行されます。 条件でタスクの親の状態が考慮されない場合は、親がキャンセルされた場合でもタスクが実行される場合があります。 ビルドがキャンセルされたときに条件付きのステージ、ジョブ、またはステップを実行するかどうかを制御するには、条件の job status check 関数を含めるようにします。

次の例は、ビルドがキャンセルされたときのステージ、ジョブ、またはステップに設定されたさまざまな条件の結果を示しています。

ステージ例 1

次のパイプラインでは、既定では stage2stage1 に依存しますが、stage1 の状態に関係なく、ソース ブランチが main の場合、stage2 には、実行するように設定されいる condition があります。

main ブランチでビルドをキューし、stage1 の実行中にそれをキャンセルした場合、eq(variables['Build.SourceBranch'], 'refs/heads/main')true と評価されるため、stage2 も引き続き実行されます。

stages:
- stage: stage1
  jobs:
  - job: A
    steps:
      - script: echo 1; sleep 30
- stage: stage2
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
  jobs:
  - job: B
    steps:
      - script: echo 2

ステージ例 2

次のパイプラインでは、デフォルトで、stage2stage1 に依存します。 stage2 のジョブ B には、condition が設定されています。 main ブランチでビルドをキューし、stage1 の実行中に、それをキャンセルすると、条件が true と評価されたジョブが含まれていても stage2 は実行されません。

その理由は、stage2 には既定の condition: succeeded() があり、stage1 がキャンセルされると、false と評価されるためです。 したがって、stage2 はスキップされ、そのジョブは実行されません。

stages:
- stage: stage1
  jobs:
  - job: A
    steps:
      - script: echo 1; sleep 30
- stage: stage2
  jobs:
  - job: B
    condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
    steps:
      - script: echo 2

ステージ例 3

次のパイプラインでは、デフォルトで、stage2stage1 に依存し、ジョブ B 内のステップには、condition が設定されています。

main ブランチでビルドをキューし、stage1 の実行中に、それをキャンセルすると、条件が true と評価されたジョブ B のステップが含まれていても stage2 は実行されません。 その理由は、stage1 がキャンセルされたことに応じて stage2 がスキップされるためです。

stages:
- stage: stage1
  jobs:
  - job: A
    steps:
      - script: echo 1; sleep 30
- stage: stage2
  jobs:
  - job: B
    steps:
      - script: echo 2
        condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')

ジョブ例 1

次の YAML パイプラインでは、ジョブ B は既定でジョブ A に依存しますが、ソース ブランチが main の場合、B には condition が実行されるように設定されます。 main ブランチでビルドをキューし、ジョブ A の実行中にそれをキャンセルした場合、eq(variables['Build.SourceBranch'], 'refs/heads/main')true と評価されるため、ジョブ B も引き続き実行されます。

jobs:
- job: A
  steps:
  - script: sleep 30
- job: B
  dependsOn: A 
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
  steps:
    - script: echo step 2.1

ジョブ A が成功し、ビルド ソースが main ブランチである時のみ、ジョブ B を実行する場合場合は、conditionand(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) にする必要があります。

ジョブ例 2

次のパイプラインでは、ジョブ B は既定でジョブ A に依存します。 main ブランチでビルドをキューし、ジョブ A の実行中にそれをキャンセルすると、そのステップで conditiontrue と評価されていても ジョブ B は実行されません。

その理由は、ジョブ B には既定の condition: succeeded() があり、ジョブ A がキャンセルされると、false と評価されるためです。 そのため、ジョブ B はスキップされ、どのステップも実行されません。

jobs:
- job: A
  steps:
  - script: sleep 30
- job: B
  dependsOn: A 
  steps:
    - script: echo step 2.1
      condition: eq(variables['Build.SourceBranch'], 'refs/heads/main', succeeded())
      

ステップ例

ステップに条件を設定することもできます。

次のパイプラインでは、ステップ 2.3 で、ソース ブランチが main の場合に condition が実行されるように設定されています。 main ブランチでビルドをキューし、ステップ 2.1 または 2.2 の実行中にそれをキャンセルした場合、eq(variables['Build.SourceBranch'], 'refs/heads/main')true と評価されているため、ステップ 2.3 は引き続き実行されます。

steps:
  - script: echo step 2.1
  - script: echo step 2.2; sleep 30
  - script: echo step 2.3
    condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')

条件設定

次の表に、さまざまな結果を生成する condition 設定例を示します。

Note

Release.Artifacts.{artifact-alias}.SourceBranchBuild.SourceBranch と等価です。

希望する結果 条件設定の例
親または前のステージ、ジョブ、またはステップが失敗したかキャンセルされた場合でも、ソース ブランチがメインの場合に実行します。 eq(variables['Build.SourceBranch'], 'refs/heads/main')
ソース ブランチがメインで、親または前のステージ、ジョブ、またはステップが成功した場合に実行します。 and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
ソース ブランチがメインではなく、親または前のステージ、ジョブ、またはステップが成功した場合に実行します。 and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/main'))
親または前のステージ、ジョブまたはステップが成功した場合にユーザー トピック ブランチに対して実行されます。 and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/users/'))
親または前のステージ、ジョブまたはステップが成功した場合、continuous integration (CI) ビルドに対して実行されます。 and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
ビルドが、プル要求のブランチ ポリシーによってトリガーされた場合、および親または前のステージ、ジョブまたはステップが失敗した場合に実行されます。 and(failed(), eq(variables['Build.Reason'], 'PullRequest'))
親または前のステージ、ジョブまたはステップが失敗またはキャンセルされた場合でも、スケジュールされたビルドに対して実行されます。 eq(variables['Build.Reason'], 'Schedule')
親または前のステージ、ジョブまたはステップが失敗またはキャンセルされた場合でも、変数が True に設定されている場合、実行されます。 eq(variables['System.debug'], true)

Note

変数が null (空の文字列) の場合、実行する条件を設定できます。 すべての変数は Azure Pipelines で文字列として扱われるため、空の文字列は次のパイプラインの null と同じです。

variables:
- name: testEmpty
  value: ''

jobs:
  - job: A
    steps:
    - script: echo testEmpty is blank
    condition: eq(variables.testEmpty, '')

条件のパラメータ

パラメーターの拡張は、条件が考慮される前に行われます。 そのため、条件と同じパイプラインでパラメータを宣言する場合は、条件内にパラメータを埋め込むことができます。 parameters.doThing が True であるため、次の YAML のスクリプトが実行されます。

parameters:
- name: doThing
  default: true
  type: boolean

steps:
- script: echo I did a thing
  condition: and(succeeded(), ${{ eq(parameters.doThing, true) }})

前のパイプラインの condition が、succeeded()${{ eq(parameters.doThing, true) }} の 2 つの関数を組み合わせます。 succeeded() 関数は、前のステップが成功したかどうかを確認します。 前のステップが無いため、succeeded() 関数は true を返します。

${{ eq(parameters.doThing, true) }} 関数は、doThing パラメータが true に等しいかどうかを確認します。 doThingの既定値が true であるため、パイプラインで別の値が設定されていない限り、条件は既定で、true を返します。

条件の Template パラメータ

パラメータをテンプレートに渡す際は、テンプレート内でパラメータ値を設定するか、templateContext を使用して、テンプレートにパラメータを渡します

たとえば、次の parameters.yml ファイルは、doThing パラメータと既定値を宣言します。

# parameters.yml
parameters:
- name: doThing
  default: true # value passed to the condition
  type: boolean

jobs:
  - job: B
    steps:
    - script: echo I did a thing
    condition: ${{ eq(parameters.doThing, true) }}

パイプライン コードは、parameters.yml テンプレートを参照します。 パイプラインの出力は、I did a thing となります。これは、パラメータ doThing が True であるためです。

# azure-pipeline.yml
parameters:
- name: doThing
  default: true 
  type: boolean

trigger:
- none

extends:
  template: parameters.yml

Template パラメータ例の詳細については、「テンプレートの利用参照」を参照してください。

後続のジョブ条件で使用されるジョブ出力変数

後続のジョブで変数を使用できるようにし、条件で指定できます。 次のコードのように、isOutput=true を使用して、今後のジョブで利用可能な変数を multi-job output variables としてマークする必要があります。

jobs:
- job: Foo
  steps:
  - bash: |
      echo "This is job Foo."
      echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #set variable doThing to Yes
    name: DetermineResult
- job: Bar
  dependsOn: Foo
  condition: eq(dependencies.Foo.outputs['DetermineResult.doThing'], 'Yes') #map doThing and check the value
  steps:
  - script: echo "Job Foo ran and doThing is Yes."

後続のステップ条件で使用されたステップで作成された変数

今後のステップで利用可能な変数を作成すると、条件で指定できます。 ステップから作成された変数は、既定で今後のステップで使用できますが、multi-job output variables としてマークする必要はありません。

ステップで作成された scoping 変数については、注意すべき重要な点がいくつかあります。

  • ジョブのステップで作成された変数は、同じジョブのステップにスコープされます。
  • ステップで作成された変数は、後続のステップで、環境変数としてのみ利用できます。
  • ステップで作成された変数は、それらを定義するステップでは使用できません。

次の例では、ステップで利用可能なパイプラインを作成し、後続のステップの条件とスクリプトを使用する方法を示しています。

steps:

# This step creates a new pipeline variable: doThing. This variable is available to subsequent steps.
- bash: |
    echo "##vso[task.setvariable variable=doThing]Yes"
  displayName: Step 1

# This step is able to use doThing, so it uses doThing in its condition
- script: |
    # Access the variable from Step 1 as an environment variable.
    echo "Value of doThing (as DOTHING env var): $DOTHING."
  displayName: Step 2
  condition: and(succeeded(), eq(variables['doThing'], 'Yes')) # or and(succeeded(), eq(variables.doThing, 'Yes'))

よく寄せられる質問

以前のジョブがエラーありで成功した場合にジョブをトリガーするにはどうすればよいですか?

前のジョブの結果を条件で使用できます。 たとえば、次の YAML は、条件 eq(dependencies.A.result,'SucceededWithIssues') は、ジョブ B の実行を許可しています。これは、問題があってもジョブ A が成功したからです。

jobs:
- job: A
  displayName: Job A
  continueOnError: true # next job starts even if this one fails
  steps:
  - script: echo Job A ran
  - script: exit 1

- job: B
  dependsOn: A
  condition: eq(dependencies.A.result,'SucceededWithIssues') # targets the result of the previous job 
  displayName: Job B
  steps:
  - script: echo Job B ran

ビルドをキャンセルしましたが、まだ実行中です。 なぜですか?

この問題は、ステージで構成した条件に、job status check 関数が含まれていないために発生します。 この問題を解決するには、ジョブ状態チェック関数を条件に追加します。

ジョブがキュー ステージあるが実行されていない場合に、ジョブをキャンセルすると、他のすべてのステージを含め、ジョブ全体がキャンセルされます。 詳細については、この記事の前半に記載されている「ビルドがキャンセルされた再の条件の結果」を参照してください。