🐥note.

小鳥とMicrosoft <3 なエンジニアの技術Blog📚

Azure DevOpsでClient Side BlazorをCI/CDしてみる

こちらの記事の続きです。

blog.piyosi.com

本エントリでは

GitHubに作ったClient Side BlazorのPrivate Repositoryのmaster branchへのコミットをトリガーにして、Azure DevOpsでBuild, UnitTest, Publishした後、Azure Storageの静的サイトへ自動デプロイする。」

というCI/CDのベーシック(?)な流れを設定してみたので、その設定方法を記録として残します。

あくまで記録なので、大した説明もしていませんのでご留意ください。

手順

Client Side Blazorと単体テスト プロジェクトを持つソースコード一式をGitHubにPrivate Repositoryとして用意しました。

f:id:piyo_esq:20191030073737p:plain

Azure DevOpsにProjectの作成

Azure DevOpsにアクセスします。

f:id:piyo_esq:20191030073753p:plain

Private Projectを生成します。
今回はClientSideBlazorにしました。

f:id:piyo_esq:20191030073804p:plain

Build Pipelinesの設定

GitHubのPrivate Repositoryへのコミットをトリガーにbuild, UnitTest, Publishを行うBuild Pipelineを設定します。

restore, UnitTest, publishの設定

メニューからPipelinesを選択して、ソースの置き場所であるGitHubを選択します。

f:id:piyo_esq:20191030073816p:plain

Blazorのソースが格納されたRepositoryを選択します。

f:id:piyo_esq:20191030073826p:plain

Starter pipelinesを選択します。

f:id:piyo_esq:20191030073839p:plain

YAMLが表示されましたね。
ここを編集してきます。

f:id:piyo_esq:20191030073849p:plain

不要なTaskを削除します。 steps以下を全て削除しましょう。

f:id:piyo_esq:20191030073900p:plain

画面右上のShow assistantを押下し、.NET Coreを選択します。

Commandrestoreを選択します。

Blazorの.slnファイルの相対パスPath to project(s)に指定しAddを押下します。

f:id:piyo_esq:20191030073912p:plain

YAMLrestoreのTaskが追加されましたね。

f:id:piyo_esq:20191030073922p:plain

あとはtest, publishのTaskを同じように追加します。

publishの注意点としてはworkingDirectory.slnがある相対パスを指定し
Argumentは-c Release -o $(Build.SourcesDirectory)/outを指定します。

publishに成功すると$(Build.SourcesDirectory)/out以下にZIPで固められたPublishファイルが格納されます。
zipAfterPublishを指定していないのにZIPになるのはpublishWebProjectsのせいでしょうか?
 ちょっとよく分かっていません。

ここまでのYAMLは以下の通りです。

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'restore'
    projects: 'src/ClientSideBlazorSample.sln'
    feedsToUse: 'select'

- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: 'src/ClientSideBlazorSample.sln'

- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: true
    arguments: '-c Release -o $(Build.SourcesDirectory)/out'
    workingDirectory: 'src/ClientSideBlazorSample'

なお.NET Core CLI Taskで使用できる設定値は以下をご参照ください。

docs.microsoft.com

Azure ArtifactsへのPublishファイルコピーの設定

publishで生成されたZIPファイルをRelease Pipelinesで使用するために、Azure ArtifactsへコピーするYAMLの設定を追加します。

Show assistantからCopy filesを選択します。

f:id:piyo_esq:20191030074228p:plain

Source Folderpublishで指定したパスを指定します。

Contentspublishで生成されたZIPのファイル名を指定します。

Target Folder$(Build.ArtifactStagingDirectory)を指定します。

Build.ArtifactStagingDirectoryについては以下をご参照ください。

docs.microsoft.com

f:id:piyo_esq:20191030074250p:plain

最後にShow assistantからPublish build artifactsを選択します。

f:id:piyo_esq:20191030074300p:plain

デフォルトのままAddします。

f:id:piyo_esq:20191030074309p:plain

以上でPipelinesの設定は完了です。

最終的なYAMLは以下の通りです。

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'restore'
    projects: 'src/ClientSideBlazorSample.sln'
    feedsToUse: 'select'

- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: 'src/ClientSideBlazorSample.sln'

- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: true
    arguments: '-c Release -o $(Build.SourcesDirectory)/out'
    workingDirectory: 'src/ClientSideBlazorSample'

- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Build.SourcesDirectory)/out'
    Contents: 'ClientSideBlazorSample.zip'
    TargetFolder: '$(Build.ArtifactStagingDirectory)'
    CleanTargetFolder: true

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

右上のSaveボタンを押下してYAMLをRepositoryにコミットすると、設定したPipelinesが実行されます。

Pipelines実行結果

実行結果はこんな感じになりました。

f:id:piyo_esq:20191030074322p:plain

Testのタブを選択するとUnitTestの結果も見れます。
※テストでFailedがあると、以降で設定するRelease Pipelineはトリガーされません。

f:id:piyo_esq:20191030074333p:plain

Release Pipelinesの設定

Azure Storageの静的サイトへ自動デプロイするためにRelease Pipelinesの設定を行います。

画面左メニューからReleaseのメニューを選択します。

New Pipelinesを押下し、Empty jobsを選択します。

f:id:piyo_esq:20191030074344p:plain

Stage名は好きに変えてください。

f:id:piyo_esq:20191030074356p:plain

Artifactsの設定

赤く塗ったAdd an artifactを押下します。

f:id:piyo_esq:20191030074409p:plain

Projectは自身であるClientSideBlazorを選択し、Source Build Pipelineは先ほど作成したbuild pipelinesの項目名を選択してAddを押下します。

f:id:piyo_esq:20191030074420p:plain

Artifactの稲妻のマークを選択します。

稲妻のマークで、このPipelineを動かすトリガーを設定します。

f:id:piyo_esq:20191030074431p:plain

Continuous deployment triggerEnableにします。

Repositoryの監視対象branchをmasterに指定します。

Pull Requestのトリガーは無効のままにしておきましょう。

f:id:piyo_esq:20191030074442p:plain

以上でCDのトリガーと、Deployに使用するArtifactsの指定を終えました。

Deploy Stageの設定

Deployの設定を行います。

今回はDeployの手動承認やGate(※)は指定しません。
関連付けられたIssueやWorkItemが0件か や Release Pipeline上で実行したテスト結果が正常か といった条件の設定

Stage1の1 job, 0 taskというリンクを押下します。

f:id:piyo_esq:20191030074453p:plain

Agent Job+リンクを押下します。

f:id:piyo_esq:20191030074504p:plain

publishで作成したZIPファイルの解凍処理を追加します。
Extract filesを選択します。

f:id:piyo_esq:20191030074514p:plain

Archive file patterns**/ClientSideBlazorSample.zipを指定します。
Destination folder$(Build.BuildId)を指定します。

f:id:piyo_esq:20191030074525p:plain

Azure Key Vaultの設定

デプロイにはAzure CLIを使用します。

CLIコマンドには--account-keyを記載する必要がありますが、機微な情報なのでAzure DevOpsの設定内に記述するわけにはいきません。

よって--account-keyの情報はAzure Key Vaultに格納し、そちらの値を参照する形でCLIを記述します。

Azure Key Vaultの設定のためここで一旦Azure DevOpsからAzure Portalに移動します。

Azure PortalからAzure Key Vaultを追加します。

f:id:piyo_esq:20191031064429p:plain

シークレットに--account-key情報を追加します。シークレットの名前はstorageKeyにしました。

f:id:piyo_esq:20191031064441p:plain

--account-keyの確認は以下のコマンドで行えます。

az storage account keys list --account-name {StorageAccount名}

f:id:piyo_esq:20191031064454p:plain

ここで一旦Azure DevOpsに戻ります。

Azure CLIから値を取得するためのAzure Key Vaultのタスクを追加します。

Agent Job+リンクからAzure Key Vaultを検索し追加します。

f:id:piyo_esq:20191031064508p:plain

Azure subscriptionはご自身のサブスクリプションを選択します。
※選択後承認ボタンが表示されるので、承認しましょう。

Key vaultは上で作ったKey Vault名を指定します。

Secrets filterはAzure Key Vaultに追加したシークレット名のstorageKeyを指定します。

f:id:piyo_esq:20191031064521p:plain

ここで一旦Azure Portalに移動し、アクセスポリシーを追加します。
アクセスポリシーの追加を押下します。

f:id:piyo_esq:20191031064533p:plain

シークレットのアクセス許可から取得一覧を選択します。

f:id:piyo_esq:20191031064544p:plain

プリンシパル{user名}-{Azure DevOpsのProject名}-{サブスクリプションID}の項目を選択します。
※先にAzure DevOpsでAzure Key Vaultのタスクを追加し、承認を終えていないとここで表示されません。

f:id:piyo_esq:20191031064556p:plain

保存ボタンを押下することを忘れないでください。

以上でAzure Key Vault側の設定は終了です。Azure DevOpsに戻ります。

Azure CLIの設定

Azure CLIを使ってAzure Storageへとファイルをアップロードします。
Agent Job+リンクを押下し、Azure CLIを追加します。

f:id:piyo_esq:20191031064650p:plain

Azure Subscriptionはご自身の任意のサブスクリプションを、
Script LocationはとりあえずInline scriptを使用します。
Inner Scriptは以下の通り。

az storage blob upload-batch --account-name {StorageAccount名} --account-key $(storageKey) -d $web -s ./ClientSideBlazorSample/dist/

az storage blob update --account-name {StorageAccount名} --account-key $(storageKey) -c $web -n _framework/wasm/mono.wasm --content-type application/wasm

$(storageKey)はAzure Key Vaultで設定したシークレットを指しています。

Working Directory$(Build.BuildId)を指定します。

f:id:piyo_esq:20191031064715p:plain

以上で設定は完了です。Saveボタンを押下し設定を終了します。

動作させてみる

指定したRepositoryにコミットするか、Build Pipelineを手動で開始させます。

手動開始は設定したBuild PipelineのRun pipelineボタンで開始できます。

f:id:piyo_esq:20191030074602p:plain

ビルドとデプロイが正常に終わると、こんな感じになります。

f:id:piyo_esq:20191030074612p:plain

無事動きました。

これでmasterへコミットするとCI/CDが走り、自動デプロイされるようになりました。

おわり

  • いまいち分らない点がありますが、ちょっと試すくらいなら画面をポチポチするだけで簡単にできちゃいますね...。

  • --account-nameもAzure Key VaultのキーとかAzure DevOpsのVariablesに乗せた方がいい気がする...

  • Azure Storage静的サイトへのファイルのコピーはAzure CLIじゃないとできないっぽいので、そこが面倒ですね。