前回の記事で行った作業を自動化できたらいいなと思っていたらAzure Pipelinesでいい感じにできたので、その時の記録です。Azureの他のサービスとの連携が簡単で、Azure Blob Storageにアップロードする作業も簡単に書くことができました。
準備
前回の記事の続きとして書くので、記事の中で作成したWPFアプリケーションが既にあることを前提とします。今回の作業では、前回の「公開」作業を行った時点で生成される「ClickOnceProfile.pubxml」を使います。Azure Blob Storageも前回と同じコンテナーを使う想定で書きます。
必要なもの
前回の記事に加えて、本記事では以下のもの利用します。
- Azure DevOpsアカウント
- Gitクライアント
記事の構成
この記事は以下の9つの手順でまとめます。
- プロジェクトにランタイムを指定する
- Azure DevOpsでプロジェクトを作成する
- Azure Reposにコードをプッシュする
- Azure Pipelinesでパイプラインを作成し、 Gitリポジトリと紐づける
- Pipelineを編集する
- Pipelineを実行する
- バージョンアップしてGitリポジトリにプッシュする
- Pipelineが自動実行することを確認する
- アプリが自動更新するか試す
1. プロジェクトにランタイムを指定する
SimpleWPFApplication.csproj
に RuntimeIdentifiers
タグを追加します。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
...
</PropertyGroup>
</Project>
ちょっと説明
RuntimeIdentifiers
タグを追加しておかないと、手順6でパイプラインを実行したときに以下のようなエラーが出てしまいます。
##[error]C:\Program Files\dotnet\sdk\5.0.402\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(241,5): Error NETSDK1047: Assets file 'D:\a\1\s\SimpleWPFApplication\obj\project.assets.json' doesn't have a target for 'net5.0-windows/win-x64'. Ensure that restore has run and that you have included 'net5.0-windows' in the TargetFrameworks for your project. You may also need to include 'win-x64' in your project's RuntimeIdentifiers.
このエラーを避けるため、エラーメッセージで勧められている通りランタイムを指定しておきます。
2. Azure DevOpsでプロジェクトを作成する
Azure DevOpsの自分の組織(Organization)のページを開き、 [+ New project] から新しいプロジェクトを作成します。
今回は [SimpleWPFApplication] という名前で作成しました。
3. Azure Reposにコードをプッシュする
プロジェクトの中にいくつかアイコンがありますが、その中の [Repos] を開きます。
クローンしたりプッシュするためのURLやコマンド例が載せられているので、手元の Git クライアントを使ってコードをプッシュします。手順は省略します。ちなみに .gitignore
はGitHub公式のこちらが役に立ちます。注意点として、この .gitignore
は今回使いたい pubxml
ファイルが含まれているので pubxml
をGit管理できるように変更する必要があります。
プッシュするとReposの画面は以下のようになります。
4. Azure Pipelinesでパイプラインを作成し、 Gitリポジトリと紐づける
プロジェクトの中から [Pipelines] を開き、 [Create Pipeline] から新しいパイプラインを作成します。接続先を選択する画面では、 [Azure Repos Git] から先程作成したリポジトリを選択します。ちなみに、候補にあるGitHubやBitbucketなどのGitホスティングサービスと連携することもできます。試しにGitHubとの連携をやってみましたがとても簡単にできました。以降の手順はそれらのサービスと連携した場合も同じように行えます。
5. Pipelineを編集する
この記事のメインです。パイプラインのテンプレートを選べるので [.NET Desktop] を選択します。
そうすると画面上で直接yamlが編集できるようになるので、以下のように編集します。yamlの編集が完了したら [Save] します。
# .NET Desktop
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
trigger:
- main
pr: none
pool:
vmImage: 'windows-latest'
variables:
solution: 'SimpleWPFApplication.sln'
project: 'SimpleWPFApplication\SimpleWPFApplication.csproj'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'
- task: VSBuild@1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: VSTest@2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: VSBuild@1
displayName: 'Publish'
inputs:
solution: '$(project)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
msbuildArgs: '-t:publish -p:PublishProfile=ClickOnceProfile.pubxml -p:PublishDir="bin\publish\\"'
- task: AzureFileCopy@3
displayName: 'Upload setup.exe'
inputs:
SourcePath: 'SimpleWPFApplication\bin\publish\setup.exe'
azureSubscription: '(サブスクリプション名)'
Destination: 'AzureBlob'
storage: '(ストレージアカウント名)'
ContainerName: '$web'
- task: AzureFileCopy@3
displayName: 'Upload SimpleWPFApplication.application'
inputs:
SourcePath: 'SimpleWPFApplication\bin\publish\SimpleWPFApplication.application'
azureSubscription: '(サブスクリプション名)'
Destination: 'AzureBlob'
storage: '(ストレージアカウント名)'
ContainerName: '$web'
- task: AzureFileCopy@3
displayName: 'Upload Application Files'
inputs:
SourcePath: 'SimpleWPFApplication\bin\publish\Application Files'
azureSubscription: '(サブスクリプション名)'
Destination: 'AzureBlob'
storage: '(ストレージアカウント名)'
ContainerName: '$web'
BlobPrefix: 'Application Files'
ちょっと説明
ブラウザの右側にある [Tasks] から使いたいタスクを選択し、フォーム入力すればタスクのyamlを自動生成してくれます。まずはこの機能を使ってyamlを自動生成し、必要であれば直接編集する、という流れが良いと思います。
pr: none
はプルリクエストを作成した時にパイプラインを実行しないように指定します。
ClickOnce公開のためのコマンドは公式ページを参考にしました。yamlでは [VSBuild] となっていますが、おそらくMSBuildを表していて同じオプションで動きました。PublishProfileオプションを使えば、Visual Studioで操作したときに生成された [ClickOnceProfile.pubxml] を指定してオプションをすっきりさせることができます。しかし、公式ページにもある通りPublishDirオプションはここでも指定する必要があります。
[AzureFileCopy] というタスクでAzure Blob Storageにアップロードしています。[azureSubscription] には、自分のAzureサブスクリプションを指定してください。執筆時点では最新版であるバージョン4 [@4] では動作しませんでした。アップロードしているファイルやフォルダは基本的に前回の記事と同じです。ただしインストールするときに使えるWebページ Publish.html
はMSBuildコマンドでは出力されないようで、今回は含めていません。インストール用のリンクが載ったページが必要であれば自分で作成する必要がありそうです。
6. Pipelineを実行する
画面右上の [Run] からパイプラインを実行します。うまくいけば下の図のように成功します。
7. バージョンアップしてGitリポジトリにプッシュする
最後に手順7から9で、コードを変更→mainブランチにプッシュ→パイプライン実行→アプリを更新の流れをやってみます。
ここはVisual Studioで作業します。前回の記事の「発行」機能を使えばリビジョンが自動で増加しましたが、今回はそういうわけにはいかないので ClickOnceProfile.pubxml
を自分で編集する必要があります。バージョン番号はなんでもいいですが 1.0.1.0
としてみました。
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.1.*</ApplicationVersion>
...
</PropertyGroup>
</Project>
前回と同様に MainWindow.xaml
を編集して画面にバージョン番号を表示するようにします。
<Window
...
>
<Grid>
<TextBlock Text="Ver.1.0.1.0" />
</Grid>
</Window>
これらの変更分をgit commitしてmainブランチにプッシュします。
8. Pipelineが自動実行することを確認する
Azure DevOpsのパイプラインのページを見にいくとパイプラインが実行しています。
9. アプリが自動更新するか試す
アプリを起動すると更新ダイアログが表示され、更新すると新しいバージョンになっていることが確認できます。