自作 npm パッケージを Azure Artifacts へ手動デプロイおよび自動化
読む前の注意
自動化において Azure Pipelines を使用するが、初めて利用する場合、Microsoft がホストしているサーバーでパイプラインを動かすには以下のフォームから利用申請を送る必要がある。(無料枠の場合)
このリクエストの回答・承認が2-3営業日後とのことなので Azure Pipelines がすぐに使えるわけではないので注意。
もし、この申請前にパイプラインを動かそうとすると、以下のエラーがでてパイプラインが失敗する。
##[error]No hosted parallelism has been purchased or granted. To request a free parallelism grant, please fill out the following form https://aka.ms/azpipelines-parallelism-request
はじめに
npm の自作パッケージの作り方は以下の記事で書いた。そこで作ったパッケージを Azure Artifacts にデプロイする方法が今回の記事である。
前提
すでに自作パッケージが Azure Repos 上のリポジトリとして存在し、それがローカルにgit clone
済みであることを前提とする。またビルドまで済んでいるものとする。もし GitHub 上のリポジトリであれば以下のドキュメントを参考にして [Import repository] すれば、簡単に Azure Repos 上に複製できる。
Azure Artifacts の準備
Azure DevOps 側の準備をする。Azure Artifacts にフィードを用意する必要がある。
Azure DevOps のプロジェクトに入って、右のリストから Azure Artifacts をクリックする。 [Create Feed] から適当な名前でフィードを作成する。ここは以下の公式ドキュメントを見ながらやるのが良い。
手動デプロイ
さて、手動デプロイについてだが、これが厄介である。以下の公式ドキュメントを参照するとわかるのは結構手間がかかりそうに見える。(あとホームディレクトリに.npmrc
ファイルを置かせようとするところがとても嫌だ。)
もちろん手動デプロイを避けて最初から自動デプロイをすれば良いと考えるかもしれないが、いずれにせよnpm install
するときに似たようなことをやらなければならないので避けて通れないのでやるが、少しアレンジする。
スコープの設定
まず、パッケージにスコープをつける。例としてよく見かけるのが@babel/core
でbabel
がスコープ名である。Azure Artifacts にはスコープをつけなくてもパッケージをデプロイできるが、実際にはスコープを設けたほうが内製ライブラリなのかそうでないのかがわかりやすくなり、またスコープに限定して Azure Artifacts から取得するようにできる。
したがって、これらに対応するためにまずはpackage.json
を少し書き換える。
{
+ "name": "@<スコープ名>/<パッケージ名>",
- "name": "<パッケージ名>",
...
}
<スコープ名>
に制限はないが、Azure Artifacts のフィードのスコープとできるだけ対応が取れてわかりやすいものが良いだろう。
.npmrc
ファイルの設定
Personal Access Token の作成とローカル環境の作業フォルダ直下に.npmrc
ファイルを作成し、以下の記述をしたい。
@<スコープ名>:registry=<フィードのnpm用URL>
always-auth=true
//<フィードのnpm用URLの'https://'以下>:username="<ユーザー名>"
//<フィードのnpm用URLの'https://'以下>:_password="<BASE64にエンコードしたPAT>"
//<フィードのnpm用URLの'https://'以下>:email=""
<スコープ名>
package.json
のname
のところと同じスコープ名にする。
<フィードのnpm用URL>
公式のドキュメントを見ると以下の二パターンであるが、[Connect to Feed] から URL を確認&コピーできる。(個人アカウントの場合 URL が異なるかもしれない。)
# プロジェクトスコープの場合
https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/_packaging/<FEED_NAME>/npm/registry/
# 組織スコープの場合
https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/npm/registry/
<ユーザー名>
これは任意の文字列でよい。
<BASE64にエンコードしたPAT>
これの用意が手間である。PAT とは Personal Access Token の略で認証に必要なものであり、以下の記事を参考に取得する。PAT を発行する際 [Scope] のところは "Packaging" の項目を "Read, write, & manage" にチェックするだけで今回は問題ない。
そうするとランダムのように見える文字列が発行されるので、それをコピーして以下のコマンド[1]の<PAT>
に入れ、BASE64 にエンコードする。
echo -n "<PAT>" | base64
そうすると別の文字列が CLI 上に出力されるので、それをコピーして.npmrc
ファイルに値を入れる。
デプロイ
以上の設定をした後、以下のコマンドでデプロイする。
npm publish
これで手動によるデプロイができた。
npm install
してみる
別のフォルダでnpm create vite@latest
で React プロジェクトを新規に作成したあと、先ほど作った.npmrc
ファイルをコピーしてきて以下のコマンドを叩く。
npm install @<スコープ名>/<パッケージ名>
するとインストールできるので、import
してみて使えるかどうか確かめてみる。
import { ... } from "@<スコープ名>/<パッケージ名>";
デプロイ自動化
手動デプロイが少し複雑なうえにこれを毎回手元で行うのはミスもしやすくリスクがある。ということで次は Azure Pipelines を利用した自動化をしてみる。
パイプラインの準備
.azure-pipelines
フォルダを作成して、その中にdeploy.yml
を以下のように作成する。
trigger:
branches:
include:
- main
pool:
vmImage: "ubuntu-latest"
jobs:
- job: "release"
variables:
PROJECT: $(System.TeamProject) # 組織スコープの場合不要
FEED: npm-test-lib
steps:
- task: UseNode@1
inputs:
version: '20.x'
displayName: 'Install Node.js'
- script: |
npm ci
displayName: 'npm install'
- script: |
npm run build
displayName: 'npm build'
- task: Npm@1
inputs:
command: publish
publishRegistry: useFeed
publishFeed: $(PROJECT)/$(FEED) # 組織スコープの場合 $(PROJECT)/ が不要
基本的な流れは以下のようである。
-
main
ブランチにマージされたタイミングで発火する。 - Ubuntu 仮想環境を用意する。
-
UseNode@1
タスクを使用して Node.js をインストールする。 -
npm ci
で依存関係をインストールする。 -
npm run build
でライブラリをビルドする。 -
Npm@1
タスクで Azure Artifacts にデプロイする。
このパイプラインを作成するにあたって参考にしたドキュメントは以下のとおり。
トリガー条件は下記のようにv
からはじまるタグを切ったときだけにした方が望ましいかもしれない。
trigger:
tags:
include:
- "v*"
手動デプロイのときと違い、Npm@1
タスクが認証も含めてやってくれるので PAT を自前で用意する必要がない点が非常に便利である。
Azure Pipelines に登録する
.azure-pipelines/deploy.yml
のファイルをmain
ブランチにマージしてみると、実はパイプラインが発火しない。これは Azure Pipelines にこのファイルを登録してからでないと動作しないからである。なので、今回作成したファイルを登録する。
Azure DevOps のプロジェクトに入り、右のサービスリストから [Pipelines] > [Pipelines] のページを開く。
そのページにはおそらく [Create Pipeline] というのが表示されており、そのボタンを押す。
-
Connect
What is your code?
と聞かれるので [Azure Repos Git] を選択する。 -
Select
Select a repository
で自作パッケージのリポジトリ(catlib
)を選択する。 -
Configure
Configure your pipeline
ではすでにあるパイプラインを参照するので [Existing Azure Pipelines YAML file] を選択し、Path を.azure-pipelines/test.yml
にする。 -
Review
[Run] を押して実行するか、[Run] の隣にマークがあり、それを押すと [Save] があるので、セーブするだけでもよい。
Azure Artifacts に Azure Pipelines からデプロイできるようにする
これで実行してみたいところだが、このまま実行しても実はうまくいかない。これは Azure Pipelines の実行系にフィードに対しての write 権限がないためである。
フィードの<プロジェクト名> Build Service (<組織ID>)
に対してContributor
のロールを付与することで解決できる。
以下の公式ドキュメントを参考にして設定すればよいが、少しわかりにくいのが [Permissions] のところで、すでにリストにある User/Group でも [Add users/groups] からロールを変えることである。
実行
package.json
のversion
を変更してmain
ブランチにマージして正常に終了すれば成功である。
フィードに置いてあるライブラリのversion
も期待通りの値かも確認しておこう。
今後の課題
package.json
のversion
と Azure Repos のtag
を一致するように自動化できたら良い。
-
Power Shell だと動かないと思われる。Windows でも Git を導入しているのであれば Git Bash も同梱してくるはずである。これを使えば Bash ライクに操作できる。https://qiita.com/alpaca-honke/items/c7516823671e499eac7d
問題はパッケージのユーザーが顧客で Git 環境もない場合だが、配布側で PAT を Base64 にエンコードし、それを相手に教えれば良いだけである。 ↩︎
Discussion