BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人メモ

Multi-stage YAML pipelines で WebApps の Pipeline を構築する ( Azure DevOps )

Azure DevOps の Azure Pipeline が今までの作り方から生まれ変わり Multi-stage YAML pipelines と呼ばれるものになりました(2019年5月の話ですが..)。

Release pipeline も Yaml できっちりかけるようになりました。以前の Builds と Releases のメニューが統合されて Pipeline (下図の2つめの Pipeline )というメニューになってます。

Releases ってメニューは classic のリリースパイプラインって扱いなので Multi-stage でパイプラインを作る際はもう不要です。

f:id:beachside:20190828141614p:plain

公式のドキュメントでも Multi-stage に関係ない古いものには (classic) と付けられているので気を付けて読みましょう。

ところで Multi-stage ってなんやねんと怯えそうですが、 Build とか Release とかが Stage という概念であり、複数の stage を構成するってだけの話です。どう構成するかは(プラクティスはあるけども) pipeline 次第ですね。

今回はASP.NET Core MVC のプロジェクトを作成して Azure DevOps の Repos で管理してるコードに対して、
Multi-stage YAML pipelines で以下のパイプラインを構築します。下図のように 3ステージで構成します。

  1. master ブランチの変更をトリガーにして Build / Test 実施
  2. Azure の WebApps のstaging スロットへのデプロイを、承認者が承認するまで待機
  3. 承認後、Azure の Web Apps の Staging スロットにデプロイ
  4. production / staging スロットの swap を、承認者が承認する必要するまで待機
  5. 承認後、Azure の Web Apps の production / staging スロットをスワップ

f:id:beachside:20190828141339p:plain

目次

準備

Multi-stage pipelines の有効化

2019年8月時点では、プレビュー機能を有効にする必要があります。方法は、Azure DevOps の右上の自分のユーザーのアイコンをクリック > […] をクリック > Preview features をクリックします。

f:id:beachside:20190826173943p:plain

プレビュー機能の一覧が表示されます。対象を自身だけじゃなく Organization 全体にすると他のメンバーでも有効になります。Multi-stage pipelines を On にすると使えるようになります。

f:id:beachside:20190826174436p:plain

Service connection の確認

Pipeline から Azure へデプロイするときには権限が必要となります。この権限は Azure DevOps のプロジェクトごとに Service connection で管理されています。

Azure DevOps の Project settings (左下の設定アイコン) > Pipeline の下の方にある Service connection のメニューから作成できます。この作成には Azure 側の強めの権限を持っているユーザーが設定する必要になります。

作成(というか権限問題に関するエラー時の対処方法ですが)に関しては以前のブログにざっくり書いてるのでリンクを貼っておきます。

blog.beachside.dev

デプロイするプロジェクトの作成

1つのプロジェクトだとあまり実用的じゃないので、ソリューションの中で4つのプロジェクトを入れてみました。

  • ASP.NET Core のプロジェクト ( MultiStagePipelineWebDemo )
  • ライブラリのプロジェクト( SampleLib )
  • xUnit のプロジェクト2つ (SampleLib.Tests, WebAppTests )

ディレクトリ構成もプロジェクト名も中途半端になってしまったので自分的に悲しみが溢れましたが、以下のようになってます。

f:id:beachside:20190826175210p:plain

Azure にリソース作る

デプロイするリソースは事前に作っておきました。 WebApps を作って staging のスロットを追加してスワップできるように準備しただけなので、特に手順は書きません。

Multi-stage YAML pipelines の作成前の基礎知識

基本コンセプト

Pipeline の基本構造は以下のイメージです。

  • stage A

    • jobs 1
      • job 1-1
        • task 1-1.1
      • job 1-2
        • task 1-2.1
        • task 1-2.2
  • Stage B

主に stage, job, task が階層化されて構成されている程度に把握しておけばよいでしょう。

  • stage: Build とか Deploy とかの単位で作る感じですが、粒度は作成者次第です。
  • job: 粒度も結局何をやりたいか次第ですが、例えば Windows 上でテストとか Linux 上でテストとかな感じです。
  • task: job の中の処理順を定義します。

作成してて気になったのは、一つの Stage で Job を複数作ると、順番がばらばらに動きました。dependsOn で開始条件を制御すれば制御通りに動きます。ドキュメントでは、

A job is a series of steps that run sequentially as a unit.

と書いてるけど...まぁ、必要に応じで dependsOn で順序を保ちましょうってところですね。 task は書いた順に上から動作します。

Deployment jobs

デプロイするタスクで細かな設定をしたいときに Deployment jobs を設定します。今はまだ Kubernetes 向けの機能ばかりで WebApps とかにはあまり対応できてないようです。今回 Deployment jobs を使う理由は、承認者を設定できるからです。設定方法は後述します。

Multi-stage YAML pipelines の作成

Azure DevOps の左側のメニュー Pipelines の下の Pipelines をクリックし、New pipeline をクリックします。あとはブランチを選択したりリポジトリーを選択したりがでますので適当に選択します。

f:id:beachside:20190826194306p:plain

そうすると YAML を編集する画面にたどり着きます。まずは一つの YAML ファイルにパイプライン全体を書きますが、後述でテンプレート化します(これは結局次回のブログになります...)。そのためにも必要に応じて変数を使っています。

まずは動くコード見た方が早いのでコード全部載せます。ちなみに、公式のテンプレートでは task として書いてあるところを job にして書いてたりしますが深い意図はありません。実行時の動作とか画面表示がみやすくなるかなーとか試したかったから変えたまでです。

4~14行目: 必要な変数を定義

vmImage を定義してますが、Release する際は windows-2019 が認識されませんでした。なので vs2017-win2016 を設定しています。しかーしこれも仕事で構築してる環境では認識されるのに私個人の検証環境では認識されず、結果として Ubuntu16 で動いてました。ぐぬぬ。

8行目の targetServiceConnection は、Project 毎で作成する Service connection の名前を指定しています。

11, 12行目は、Environment の名称です。Azure DevOps のメニューの Pipelines > Environment から作成することができますが、なければ自動で生成されます。

他は Azure 上のリソースの名前や今回デプロイするプロジェクトの名前などを定義してます。

16~42行目: build / test

build と test は dotnet のコマンドを叩くだけです。以前の書き方とさほど変わりありません。ビルドはプロジェクト名を指定してますが、テストは tests のフォルダ内にあるプロジェクトを全部実行するように指定してみました。

他にも指定方法はありますので必要に応じて YAML の Schema を見てみると良いでしょう。

44~64行目: Build の Artifact を 保存

プログラムをビルドして zip にしたものを保存する job です。このジョブの実行を 46~49行目の build_jobtest_job の両方が成功しないと動かないようにdependsOncondition で設定しています。

54~64行目は、もうこう書けばよいというものなので細かいことを確認したい場合はドキュメントを見ましょう。

67~100行目: デプロイ

この stage は、68-69行目で build stage が成功したら動作するように設定しています。89行目と91行目の slot の設定を消せば slot なしの環境または production スロットへデプロイされます。

condition で以下のように複数の条件を定義できます。例えば trigger で master と release ブランチを対象にして、リリースは master ブランチのみにするときはこんな感じに書けばよいですね。

and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))

Conditions に関する詳しい情報やサンプルはこちらに記載されています。

71行目: Deployment job の設定

Jobs の配下で deployment と書くことで Deployment job として設定しています。75行目以降も task の時と書き方が全然違います。75行目で environment を定義しています。後ほど承認の設定するためですが、Environment に存在しなければ生成されます。どっちを先に作ってもまーなんとかなるって感じですね。

83~93行目: デプロイ

Azure の Web Apps の Staging スロットへデプロイしています。ここも以前とさほど変わってないですね。ほぼ?ドキュメント通りに書いただけです。

95~100行目: Azure CLI の実行

WebApp の環境変数(アプリケーション設定)に Build Number をセットしてみました。単に試したかっただけでですが、BUILD_ID という環境変数名に Build Number をセットするカオスは真似しないようにしましょう。。。

103~122行目: staging / production の swap

ここでは Azure CLI で swap しているだけです。staging へのデプロイが成功したら実施という条件にしています。

107行目で deployment と書いて Deployment job にして承認ができるようにしています。

次回のブログでやっていますが、CLI をたたかず、Azure App Service Manage task でやっても良いですね。

承認の設定

Azure DevOps の左側のメニュー Pipelines の中にある Environment を開きます。ここではパイプラインを実行してるので YAML で定義した Environment があります。なければ同一の名称のものを作ればOKです。

f:id:beachside:20190826192327p:plain

一覧で環境をクリックして、ハンバーガーメニューっぽいのをクリック > Checks をクリックすると承認者( Approvals ) を登録することができます。ディレクトリーにいる人やグループを登録できます。

f:id:beachside:20190826192646p:plain

登録すると、デプロイするときに承認を求められるようになります。Pipeline の実行の画面やログの画面で Review ボタンをクリックして、承認や拒否がきます。

f:id:beachside:20190826193911p:plain

承認待ちのタイムアウトの設定を今回はしてませんが、公式ドキュメントのここら辺を参考に設定できます。

メールの通知が飛ばないのが気になりますが、(あまりドキュメントも見てないしそれ調べるモチベーションもあまりないので)また今度調べようと思います。

テンプレート化を断念...

テンプレート化してパラメーターを渡してあげることで、再利用性を高めてさくさくとパイプラインを作れるようになります。ここまで来てると非常に簡単な変更なんですが 、長くなって餓死寸前に追い込まれそうなので次回書きます。

参考

しばやん先生がめっちゃまとめてたのでがっつり見ました(そしてやらなあかんなーと焦りが生まれた)。

blog.shibayan.jp

What’s new with Azure Pipelines | Azure DevOps Blog

Azure Pipelines Documentation - Azure DevOps Services | Microsoft Docs