この記事はタイムリープTypeScript 〜TypeScript始めたてのあの頃に知っておきたかったこと〜
15日目の記事です。
みなさんはnpmにパッケージをpublishしたことがありますか?私はあります。
このNPM、実は一度publishしたパッケージはpublishしてから72時間以内でないと非常に削除がしづらくなります。一応削除するためにはnpm unpublish
というコマンドがあるのですが、そのパッケージがpublishされてから72時間以内かどうかで対応が変わります。
npm Unpublish Policy
ここに説明があるのですが、72時間以内であれば
For newly created packages, as long as no other packages in the npm Public Registry depend on your package, you can unpublish anytime within the first 72 hours after publishing.
つまり、npmの他の(publicである)パッケージが依存していない限り削除できます。一方72時間を超えると
Regardless of how long ago a package was published, you can unpublish a package that:
- no other packages in the npm Public Registry depend on
- had less than 300 downloads over the last week
- has a single owner/maintainer
npmのpublicであるパッケージが依存しておらず、直近1週間のダウンロード数が300未満であり、オーナーまたはメンテナーが1人でなければ削除できません。
組織内で使う共通ライブラリやビジネスロジックなどを誤ってpublishしてしまうと迅速にunpublishしない限り非常に削除しづらくなってしまいます。
👶ではどうすればいいんですか
このようなデジタルタトゥーをこれ以上生み出さないためにも今回紹介するのはnpmではなくGitHubのパッケージレジストリ、その名もGitHub Package Registry(以下GPRと称します)にパッケージをGitHub Actionsからpublishし、それを使用する方法を紹介いたします。
GPRにpublishする
publishするためには大まかには以下の手順になります。
- package.jsonの
name
に@xxx
(スコープ)を追加する - package.jsonの
private
をfalseにする - package.jsonに
publishConfig
を書き込む
package.jsonのname
に@xxx
(スコープ)を追加する
パッケージの名前をyyy
から@xxx/yyy
に変更します。一般的にxxx
はパッケージのオーナーの名前を使い、常に@
から始まります。
例: "name": "awesome-package"
-> "name": "@jamashita/awesome-package"
package.jsonのprivate
をfalseにする
これはnpmにパッケージを登録するときと同じです。
例: "private": true
-> "private": false
package.jsonにpublishConfig
を書き込む
以下を追加します。
"publishConfig": {
"access": "restricted",
"registry": "https://npm.pkg.github.com/"
}
access
についてはpublicパッケージにしたければpublic
にし、privateパッケージにしたければrestricted
に設定します。
あとはGitHub ActionsでGPRにpublishするjobを設定します。以下はそのサンプルです。
jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.0
registry-url: https://npm.pkg.github.com
scope: '@xxx'
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: npm install
- run: npm publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
普通のpublishを行うときと異なるのは4点です。
actions/setup-node@v2
のregistry-url
ここでpublishする向き先をhttps://npm.pkg.github.com
に変更します。
actions/setup-node@v2
のscope
package.jsonで指定した@xxx
(スコープ)を指定します。
actions/setup-node@v2
のenv.NODE_AUTH_TOKEN
ここには${{ secrets.GITHUB_TOKEN }}
を設定します。
publishするときのenv: NPM_TOKEN
NPM_TOKEN
に${{ secrets.GITHUB_TOKEN }}
を設定します。
これでGPRにGitHub Actionsを使ってパッケージをpublishできるようになりました。
GPRのパッケージを取得する
GPRに登録されたパッケージを取得するには以下の手順が必要になります。
-
read:packages
権限のPersonal access token(以下PATと称します)を取得する -
~/.npmrc
に先ほどのPATを書き込む - 使用したいプロジェクトの
.npmrc
にスコープの参照先を変更するよう記述する
read:packages
権限のPersonal access tokenを取得する
PATはユーザーのSettings > Developer settings > Personal access tokensで取得できます。このときの権限は上述のとおりread:packages
のみです。
~/.npmrc
に先ほどのPATを書き込む
~/.npmrc
に取得したPATを書き込みます。PATをxxxxyyyyzzzz
とした場合、以下の一文を追加してください
//npm.pkg.github.com/:_authToken=xxxxyyyyzzzz
使用したいプロジェクトの.npmrc
にスコープの参照先を変更するよう記述する
使用したいプロジェクトのルートディレクトリに.npmrc
を置き、以下の一文を加えます。
@xxx:registry = https://npm.pkg.github.com
@xxx
はスコープです。こうすることによってこのスコープが付けられたパッケージだけはGPRにパッケージを探しに行くようになります。
これで通常どおりnpm install
でGPRに登録されたパッケージを使うことができるようになります。
登録したパッケージをGitHub Actionsで使いたい
CIなど、GitHub Actionsで登録したパッケージを使いたいときがあります。そのときは登録したパッケージがGPRにあることをGitHub Actionsに教えてあげないとたとえ使う側、使われる側が同じオーナーであってもパッケージをインストールすることができません。そこで以下のようにします。
read:packages
権限のPATを取得する
これは上述のGPRのパッケージを取得するの**read:packages
権限のPersonal access tokenを取得する**と同じです。
PATを使う側のプロジェクトのSecretsに追加する
使う側のプロジェクトにあるSettings > Secretsに先ほどのPATを追加します。
GitHub Actionsで先ほど登録したPATを参照してnpm install
をする
追加したPATの名前がGPR_TOKEN
ならGitHub Actionsのjobは以下のようになります。
jobs:
ci:
runs-on: 'ubuntu-latest'
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.0
registry-url: https://npm.pkg.github.com
scope: '@xxx'
- run: npm install
env:
NODE_AUTH_TOKEN: ${{ secrets.GPR_TOKEN }}
- run: npm test
特筆すべきところは1点です。
npm install
時にenv.NODE_AUTH_TOKEN
を設定する
ここで先ほど取得したPATの名前の前にsecrets.
を加えます。するとGitHub Actionsは@xxx
のスコープのパッケージをGPRから取得できるようになります。
🤖個人だけではなく組織でも使いたい
組織の場合、個人のようにPATを取得することができません。ではGPRを使ったパッケージ管理ができないかというとできます。方法は簡単で組織に属しているメンバーの誰かがPATを取得し、同じようにすることでGitHub Actionsでパッケージの取得ができるようになります。
このときPATをプロジェクトのSecretsに加えても、組織のSecretsに加えても同様に機能します。
🧟注意すること
- GPRにあるパッケージはNPMと異なり削除が容易です。誤って消してしまったり組織のメンバーの謀反に遭うとパッケージが消える恐れがあります
- できるだけ辞めなさそうな組織のメンバーにPATを取得してもらってください