(Azure Pipelines) どういったデータがループ(each in)処理に対応しているのか検証してみる
Azure Pipelines で複数回登場するようなタスクなどを Template にまとめると再利用できるため大変便利です。
Template ではeach in
という構文で反復処理(ループ処理)を行うことができます。
ただ、公式ドキュメントはあまり情報が記載されていないため、どういった方法でループ処理ができるのかよくわからないため、いくつかのパターンでループ処理ができるかどうかを検証してみました。
なお、公式ドキュメントは以下を確認してください。
parameters
に文字列配列を渡してループさせる
テンプレート側のparameters
に文字列配列を渡してループさせることができるかどうかを見てみます。
先に結論から言うとこちらは可能です。
反復処理が可能なのは配列やKey-value pair
(steps
やjobs
など)となっており、これを利用することで繰り返しタスクの実行が可能になっています。
(以下参考)
Templates [Iterative insertion] - Azure Pipelines | Microsoft Docs
ループする場合は配列も可能ということですが、例えば文字列配列をparameters
でテンプレートに渡してループ処理を実行することは可能なのでしょうか?
まずは通常よくあるサンプルから見ていきます。
次のようにiterative-string-template.yml
のparameters
で文字列の配列(実際にはobject
型)を指定してループするような構成です。
非常に単純な構成で、これは成功します。
parameters: - name: values type: object default: - "Azure" - "Pipelines" - "Learning" steps: - ${{ each value in parameters.values }}: - script: echo "call ${{ value }}." displayName: script ${{ value }}
trigger: none pool: vmImage: windows-latest jobs: - job: steps: - template: iterative-string-template.yml
ただ、この構成だとループする要素の数が限られているため、可変長の要素をループさせたいような要件には対応できません。 可変長の要素をループさせるような場合は以下のようにすれば良いのでは?と思い、試してみました。
テンプレート側は以下のように書き換えました。
変わったのはparameters
のdefault
です。
parameters: - name: values type: object default: [] steps: - ${{ each value in parameters.values }}: - script: echo "call ${{ value }}." displayName: script ${{ value }}
呼び出し元の yaml は、以下のようにparameters
に文字列配列を指定するように変更しています。
trigger: none pool: vmImage: windows-latest jobs: - job: steps: - template: iterative-string-template.yml parameters: values: ["Azure", "Pipelines", "Learning"]
結果は以下のように成功しています。 スクリプトの呼び出しだけなのでパット見はわかりませんが…
ただし、これが成功するのはtype
を指定した場合のみ
こちらの方法はあるパターンにおいては失敗します。
それはテンプレート側でparameters
のtype
が指定されていない場合です。
具体的には以下のようなものです。
parameters: - values: [] steps: - ${{ each value in parameters.values }}: - script: echo "call ${{ value }}." displayName: script ${{ value }}
この状態でパイプラインを実行すると以下のようなメッセージが出力されます。yaml Editor で Validate を実行した場合も同様です。
/LearningTemplate/iterative-string-template.yml (Line: 2, Col: 5): Unexpected value 'values'
複雑なデータを渡してループすることもできる
文字列だけなど単一のデータを渡すこともあれば、もっと複雑なデータを渡したいケースはあるかもしれません。 例えば key value pair のような構造のデータを渡してループさせることも可能です。
parameters: - name: keyValuePairs type: object default: [] steps: - ${{ each keyValuePair in parameters.keyValuePairs }}: - script: echo "call ${{ keyValuePair.value.Value }}." displayName: script ${{ keyValuePair.value.Key }}
trigger: none pool: vmImage: windows-latest jobs: - job: steps: - template: iterative-string-template.yml parameters: keyValuePairs: pair1: Key: "number1" Value: "Azure" pair2: Key: "number2" Value: "Pipelines" pair3: Key: "number3" Value: "Learning"
azure-pipelines.yml
からは、Key
とValue
という構造の変数を複数定義しています。
このとき、keyValuePairs
変数は配列のように扱われているようです。
iterative-string-template.yml
では、each
ディレクティブでkeyValuePairs
の反復処理を行い、keyValuePair.value
とすることでpair1
やpair2
のデータを参照しています。
つまり、keyValuePair.value.Value
はループ1回目はkeyValuePair.pair1.Value
を参照し、ループ2回目はkeyValuePair.pair2.Value
を参照していることになります。
データ構造が複雑になるとその分 yaml も可読性が下がりますが、こういった機能が必要になるケースもあるかもしれません。
テンプレートを利用して反復処理をしたいようなケースはよくあると思うので、実際に要件にあった方法が実現できるかどうかは検証してみなければわかりません。 今回試した方法であれば割と柔軟に色々なパターンに適応できると思います。