BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

NuGet パッケージ 作成と Azure Artifacts へ公開 ( Azure DevOps )

今回は .NET Standard のライブラリを NuGet パッケージ化して手作業で AzureDevOps の Artifacts への発行をします。次回 Azure DevOps の Pipelines を使って発行を自動化します。

また NuGet Package を作成するの備忘録として、バージョン管理とかライセンスの情報といった パッケージのプロパティ を設定しておきたいところですが、たまにしかやらないしやるときは毎回記憶にないので、ようやくメモしておきます。

NuGet パッケージのプロパティを構成をする

パッケージのプロパティ では、ID とかバージョンとか、ライセンスに関することとかを設定できます。基本的なことは以下のドキュメントに書いています。

docs.microsoft.com

csproj ファイルを開いて直接書いてもいいですし、ソリューションエクスプローラーでプロジェクト名を右クリック > プロパティを開いて パッケージ から編集できます。

ここで気を付けておきたいことをメモします。

ライセンス関連

ライセンスに同意が必要 にチェックを入れた場合、ライセンスの入力が必要です。
式の方に MIT とか Apache-2.0 とか適用したいライセンスを直接書けばよいです。

f:id:beachside:20191017233908p:plain

2つの時はこちらにかいてあるように MIT OR Apache-2.0 と書くようですね(試したことない)。

後述で出てくるパッケージ化の話になりますが、ライセンスに同意が必要 のチェックボックスの上にある ビルドで NuGet パッケージを生成 のチェックを入れると、ビルドした際に .nupkg のファイルが生成されます。csproj では <GeneratePackageOnBuild>true</GeneratePackageOnBuild> が追加されます。

タグ (Tags)

nuget.org の Tags に表示されるタグです。Azure Artifacts でも同じく表示されます。複数つける場合は ; で区切ります。

バージョン管理

基本的にアプリのバージョン管理と一緒。プレリリース(beta版とか)にしたいときもアプリのバージョン管理と一緒です。csproj ファイルから VersionSuffix を書いてあげればよいです。

NuGet パッケージのプレリリース版 | Microsoft Docs

VersionPefixVersionSuffix については以前に触れましたのでリンク張っておこう。

blog.beachside.dev

依存関係のバージョンの制御

自分で作ったライブラリ自体が使ってる NuGet のバージョン依存関係の管理をするときは、csproj ファイルを開いて、PackageReference に条件を書きます。

docs.microsoft.com

バージョンの範囲を指定する場合の書き方は、以下にあります。

https://docs.microsoft.com/ja-jp/nuget/concepts/package-versioning#version-ranges-and-wildcards

パッケージ化

ライブラリを作成してパッケージのプロパティを設定したら、NuGet の Feed に登録するために、ライブラリのプロジェクトをパッケージ化します。

このご時世にビルド・テスト、パッケージ化して Feed に発行するのを手作業でやるなんて(個人的には)考えられないですが、今回はあえて手作業でやります。次回のブログで、Azure DevOps の Pipelines でビルド・テストと発行をします。

そもそもパッケージ化とは、.nupkg ファイルを作ることです(雑な説明ですな)。いくつか方法があります。

  • コマンドで作成: dotnet や nuget のコマンドで作成できます。次回の Azure Pipelins でCICDを構成するとにも出てくるので今回はやらんでおきます。
  • ビルド時に自動生成: 前述 "パッケージのプロパティを構成する" でさらっと書きましたが、"ビルドで NuGet パッケージを生成" のチェックを入れるとビルドしたタイミングで .nupkg` のファイルが生成されます。
  • Visual Studio のメニューから作成: のソリューションエクスプローラーで、プロジェクトを右クリック > パック をクリックすると生成できます。

2つ目と3つめは、実行すると、プロジェクトのディレクトリの中の bin > ソリューション構成で指定されている名称のフォルダ( "Dbug" とか "Release" とか)の直下にできます。ファイル名は、プロジェクト名+バージョン + 拡張子(.nupkg)です。

パッケージの公開

さっきも書きましたが、今回はあえて手作業でやります。次回のブログで、Azure DevOps の Pipelines でビルド・テストと発行をします。

公開する先は色々ありますが、私の個人的な選択肢は、

  • パブリックに公開したいなら NuGet Gallery である nuget.org
  • Private に package を管理したいなら Azure DevOps Artifacts

って感じでしょうか。Azure DevOps Artifacts は Public に公開もできるようになりましたが今回は扱いません(ブログ書いた時点では Preview 中)。

今回の本題ではない nuget.org への公開を手作業でする場合、以下リンクを参考にすればサクッとできます。
.NET Standard NuGet パッケージの作成と公開 - Windows 上の Visual Studio | Microsoft Docs

Azure DevOps Artifacts で Feed の作成

発行先となる Azure DevOps の Artifacts で Feed を作成します。Feed とは、自身の NuGet ギャラリーみたいなものです。
Azure DevOps で Artifacts のメニューをクリックし、Create Feed をクリックします。

f:id:beachside:20191018170123p:plain

"Create new feed" の画面が開きます。名前とパーミッションを入力します。

名前は URL の一部になるので、それっぽくするとよいでしょう。
パーミッションの1つ、Visibility は説明書かれてるままの内容です。誰が使えるかのスコープを選択しましょう。
もう一つ、Packages from public sources はデフォルトでよいでしょう。説明のリンクがついてますが、のドキュメントが古くて微妙な感じです。

f:id:beachside:20191018170512p:plain

Feed を作成したら、この Feed に Package を発行すれば、 Visual Studio や CI/CD のパイプラインから NuGet パッケージをダウンロードすることができます。
Feed にはもちろん複数のパッケージを登録することができるので、(当たり前ですが)パッケージ毎ではなく、公開したい範囲に応じて Feed を作る感じです。

Visual Studio から Feed が見えるようにする

Visual Studio の Nuget パッケージの管理 画面からこの Feed のパッケージを検索できるようにするには、この場所の情報を登録する必要があります。
作成した Feed の画面上部にある Connect to feed をクリックします。

f:id:beachside:20191018201924p:plain

Connect to Feed の画面が表示されます。Visual Studio の NuGet の管理から検索できるための情報が表示されます。

f:id:beachside:20191018202423p:plain

方法は2通りあります。

  • nuget.exe のコマンドを使って登録する
  • Visual Studio の GUI で登録する

nuget.exe のコマンドで登録する(私はこの方法ではしたくない)

nuget.exe の CLI を使う場合、まず nuget.exe のインストールが必要です。インストール方法は、nuget.exe をダウンロードして適当なフォルダーにおき、環境変数で nuget.exe のパスを通す流れです。ダウンロードに関してはドキュメントのリンクを張っておきます。

NuGet クライアント ツールのインストール > nuget.exe CLI

nuget.exe の CLI を使っての方法は私はやらないので、公式のドキュメントのリンクを張るだけにしておきます。

Use NuGet with Azure DevOps Services feeds - Azure Artifacts | Microsoft Docs

git はクライアントアプリ使わずコマンドしか使わない私ですが、 nuget.exe の CLI を使わない熱い理由は以下です。

  • Feed の登録は滅多にやらないし、滅多に使わないのに exe をダウンロードしてパスを通して使うとかめんどい。
  • nuget.exe の CLI の代替として、VS 2019 で操作すればサクッとできる。
  • ローカル環境でコマンドによる自動化を行うわけでないなら、使いどころがない(自動化は、Azure DevOps の Pipelines でやります)。
  • コマンドで Feed を登録すると、今私が使ってる Visual Studio 2019 ( Version 16.4.0 Preview 2.0) では、コマンド実行後に再起動しないと Feed が見えるようにならない。VS 再起動はめんどい。後述の VS の GUI の操作で登録するなら再起動不要です。

Visual Studio で Feed を登録する

Visual Studio 2019 の GUI でメニュー ツール > オプション > メニューの NuGet パッケージマネージャー > パッケージソース を開き、パッケージソースを登録することで VS から検索できるようになります。

ソースに入力する値は、先ほど Azure DevOps の Artifacts の Connect to feed の画面にある Package source URL です。

f:id:beachside:20191021153655p:plain

これで Visual Studio の NuGet パッケージの管理 画面を開くと、上左の方にあるパッケージソースを選択することで見えるようになります。

f:id:beachside:20191021154136p:plain

パッケージを発行する

nuget.org へ発行する際は、nuget.org のウェブサイトから .nupkg のファイルをアップロードすることができます。

しかーし Azure DevOps Artifacts への push は、nuget.exe の CLI でしか登録する方法がないっぽい? dotnet nuget push でいけるかと試したら思ったら無理そうでした。。。Personal Access Token 作って Azure DevOps Artifacts Credential Provider と同じ権限与えても、Full access にしてもダメだった。

ということで、nuget.exe の CLI を使って発行しましょうってオチです。悲しい。nuget.exe をダウンロードしてない場合は前述 nuget.exe のコマンドで登録する のところにさらっとダウンロード方法について書いています。

nuget.exe がコマンドで認識できるようになったらあとはこちらのドキュメントを参考にコマンドを実行します。。

Publish a NuGet package from the command line - Azure Artifacts | Microsoft Docs

リンクのドキュメントでは以下のコマンド打てって書いてますので、パラメーターについて補足しておきます。

  • -Source: パッケージソースの url を直接書いてもいいし、VS にパッケージソースを登録する際に入力した名前を入れても大丈夫です。
  • -ApiKey: Key は AzureDevOps と書いておけば初回に認証画面がでて、あとは勝手に認証するようになります(認証の画面が出てきてログインしたら PAT が作られて、pcの localの AppData の深いとこに暗号化されて格納されるってやつですね)。
nuget.exe push -Source {NuGet package source URL} -ApiKey key {your_package}.nupkg

実際のコマンドはこんな感じです。

f:id:beachside:20191023143844p:plain

最後に、Visual Studio で NuGet パッケージの管理画面から発行したパッケージが見えていることを確認しましょう。

f:id:beachside:20191021154136p:plain


次回、Azure DevOps の Pipelines を使って、ビルド・テストから発行までを自動化します。

GitHub のコードを Azure Pipelines 使って Azure Artifacts へ公開 (NuGet パッケージ, Azure DevOps ) - BEACHSIDE BLOG


(NuGet に対するモチベーションが低すぎて、このブログ終わらせるのに3カ月くらいかかりました。書いた時間は1日くらいですがね。)