非常に今更感がある内容なのと、Azure Pipelines の方が便利なんじゃないか疑惑もありますが、AppVeyor を使っているプロジェクトが多いので、やっと真面目に対応しました。
GitHub 上で新しく Release を作成すると、そのタグ名をバージョンにして NuGet パッケージを作成して、デプロイするという流れです。そしてタグ以外の場合はビルドはしますがパッケージは作成しません。
一部 NuGet とは関係ない部分もありますが、AppVeyor を使う場合に注意したい部分です。
Pull Request 作成時に 2 度ビルドされるのを防ぐ
普通に AppVeyor を使い始めると悩むのが、この PR 作成時の 2 度行われるビルドです。
ビルドが数秒で終わる場合ならまだマシですが、時間がかかる場合には最悪です。
イマイチ最適な解を見いだせなかったのですが、対象のブランチをデフォルトブランチに絞れば解決します。多くの場合は master なので、master だけビルドするようにします。
branches: only: - master
この場合でも Pull Request では問題なくビルドされますが、マージ先を master にする必要はあります。
Pull Request でビルド番号を増やさない
これは割とおまけ感ありますが、AppVeyor は Pull Request でのビルド時にはビルド番号を増やさずに、suffix を付けて識別する機能があります。
pull_requests: do_not_increment_build_number: true
同じ Pull Request の場合は同一のビルド番号が使われるので、履歴が分かりやすいです。
ビルド番号をバージョンに含めている場合などは、PR の雑なコミットで増やしたくないケースもあるかと。
タグが打たれた時だけ nupkg を作る
GitHub でタグが打たれた時は APPVEYOR_REPO_TAG
の値が true
となるので、それを利用してビルドスクリプトの挙動を変えます。AppVeyor ではビルドに条件を書けないので、PowerShell を使って対応します。
build_script: - ps: | dotnet build .\NuGetTest\NuGetTest.csproj -c Release if ($env:APPVEYOR_REPO_TAG -eq $true) { dotnet pack .\NuGetTest\NuGetTest.csproj -c Release --no-build -p:Version=$env:APPVEYOR_REPO_TAG_NAME }
これで通常のコミットではビルドだけ実行されますが、タグの場合は nupkg が作成されるようになります。
タグ名をパッケージ生成時に渡すようにしているので、これで NuGet パッケージのバージョンがオーバーライドされます。一緒に --no-build
を渡しているので再度ビルドは行われません。
NuGet の API キーを環境変数で渡す
NuGet へのデプロイに必要な API キーを appveyor.yml に含めておくのは、暗号化されていても良い気分がしないのと、キーのローテートの時にコミットするのが面倒だったので、環境変数で渡すことにしました。
AppVeyor の設定から API キーを追加しておきます。鍵ボタンをクリックすると暗号化されます。
API キーを使う場合には $(NUGET_API_KEY)
というような形で名前を指定します。
deploy: - provider: NuGet api_key: $(NUGET_API_KEY) skip_symbols: true artifact: /.*\.nupkg/ on: appveyor_repo_tag: true
そしてデプロイの条件で appveyor_repo_tag: true
を指定して、タグの時のみ動くようにします。
完成した appveyor.yml
作成した appveyor.yml の全体は以下の通りです。個別に見ると大したことはしていない簡単な処理です。
version: '{build}' branches: only: - master pull_requests: do_not_increment_build_number: true image: - Visual Studio 2017 build_script: - ps: | dotnet build .\NuGetTest\NuGetTest.csproj -c Release if ($env:APPVEYOR_REPO_TAG -eq $true) { dotnet pack .\NuGetTest\NuGetTest.csproj -c Release --no-build -p:Version=$env:APPVEYOR_REPO_TAG_NAME } artifacts: - path: '**\*.nupkg' deploy: - provider: NuGet api_key: secure: $(NUGET_API_KEY) skip_symbols: true artifact: /.*\.nupkg/ on: appveyor_repo_tag: true
ビルドするプロジェクトの指定周りは少し注意が必要です。プロジェクト名を明示的に指定しなくてもパッケージ作成は行えますが、プロジェクトが多い場合には時間がかかったりするので、注意したいところです。
テストでビルドしたり、タグを打ってリリースを確認しておきました。問題なくデプロイされています。
長期的には Azure Pipelines への移行を考えていますが、しばらくは AppVeyor を使います。