見出し画像

GitHub Packagesのnpm registryを利用してパッケージを公開してみた

はじめに

こんにちは、SHIFTの開発部門に所属している Katayama です。

GitHub にはGitHub Packagesと呼ばれるパッケージを公開できる機能がある。パッケージには、npm・RubyGems・Docker などの主要なパッケージ(コンテナ)レジストリに対応している(概要についてはGitHub Packages についてを参照)。

今回は自作のパッケージを作成して GitHub Packages に公開して別のプロジェクトでそれを利用する、というのをやってみようと思う。また、他の人が作成した GitHub Packages に公開済みの npm ライブラリをインストールして利用する、という事もやってみようと思う。

パッケージを作成して、GitHub Packages に公開する

ローカル環境から GitHub Packages に公開する

まず初めに、ローカル環境から GitHub Packages にパッケージを公開する方法をやってみる。

GitHub Packages への認証を行うに書かれている通り、まず認証が必要になるので、その準備として個人アクセストークンを発行する。手順は個人用アクセス トークンの作成に書かれている。

今回のパッケージの公開にはパッケージの管理宛先リポジトリへの認証に記載がある通り、write:packages の権限が必要になるので、上記ではそれにチェックを入れ、トークンを発行している。

次に、宛先リポジトリの設定パッケージの公開に書かれている通り、package.json の name と repository の設定を変更する。具体的には以下のように、name は "@{Organization 名 or 個人アカウント名}/{公開されるリポジトリ名}" となるようにし、repository には Package を公開するリポジトリの URL を記載する。

{
	"name": "@yuta-katayama-23/learn-mysql",
	...
	"repository": {
		"type": "git",
		"url": "https://github.com/yuta-katayama-23/learn-mysql.git"
	},

最後に実際にパッケージを公開していくが、その際の認証方法で 2 パターンに分かれ、設定が変わるのでそれぞれについてみていく(個人アクセストークンでの認証を参照)。

①.npmrc にトークンを記載する

この方法は以下のように、.npmrc にアクセストークンを記載する方法。トークン自体は各個人で別になるので、この方法の場合には.npmrcはgitignoreの対象にする必要がある(チーム内でトークンを使いまわす運用もできるだろうが、あまりセキュリティ的によろしくない)。

//npm.pkg.github.com/:_authToken=gh......................OU

上記の方法を取る場合、さらにやり方は 2 パターンに分かれる。

A: .npmrc ファイルを使用する

このパターンはローカルの .npmrc ファイルを使用したパッケージの公開に書かれている方法で、.npmrc にトークンに加えて以下のようにパッケージを公開する場(レジストリ)に関する設定を追記する。

//npm.pkg.github.com/:_authToken=gh......................OU
@yuta-katayama-23:registry=https://npm.pkg.github.com/

後は、以下のように "npm publish" コマンドを実行すればいい。

study@localhost:~/workspace/learn-mysql (main *)
$ npm publish
npm notice
npm notice 📦  @yuta-katayama-23/learn-mysql@1.0.0
npm notice === Tarball Contents ===
npm notice 328B  .eslintrc.json
...
npm notice === Tarball Details ===
npm notice name:          @yuta-katayama-23/learn-mysql
npm notice version:       1.0.0
npm notice filename:      @yuta-katayama-23/learn-mysql-1.0.0.tgz
npm notice package size:  17.5 kB
npm notice unpacked size: 1.6 MB
npm notice shasum:        d2dd481c1fe381a0f9b623578e518271971886c7
npm notice integrity:     sha512-PbyFpHYa2Usoa[...]VnUqqqZF2HzlA==
npm notice total files:   17
npm notice
npm notice Publishing to https://npm.pkg.github.com/
+ @yuta-katayama-23/learn-mysql@1.0.0

上記のコマンドを実行すると、以下の画像のように GitHub Packages にパッケージを公開で着ている事が確認できる(基本的に、初期では private のパッケージとして公開されるので、public にするには "Package settings" から "Change package visibility" を行う必要がある)。

B: package.json に publishConfig の設定を行う

この方法はpackage.json ファイルでの publishConfig を使用したパッケージの公開に書かれている方法で、上記では .npmrc にレジストリの設定を書いていたが、これを package.json に記載する方法。以下のように記載すればいい。

package.json{
	"name": "@yuta-katayama-23/learn-mysql",
	"version": "1.0.2",
	...
	"repository": {
		"type": "git",
		"url": "https://github.com/yuta-katayama-23/learn-mysql.git"
	},
	"publishConfig": {
		"registry": "https://npm.pkg.github.com"
	},
	...

上記のように設定し、 .npmrc の方にはトークンのみ記載した状態で "npm publish" コマンドを実行すると、上記の「A: .npmrc ファイルを使用する」同様にパッケージを公開する事ができる。

study@localhost:~/workspace/learn-mysql (main *)
$ npm publish
...
+ @yuta-katayama-23/learn-mysql@1.0.2

続いて、以下では .npmrc にトークンを記載しない方法でのパッケージ公開方法を見ていく。

②npm login コマンドでログインする

この ② は npm にログインして認証するパターンで、npm login コマンドを使用する。
公式の以下の画像の USERNAME などは説明にある通り、USERNAME を GitHub のユーザー名、TOKEN を個人用アクセストークン、PUBLIC-EMAIL-ADDRESS を自分のメールアドレスに、それぞれ置き換える。

study@localhost:~/workspace/learn-mysql (main *)
$ npm login --scope=@yuta-katayama-23 --registry=https://npm.pkg.github.com
npm WARN adduser `adduser` will be split into `login` and `register` in a future version. `adduser` will become an alias of `register`. `login` (currently an alias) will become its own command.
npm notice Log in on https://npm.pkg.github.com/
Username: yuta-katayama-23
Password:                 <- 見えないが①の{TOKEN}と同じトークンを記載
Email: (this IS public) ‥‥‥@gmail.com
Logged in as yuta-katayama-23 to scope @yuta-katayama-23 on https://npm.pkg.github.com/.

認証が済んだ後は、.npmrc または package.json の publishConfig にレジストリの設定を記載していれば、 "npm publish" コマンドでパッケージの公開ができる。

・.npmrc にレジストリの設定をした場合

@yuta-katayama-23:registry=https://npm.pkg.github.com/

・package.json の json の publishConfig にレジストリの設定をした場合

{
	...
	"publishConfig": {
		"registry": "https://npm.pkg.github.com"
	},
	...

CI でパッケージを公開する

CI(GitHub Actions)からパッケージを公開する方法についてみていきたいと思う。
やり方としてはパッケージを公開するGitHub Packages へのパッケージの公開Ensuring workflow access to your packageなどが参考になる。

まず、GitHub Actions のワークフローを以下のように作成する。

name: ci

on:
  push:
    branches: [main]

  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read

    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-node@v3
        with:
          node-version: "16.17.0"
          registry-url: https://npm.pkg.github.com/

      - name: yarn install
        run: yarn install

      - name: build
        run: yarn build

      - name: publish
        run: yarn publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

actions/setup-node@v3は GitHub Actions 公式のアクションで、GitHub Actions での Node 環境のセットアップなどを行えるもの。
今回はPublish to npmjs and GPR with yarnにあるような、パッケージを公開する上で必要な設定を行うために利用している。具体的には、.npmrc ファイルを動的に生成し、トークン・レジストリの設定を行ってくれる。

ワークフロー内で、 "cat ~/work/_temp/.npmrc" で中身を確認してみると以下の通り、トークン・レジストリの設定が行われている事が分かる(${NODE_AUTH_TOKEN}の部分は、ワークフロー内の環境変数で置き換えられる部分で、 secrets.GITHUB_TOKEN が実際に置き換わる値。この GITHUB_TOKEN はワークフロー内で自動生成されるもので、詳細はAutomatic token authenticationなどを参照。トークンは permissions のキーで設定しているパーミッション・権限を持つ)。

あとは、Ensuring workflow access to your packageにあるように、どの GitHub Actions から GitHub Packages にアクセスできるようにするか?という設定をすればいい("Manage Actions access" の "Add Repository" から GitHub Packages のパッケージにアクセスできる GitHub Actions を追加する)。

ここの設定ができていない場合、以下のように permisson で 403 エラーになる(手動で GitHub packages にパッケージを公開した場合は手動で上記のように GitHub Actions から当該のパッケージにアクセスできるように設定する必要があるが、GitHub Actions で初めてパッケージを公開する場合は、上記の設定は不要で、パッケージの公開に成功すると、自動でそのパッケージ公開を行った GitHub Actions が登録される)。

実際に GitHub Actions のワークフローを実行してみると、以下の画像のようにワークフローが成功している事が確認でき、さらに GitHub Packages 上のパッケージも更新されている事が確認できる。

他の人が作成した GitHub Packages に公開済みの npm ライブラリをインストールして利用する

今回は GitHub の方で例として公開しているhello-world-npmというパッケージ(ライブラリ)があるので、これをインストールして利用してみたいと思う(先ほど公開したパッケージを利用する際も全く同じ手順になる)。

まずは GitHub Packages への認証が必要だが、これは "npm login"コマンドでログインする方法でも、.npmrc にトークンを記載する方法でもどちらでもよい(今回は.npmrc にトークンを記載する方法で行う)。

//npm.pkg.github.com/:_authToken=gh......................OU

次に、インストールしたいパッケージが GitHub packages にあるので、パッケージの在りか=レジストリの設定を行う。
今回利用しようとしているパッケージの所有者は@codertocat なので、以下のようにレジストリの設定を追記すればいい。

//npm.pkg.github.com/:_authToken=gh......................OU
@codertocat:registry=https://npm.pkg.github.com

あとは "npm install" or "yarn add" でパッケージをインストールすればいい。

study@localhost:~/workspace/github-package-test
$ yarn add @codertocat/hello-world-npm
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ @codertocat/hello-world-npm@1.0.2
info All dependencies
└─ @codertocat/hello-world-npm@1.0.2
Done in 1.78s.

実際に実装してみると、問題なくパッケージ・ライブラリのコードが利用できる事も確認できる。

const myPackage = require("@codertocat/hello-world-npm");
myPackage.helloWorld();
study@localhost:~/workspace/github-package-test
$ node index.js
Hello World!

※ちなみに、複数の organization からパッケージをインストールしたい場合、以下のように複数行レジストリの設定を記載すればいい(他の Organization からのパッケージのインストールを参照)

//npm.pkg.github.com/:_authToken=gh......................OU
@codertocat:registry=https://npm.pkg.github.com
@yuta-katayama-23:registry=https://npm.pkg.github.com
package.json{
  "name": "github-package-test",
  ...
  "dependencies": {
    "@codertocat/hello-world-npm": "^1.0.2",
    "@yuta-katayama-23/learn-mysql": "1.0.11"
  }
}

・参考:パッケージのインストール

まとめとして

今回は GitHub Packages を利用して、自作のパッケージを公開してみたり、既に公開済みのパッケージをインストールして利用したりしてみた。
共通機能をライブラリ化して組織内で共有したいといった場面では、AWS の CodeArtifact なども候補に上がりそうだが、その場合には AWS 環境が別に必要になったりと別のコストがかかるので、GitHub ユーザーであれば GitHub Packages を利用する事で、簡単にその要望を実現でき便利そうだと思った。

また、Github Packagesであれば、パッケージが信頼できるソースである、社内で承認されたものだけを使えるように設定する事が可能、といった利点もあるだろう。

次回は ESLint などで CLI(npx eslint src/...のようなコマンド)が利用できるのはなぜか?と実際に自作の npm パッケージの CLI ツールを実装してみたいと思う。

《この公式ブロガーの記事一覧》


執筆者プロフィール:Katayama Yuta
認証認可(SHIFTアカウント)や課金決済のプラットフォーム開発に従事。リードエンジニア。
経歴としては、SaaS ERPパッケージベンダーにて開発を2年経験。 SHIFTでは、GUIテストの自動化やUnitテストの実装などテスト関係の案件に従事したり、DevOpsの一環でCICD導入支援をする案件にも従事。その後現在のプラットフォーム開発に参画。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら 
https://recruit.shiftinc.jp/career/