概要
- 社内向けの npm packages を publish するのに GitHub Packages が便利
- GitHub 内で完結してお手軽 & Actions を使って自動リリースフローを作りやすい
- しかし GitHub Packages に上がっている npm packages を npm install するには少々手間がかかる
- 具体的には GitHub の Personal Access Token (以下PAT) を使い、npm-cli を認証させる必要がある
- https://docs.github.com/ja/packages/guides/configuring-npm-for-use-with-github-packages#installing-a-package
repo
とread:packages
にチェックの入ったトークンが必要- package が public/private に限らず認証必須
- 従って、GitHub Packages に上がっている npm packages を使うプロジェクトでは、npm install をするあらゆる場面で、PAT による認証を挟んでおかなければならない
- local で
docker-compose up
する時 - actions/jenkins 上で Node.js の CI を走らせる時
- リリース用の docker image を CI 上で作る時
- ...などなど
- local で
- この時 PAT をどう管理するか、というのが意外と悩ましい (と個人的に思っている)
- 何か楽な方法がないか色々考えてみる
案1: 社内の共有GitHubアカウントで発行した PAT をリポジトリの .npmrc
に埋め込んでおく
共有トークンをリポジトリにベタ書きし、リポジトリに直接 commit してしまう、という案。
.npmrc
:
//npm.pkg.github.com/:_authToken=<社内の共有GitHubアカウントで発行したトークンをここに貼る> @example-corp:registry=https://npm.pkg.github.com/
- メリット
- npm は
npm install
時に自動でカレントディレクトリにある.npmrc
を見て認証してくれるので、これさえ書けば local だろうと actions だろうと jenkins だろうと、全ての場所で動く
- npm は
- デメリット
- リポジトリにトークンが commit されてしまう
案2: プロジェクトを動かしたい人ごとに PAT を発行して、.npmrc
に直書きしてもらう & GitHub Secrets などの仕組みを使う
共有トークンを commit するのを避けて、個人で PAT を発行して、それを使ってもらうという案。
.env
などに個人で発行した PAT を埋め込んでおき、dotenv などと組み合わせて以下のように .npmrc
から読み込む。
.npmrc
:
//npm.pkg.github.com/:_authToken=${NPM_TOKEN} @example-corp:registry=https://npm.pkg.github.com/
これだけだと local でしか PAT が設定されず、actions や jenkins 上では認証ができないので、適時 GitHub Secrets や Jenkins の Credentials を使って PAT を環境変数 NPM_TOKEN
に設定するようにしておく。
サードパーティツールへのパスを設定 - Cloud https://docs.github.com/ja/actions/reference/encrypted-secrets *1
- メリット
- トークンがリポジトリに commit されない
- デメリット
- プロジェクトを使いたい個人ごとにトークンを発行しないといけない
- 一度セットアップすれば良いとはいえちょっと手間
- プロジェクトを使いたい個人ごとにトークンを発行しないといけない
package が公開可能な場合
社内向けだけど OSS にして良いとか、公開可能な場合は他にも取れる手段がある。
案3: npmjs.com に公開する
- npmjs.com に public で package を publish する方法
- デメリット
- 公開可能な package でないと利用できない
- npmjs.com のアカウントを作るのがちょっと手間
- まあ一度作ってしまえば良いのだけど
案4: git 形式で npm install
する
- 予め GitHub リポジトリを公開しておき、
npm install https://github.com/example-corp/xxx.git#v1.0.0
でインストールする方法 - デメリット
- 公開可能な package でないと利用できない
- 事前ビルドが必要な package との相性が悪い
- というのも、通常 Git リポジトリにはビルドの成果物が commit されていない & git 形式の
npm install
は単に git に commit されているファイルをコピーしてnode_modules
配下に置くだけで、npm run build
などはしてくれないため
- というのも、通常 Git リポジトリにはビルドの成果物が commit されていない & git 形式の
npm update
/yarn upgrade
や renovate でアップデートできない *2- データソースが npm repository でないため、標準的なツールを使ったアップデートができない
@example-corp:registry=<URL>
の注意点
.npmrc
に記載する @example-corp:registry=<URL>
は @example-corp
をスコープとするパッケージ全てを <URL>
から取得する使用になっています。つまり @example-corp/package-a
, @example-corp/package-b
, ... は全て <URL>
から取得されます *3。その挙動の影響で「GitHub Packages にホストされている @example-corp
スコープのパッケージ」と「npmjs.com にホストされている @example-corp
スコープのパッケージ」を共存させることができないという既知の問題があります。public package は npmjs.com、private package は GitHub Packages、みたいな運用をしているとハマります。もしそういう使い方をする予定であれば、GitHub Packages or npmjs.com のどちらかに寄せる、という対応を別途検討したほうが良いでしょう *4。
この問題については以下の記事が詳しいので、それぞれ読んでみるとよいと思います。
- GitHub Package Registry and Npm Registry for same scoped does not work @ 2020-01-10 · GitHub
- npmのprivate registryからGitHub Packages Registryに移行する
どの方式も一長一短あって難しい。皆さんはどうしてますか?
*1:Organization Secrets というやつがオススメです
*2:npm update / yarn upgrade は手元で試して確認した。renovate も https://github.com/mizdra-sandbox/git-npm-package-test/issues/1 で試して確認した。dependabot は試してないので知りません。
*3:URL に無かったら npmjs.com から取得するといった fallback も一切ないので、URL にないパッケージのインストールは失敗する。
*4:GitHub Packages と npmjs.com でスコープ名を変えるという素朴な workaround もある