🗝️

Github Packagesで非公開のライブラリを社内展開する

2021/12/04に公開

これはストックマーク Advent Calendarの4日目の記事です。

ストックマークではdonguri-uiと呼ばれるデザインシステムやそれを元にしたコンポーネントライブラリを運用していて、複数プロダクトで使用されています。デザインシステムやライブラリ自体を社外に公開する企業も増えていますが、ストックマークでは現在公開せず運用しています。
このような公開していないケースでは、通常npmで公開されたものとは違う手法でインストールする必要があります。その一つとしてGithub Packagesを使用する方法があり、今年それを導入して管理するようにしたのでその話を紹介します。

背景

Github Packagesを使用する前は、社内の共有アカウントとそのパスワードによるbasic認証によって、プライベートリポジトリを直接 npm install していました。次のような設定が実際に使われていました。

package.json
"donguri-ui": "git+https://<共用アカウントID>:<パスワード>@github.com/stockmarkteam/donguri-ui.git#master"

この方法は、Githubのセキュリティ変更 (2021/8/13以降パスワード認証でリポジトリを参照することができなくなる) により使用できなくなるため、別の方法に変えなければならない状態でした。(参考までに、この対応は8/13より前に行いました)
他にも、git管理下のソースコードにパスワードやトークンをハードコードしていることや、semantic versioningが採用できていないために使用する側でバージョンを指定するのが手間でなかなか最新版が使われないという問題もありました。
上記のような問題の解決策として今回Github Packagesを導入しました。

対応内容

ここでは実際やったことを紹介します。

ライブラリ側での修正

Github PackagesではScoped package (@babel/env などのように@から/の間にスコープ名を含めたパッケージ名) のみをサポートしているのでpackage.jsonの name をScopedに変更する必要があります。

package.json
- "name": "donguri-ui",
+ "name": "@stockmarkteam/donguri-ui",

同じくpackage.jsonに npm publish するための設定を追加します。このとき、"access": "restricted"を設定しないとパッケージは公開されてしまう(誰でもインストールできてしまう)ので、非公開にしたい場合はこの設定が必要です。

package.json
+ "publishConfig": {
+   "access": "restricted",
+   "registry": "https://npm.pkg.github.com/"
+ },

最後に、Github ActionsでGithub Packagesへpublishするよう設定します。今回はGithubのGUI上でリリースを作成した時にこのCIが走るようにしています。

name: donguri-ui をGPRへリリースする

on:
  release:
    types: [created]

jobs:
  publish-gpr:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://npm.pkg.github.com/
      - (省略)
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

実際にはこのCIの中でビルド処理を行なっていますがその内容は今回省略します。

以上の対応により、Github Packagesで社内向けにライブラリを公開することができました。次にそれを使用する各プロダクト側で行った修正を紹介します。

使用する各プロダクトの修正

npmコマンドを実行するディレクトリに.npmrcファイルを作り、次の内容を追加します。

.npmrc
//npm.pkg.github.com/:_authToken=${GITHUB_READ_PACKAGES_TOKEN}
@stockmarkteam:registry="https://npm.pkg.github.com"

一行目のGITHUB_READ_PACKAGES_TOKENにはプライベートなパッケージにアクセスするためのトークンを環境変数で渡しています。
この値はGithubの設定画面で開発者各自が自身のアカウントで作成したものを、各々の開発環境に設定してもらっています。このとき、トークンの権限は read:packages のみにすることで、もしトークンが流出した場合でも被害を最小限に絞ることができます。

また、ライブラリ側でパッケージ名を変更したので、package.jsonやインポートしているファイルでもパッケージ名を変える必要があります。

package.json
- "donguri-ui": "git+https://<共用アカウントID>:<パスワード>@github.com/stockmarkteam/donguri-ui.git#master",
+ "@stockmarkteam/donguri-ui": "1.0.0",
index.ts
- import DonguriUI from 'donguri-ui';
+ import DonguriUI from '@stockmarkteam/donguri-ui';

Github Packagesに変えてみて

実際に変えて運用した結果、次のような利点がありました。

  • npm updateで使用するライブラリのバージョンを上げれるようになり、最新版を使うハードルが下がった
  • masterブランチへpushするときにビルド結果も含める必要があったが、publish前にCIでビルドを行うようにフローを変更したためビルド結果が不要になった
  • Githubアカウントとライブラリへのアクセス権を紐づけることができたので、メンバーが変わったとき時などの権限管理が楽になった
  • (副次的な効果として)ライブラリ管理の方法が属人化していたが、今回フローを更新し改めてエンジニアに共有したことで、ライブラリへコミットするメンバーが増えた

CI設定など開発フロー自体にはまだまだ改善の余地があるので、引き続きより良い方法を模索していきたいと考えています。
また、Github PackagesはNode.jsのパッケージ以外にも適用可能なので、今後社内ライブラリを作成する時にも使っていくことができます。

注意点として、Github Packagesをプライベートリポジトリで使う場合、Github Actions以外への転送量によって課金されます。そのため他のCIサービスを使用している場合は料金が発生する場合があります。

最後に

本稿で紹介した改善をするにあたって、公式ドキュメントの他に、PLAIDさんのnpmのprivate registryからGitHub Packages Registryに移行する記事を参考にさせていただきました。npm private registryとGithub Packagesの比較もまとまっているので気になる方はそちらも参照ください。

Discussion