Github Packagesことはじめ #techtekt Advent Calendar 2022

Github Packagesことはじめ #techtekt Advent Calendar 2022テクノロジー本部 エンジニアリング統括部 サービス開発部でエンジニアをしている青木です。
今年、担当していたプロジェクトでGithub Packagesを用いてprivate packageを作成した話を紹介します。

 

こんな人に見てほしい

  • 複数プロジェクト間でUIのリソースを共有したい
  • github repository間で共有したいリソースがある
  • npm packageを作る上での選択肢を知りたい

 

背景

当時担当していたプロジェクトでは、以下のような状況でした。

  •  サブプロジェクトA,Bの間でリソースを共有したい
    • UIコンポーネント
    • ユーティリティ、など

サブプロジェクトA,Bに関しては同じ技術スタック(Node.js+React+Next.js+TypeScript)であるため、リソースを再利用することができれば、開発効率向上が期待できる状態でした。

しかし、サブプロジェクトA,Bそれぞれでリソースを持つと、どちらかで変更が入った場合に手動で同期を取る必要が出てきます。したがって、共有が必要なリソースを適切な方法で一元管理することが重要であると考えられました。

解決策の検討

Githubでソースコード管理されている複数のプロジェクト間でリソースを共有したい場合、まず以下のような選択肢が考えられます。

  • git subtree, submodule
  • Github Actionsによるファイル同期

上記に関しても検討しましたが、Github Actionsによるファイル同期は以前挑戦した他プロジェクトがあったものの課題が多かったこと、git subtree, submoduleを各サブプロジェクトの開発手順に組み込むのがハードルが高かったことから見送りました。

今回のプロジェクトの場合はNode.jsベースだったため、パッケージマネージャーとしてはnpmを使っていました。そこで、共有したいリソースをパッケージとして提供することを検討しました。

部内でnpm packageを作成した経験は以前にもあったのですが、当時作成したpackageはpublicでした。public packageの場合、機密情報などが誤って入らないように注意する必要があり、簡易なツールなどであればよいのですが、今回のような規模の社内リソース共有に使うのは困難です。

したがってpackageを作成するのであれば、public packageではなくprivate packageとする必要があります。private packageを作成するのであれば以下のような選択肢があります。

  • npm registryを自前で立てる
  • Github Packagesを使う

npm registryを自前で立てるのは、VerdaccioなどのツールやJFrog Artifactoryなどのサービスを使えば可能ではありますが、継続してメンテナンスをしていく必要が出てきます。

今回のリソース共有の取り組みはスモールステップではじめたかったという背景もあり、最終的にGithub Packagesを使うことに決定しました。

Github Packagesとは

https://docs.github.com/ja/packages

GitHub Packages is a software package hosting service that allows you to host your software packages privately or publicly and use packages as dependencies in your projects.

GitHub Packages usage is free for public packages. For private packages, each account on GitHub.com receives a certain amount of free storage and data transfer, depending on the product used with the account. Any usage beyond the included amounts is controlled by spending limits.

Github PackagesとはGithubで提供されているpublic packageあるいはprivate packageのホスティングサービスです。

気になるお値段は、public packageの公開に使う分には無料、private packageの公開については無料分のストレージ&転送量を超えた分から課金されるということがわかりました。

部内のインフラセキュリティチームに相談したところ、コスト面も含めてOKをいただくことができました。

Github Packagesの仕組み

Github Packagesの仕組み

`npm install` した場合、通常は https://registry.npmjs.org/ をレジストリとして参照しますが、Github Packagesの場合は https://npm.pkg.github.com/ をレジストリとして参照に行くように設定する必要があります。

Personal Access Tokenの作成

Organization限定公開のprivate packageをpublishしたりインストールしたりする際には、Personal Access Tokenが必要となります。以下の手順で作成します。

  1. https://github.com/settings/tokens を開く
  2. `Generate new token` をクリック
  3. Note に利用用途を入力、Expiration と Scope (read:packages 必須) を設定
  4. Configure SSO等からOrganization認証を通す

Github Packagesの開発とデバッグ

packageの開発中に、ローカルでpackageとしての動作を確認したい場合は以下の手順を実施します。

  1. packageを作成し `npm run build` を実行
  2. 作成したpackageのディレクトリで `npm link` を実行
  3. 作成したpackageを利用するプロジェクトのディレクトリに移動
  4. `npm link <作成したpackageのpackage.jsonで定義した名前>` を実行

その他に `npm install <package dir>` でlocal packageとして追加する方法や、yalc を使う等の選択肢もありますので、環境に合わせた方法を適宜選択してください。

Reactでエラーが出る場合

package側と、packageを利用する側の双方でReactをdependenciesに入れていると、`npm run dev` した際に以下のようなエラーが出ます。

ReactのUnhandled Runtime Error

この場合は 3. You might have more than one copy of React in the same app に該当します。
Hooks don't work with yarn linkに書かれた回避策を参考に、以下のような手順でエラーを回避しました。

cd <PACKAGE_YOU_DEBUG_LOCALLY>
npm link
cd <PACKAGE_YOU_DEBUG_LOCALLY>/node_modules/react
npm link
cd <PACKAGE_YOU_DEBUG_LOCALLY>/node_modules/react-dom
npm link
cd <PROJECT_USES_THE_PACHAGE>
npm link <PACKAGE_YOU_DEBUG_LOCALLY>
npm link react
npm link react-dom

Github Packagesのpublish

以下の手順で https://npm.pkg.github.com へpackageをpublishします。

  1. HOMEディレクトリか、Github Packagesのディレクトリに以下の内容で .npmrc ファイルを作成
    @<org name>:registry=https://npm.pkg.github.com
  2. 以下のコマンドを実行し、作成したPersonal Access TokenをPassword に入力
    $ npm login --scope=@<org name> --registry=https://npm.pkg.github.com
    > Username: <USERNAME>
    > Password: <TOKEN>
    > Email: <PUBLIC-EMAIL-ADDRESS>
  3. package.json の以下の property に適切に値を設定
    • name - @<org name>/<package name>
    • repository - git://github.com/<org name>/<package repository>.git
    • publishConfig - https://npm.pkg.github.com
  4. `npm run build` を実行
  5. `npm publish` を実行

40X エラーになった場合

publishで40Xエラーになった場合は、以下を確認してみましょう。

  • Personal Access Tokenのscope
  • Personal Access TokenのOrganization認証を通せているか

publishしたprivate packageの削除

基本的にはいったんpublishしたpackageの削除はしない方が望ましいのですが、誤ってpublishしてしまった場合などはUIから削除することができます。

  1. Github repositoryのページで右のメニューからPackagesを選択
  2. 削除したいPackageを選択
  3. 右のメニューからPackage settingを選択
  4. Delete this packageを選択

Delete this package

Github Packagesのインストール

Organization限定公開のprivate packageをインストールする手順は以下になります。

  1. HOMEディレクトリか、Github Packages を利用したいrepositoryのディレクトリに以下の内容で .npmrc ファイルを作成
    @<org name>:registry=https://npm.pkg.github.com
  2. 以下のコマンドを実行し、作成したPersonal Access TokenをPassword に入力
    $ npm login --scope=@<org name> --registry=https://npm.pkg.github.com
    > Username: <USERNAME>
    > Password: <TOKEN>
    > Email: <PUBLIC-EMAIL-ADDRESS>
  3. `npm install` を実行する

Github Actions上でのGithub Packagesのインストール

  1. repositoryに.npmrcがpushされている場合は削除
  2. actions/setup-nodeを利用するときに registry-url scope を設定
  3. `npm install` の実行時に NODE_AUTH_TOKEN として該当のprivate packageにアクセスできるPersonal Access Tokenを設定
   - run: rm .npmrc

   - name: Use Node.js
     uses: actions/setup-node@v3
     with:
       node-version: <node version>
       registry-url: 'https://npm.pkg.github.com'
       scope: '@<org name>'

   - run: yarn install
     env:
       NODE_AUTH_TOKEN: ${{ secrets.AUTH_TOKEN_FOR_GITHUBPKG }}

まとめ

上記の通り、Github Packagesの作成と利用について、いくつか問題に直面した部分もありましたが、無事解決して進めることができました。

Githubをすでに組織単位で利用しているようなケースであれば、Organization限定公開のprivate packageを作成し、共有することができます。CIとして使っているのがGithub Actionであれば、private packageのインストールを組み込むのも容易です。

今回はあるプロジェクト内のサブプロジェクト間でのリソース共有でしたが、今後は更に発展させてプロジェクト間でのリソース共有を実現していきたいと考えています。

お読みいただきありがとうございました!

良いお年をお迎えください。

alt

青木 美穂子 Mihoko Aoki

エンジニアリング統括部 サービス開発部 第1グループ シニアエンジニア

新卒でIT企業へ入社。コンシューマ開発、金融・保険系プロジェクトへのサービスデリバリーなどを経て、Webアプリケーションフロントエンド開発のリーダーとしてBtoBサービスの開発に携わる。新規サービスの立ち上げとチームビルディングに参画できる機会に魅力を感じて、2020年7月にパーソルキャリア入社。

※2022年12月現在の情報です。