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 も可読性が下がりますが、こういった機能が必要になるケースもあるかもしれません。
テンプレートを利用して反復処理をしたいようなケースはよくあると思うので、実際に要件にあった方法が実現できるかどうかは検証してみなければわかりません。 今回試した方法であれば割と柔軟に色々なパターンに適応できると思います。