この記事はタイムリープ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を取得してもらってください