かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Azure DevOps のパイプラインのテンプレートを使ってみた

昨日は、べたっとパイプラインを書きました。

blog.okazuki.jp

そして、横浜さんのブログを読んでるとテンプレートなるものが出てきてますね。

blog.beachside.dev

ドキュメントとしては以下の部分ですね。

docs.microsoft.com

テンプレート

パイプラインを小さな単位に分割して、それを別のファイルから参照するような仕組みですね。大きなパイプラインを分割して見通しをよくしたり、複数個のパイプラインで同じような処理をするときに再利用可能な形で使うことが出来そうです。

ではやってみましょう。

Hello world

何事もハローワールドから。テンプレートの書きかたは、parameters というものに外部から渡したいパラメーターを定義して、その上で中身を書いていく感じ。適当なリポジトリーを Azure Repos 上に作って templates/helloworld-template.yml という名前で以下のようなファイルを作りました。

parameters:
- name: message
  type: string
  default: Hello world

steps:
- script: echo ${{ parameters.message }}

これで message というパラメーターを受け取って、それを echo で出力するテンプレートが出来ました。では、実際にパイプラインから使ってみましょう。適当にパイプラインを作って以下のような内容にします。テンプレートを読み込むには steps や jobs とかで template で指定します。横浜さんのブログによると、パイプラインのあるフォルダーからの相対パスでテンプレートを指定するみたいです。ルートからのパスじゃないということに気を付けないとですね。

trigger: none

pool:
  vmImage: 'ubuntu-latest'

steps:
- template: templates/helloworld-template.yml

実行すると Hello world が出ました。

f:id:okazuki:20200224095148p:plain

パラメーターを渡す場合は - template: に続けて以下のように parameters を追加すれば OK です。

trigger: none

pool:
  vmImage: 'ubuntu-latest'

steps:
- template: templates/helloworld-template.yml
  parameters:
    message: 'こんにちは世界'

実行すると以下のように、ちゃんと「Hello world」だったものが「こんにちは世界」になってますね。

f:id:okazuki:20200224095557p:plain

変数とかも別ファイルに外だしとかできますね。

# templates/variables-template.yml
variables:
- name: message
  value: Hello world


# azure-pipeline.yml
trigger: none

variables:
- template: templates/variables-template.yml

steps:
- script: echo $(message)

上記の例では使ってませんが、ちゃんとこの場合でも parameters が使えます。

もうちょっとドキュメントを参照してみると、以下のように stepList とかみたいに step のリストもパラメーターとして渡すことができるようになってます。

f:id:okazuki:20200224101916p:plain

試してみましょう。templates/steps-template.yml という名前で以下のようなファイルを作ってみました。

parameters:
- name: steps
  type: stepList
  default: []

steps:
- script: echo pre-process
  displayName: pre-process
- ${{ each step in parameters.steps }}:
  - ${{ step }}
- script: echo post-process
  displayName: post-process

そして、azure-pipeline.yml を変更して上のテンプレートを使うようにしました。

trigger: none

pool:
  vmImage: 'ubuntu-latest'

steps:
- template: templates/steps-template.yml
  parameters:
    steps:
    - script: echo Hello world
      displayName: process for English
    - script: echo こんにちは世界
      displayName: process for Japanese

テンプレートに steps という名前のパラメーターを渡していて、そこで echo を 2 つ実行しています。テンプレートでは pre-process を実行してテンプレートで渡されたステップを展開して、 post-process という流れにしてます。実行してみると…

f:id:okazuki:20200224102241p:plain

ちゃんと、思った通りに pre-process → パラメーターで渡したステップ → post-process の順番んで実行されてますね!

ちなみに、今回のようにパイプラインのフローを別のテンプレートで定義して、それをメインのパイプラインから参照する場合は extends を使って以下のようにも書けます。

trigger: none

extends:
  template: templates/steps-template.yml
  parameters:
    steps:
    - script: echo Hello world
      displayName: process for English
    - script: echo こんにちは世界
      displayName: process for Japanese

この場合 pool ってどうやって定義するんだろう?という感じですが、テンプレート側に job 定義すればいけそうですね。ということでテンプレートのほうを以下のようにして windows-latest を指定してみました。

parameters:
- name: steps
  type: stepList
  default: []

jobs:
  - job:
    pool: 
      vmImage: 'windows-latest'
    steps:
    - script: echo pre-process
      displayName: pre-process
    - ${{ each step in parameters.steps }}:
      - ${{ step }}
    - script: echo post-process
      displayName: post-process

これで実行すると、ちゃんと windows-latest になってますね。

f:id:okazuki:20200224103850p:plain

まとめ

ということで、これでテンプレートの再利用が捗りそうです。