WPF on .NET Core 3.0アプリをAzure PipelinesでビルドしてAppCenterにリリースする
タイトルまんまです。
2ヶ月ほど前に WPF / WindowsForms に対応した App Center について色々遊んでいましたが、Distribute については .NET Framework だとちょっと面倒な部分があったので .NET Core 3.0 が GA されるまで放置してました。 9月に無事 .NET Core 3.0 が GA されたので色々試した結果、Azure Pipelines を使用して App Center Distribute へリリースするところまでできたので備忘録として残したいと思います。
前回までの記事
やりたいこと
- GitHub 上のコードにプッシュ
- Azure Pipelines が上記をトリガーにビルド&publish
- 成果物を App Center Distribute へリリース
- メールで通知してアプリを配布する
今回はこういった流れでコードのプッシュから配布までをやってみます。
これができると例えば"release ブランチにコードをプッシュしたらステークホルダー グループに登録したユーザーにメールで通知する"みたいなことが可能になります。
開発環境
- Visual Studio 2019
- .NET Core 3.0.100
- WPF
- C#
やってみる
ということで早速やっていきます。 GitHub と Azure Pipelines との連携はググるレベルでもないので省略します。
App Center の設定
App Center の設定はプロダクトによって異なるので必要な情報のみ記載します。 Release Group の登録やバージョン番号の管理など予め設定されているものとします。
Azure Pipelines から App Center Distribute を使用するためには以下のページが参考になります。
Azure Pipelines との連携に API Token が必要になるので発行しておきましょう。
次に、App Center タスクに必要な情報を取得しておきます。
まずはApp slug
です。こちらは上記 URL にも記載されていますが、リリース先の App Center ページの URL から取得します。
https://appcenter.ms/users/{username}/apps/{app_identifier}
このような URL 形式になっていると思うので、{username}
と{app_identifier}
を結合して{username}/{app_identifier}
としたものがApp slug
となります。
そしてDestination IDs
です。こちらはリリースグループを識別するための ID です。
取得方法は上記 URL に記載がありますので参照してください。
とりあえず App Center で必要なのはここまで。
Azure Pipelines の設定
Azure Pipelines と App Center との連携には[Project Settings] - [Service connections] から設定します。 App Center の API Token が必要になるのでご注意を。
今回設定したタスクは以下のとおりです。(タスク名を列挙しています)
- NuGet tool installer
- NuGet
- Use .NET Core
- .NET Core
- Archive files
- App Center distribute
NuGet tool installer
, NuGet
, Use .NET Core
はいつも通りのやつなので省略します。
1つ注意点として、Use .NET Core
に指定するバージョン番号は .NET Core 3.0 の場合は、3.0.100
などになります。
一度ローカル環境で dotnet コマンドを実行してバージョン番号を確かめておきましょう。(私はこれにちょいハマりました)
.NET Core
タスクはビルド用と publish 用に2つ使用します。
ビルドは特別なことはしていないので省略します。
publish はタスクのArguments
に以下を設定しました。
-c Release -r win10-x64 /p:PublishSingleFile=true --output $(Build.ArtifactStagingDirectory)
シングルファイルでパッケージして、出力先を$(Build.ArtifactStagingDirectory)
としました。
なぜこうしているかはハマリポイントを参照してください。
次にArchive files
です。
こちらも普通に publish で生成したファイルを zip にするだけです。
WPF アプリを App Center Distribute に追加するには .zip もしくは .msi でなければならないため、このタスクを追加しています。
ここはもうそのまままですね。
最後はApp Center distribute
です。
このタスクの各種設定地については以下を参照して下さい。
- App Center service connection
接続先の App Center を選択します。選択式なので迷うことはないでしょう。 - App slug
アプリケーション名とユーザー名を組み合わせたものです。App Center の設定を参照してください。 - Binary file path
発行対象のファイルパスを指定します。ここには先程Archive files
で指定した出力先を設定します。 - Build version
アプリのバージョン番号を指定します。ここは過去のバージョンよりも大きい数値を設定する必要があります。 - Create release notes
リリースノートをどうするか選択します。Enter Release Notes
を選択するとリリースノートを入力できるようになります。Select Release Notes File
を選択すると、リポジトリ内にあるファイルをリリースノートとして使用します。こちらはプロダクトに合わせて設定してください。 - Destination IDs
配布先の ID です。ステークホルダーやテスターなど、アプリを配布したいグループの ID を設定します。ID の取得方法はApp Center の設定を参照してください。
今回は以下のようなりました。
これを実行すれば、App Center へ配布して登録されているユーザーへメールで通知されます。
今回のYAML
今回作成したタスクをYAMLで出力するとこうなります。
pool: name: Azure Pipelines steps: - task: NuGetToolInstaller@1 displayName: 'Use NuGet 4.4.1' inputs: versionSpec: 4.4.1 - task: NuGetCommand@2 displayName: 'NuGet restore' inputs: restoreSolution: Samples/AppCenter.Wpf/AppCenter.Wpf.sln - task: UseDotNet@2 displayName: 'Use .Net Core sdk 3.0.100' inputs: version: 3.0.100 - task: DotNetCoreCLI@2 displayName: 'dotnet build' inputs: projects: 'Samples/AppCenter.Wpf/AppCenter.Wpf/**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'dotnet publish' inputs: command: publish publishWebProjects: false projects: 'Samples/AppCenter.Wpf/AppCenter.Wpf/**/*.csproj' arguments: '-c Release -r win10-x64 /p:PublishSingleFile=true --output $(Build.ArtifactStagingDirectory)' zipAfterPublish: false modifyOutputPath: false - task: ArchiveFiles@2 displayName: 'Archive $(Build.ArtifactStagingDirectory)' inputs: rootFolderOrFile: '$(Build.ArtifactStagingDirectory)' - task: AppCenterDistribute@3 displayName: 'Deploy $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip to Visual Studio App Center' inputs: serverEndpoint: '<連携した App Center を選択する>' appSlug: '<slug を設定する>' appFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip' buildVersion: 1.2.0 symbolsOption: UWP releaseNotesOption: file releaseNotesFile: Samples/AppCenter.Wpf/AppCenter.Wpf/ReleaseNote.txt distributionGroupId: '<Group ID を設定する>' isSilent: false
ハマリポイント
publishする際に出力先を指定しないとFile not foundになる
そのまんまですが、publish で--output
を指定していないと以下のようなエラーが出力されます。
なぜこのような現象が発生するのかは不明です。
--output
を指定すれば回避できるので素直に指定しましょう。
##[error]Error: form-data: EISDIR: illegal operation on a directory, read
ビルド番号が指定されていないとApp Centerからレスポンスコード422が返ってくる
こちらもそのまま。
App Center distribute
タスクのBuild version
が未指定だと以下のように422が返ってきます。
バージョン番号を設定することで回避できるのでこちらも素直に設定しましょう。
##[error]"{\"status\":\"error\",\"message\":\"Version could not be created from build.\"}"
わかっていない・試してないところ
.msi での配布
Azure Pipelines の Hosted を使用して .msi ファイルを作るには Wix が必要になります。 この .msi ファイルであれば .NET Framework でも配布は可能です。 私は Wix は使ったことがないため、 .msi ファイルの配布は試したことがありません。
Build versionを動的に設定する
今回の方法ではApp Center distribute
タスクのBuild version
は固定値になっています。
できればここは動的に設定できるようにしたいところ。
策としては以下の2つでしょうか。
- ブランチにバージョン番号のタグを設定し、PowerShell を使ってブランチのタグからバージョン番号を取得する
- .msi を作成して製品バージョンを手動で設定してプッシュする
.msi の方は説明を読む限り App Center 側で製品バージョンを読み込んでくれるようです。(未検証) .NET Core の場合はもうちょいうまいやり方ってないんでしょうかね? この辺は知識不足なのでもっといい方法があるかもしれません。
最後に
今回でプッシュ→リリースのパイプラインが完成しました。 プロダクトに利用すれば面倒な作業はかなり自動化されそうです。
通知手段がメールしかないのでチャットツールとの連携手段もほしいところ。ここは App Center のアップデート待ちですね。
にしても App Center は日本ではあまり知名度がないのかほとんどブログなどで見かけることがありません。 Analytics や Crashes , Distribute といった仕組みがフルマネージドで提供されている上に組み込みもかんたんなので、使い所は大いにありそうなんですが…。
もし、この記事を見て興味を持った方はぜひチャレンジしてみてください!!