🧳

Gitlab Package Registryを利用してプライベートNPMパッケージを運用する

2021/12/10に公開

はじめに

はじめまして!株式会社エイチームコマーステックの gami です。ソフトウェアエンジニアとして、モバイル、Web フロントエンド、バックエンドなど広く開発に携わっています。
この記事はAteam Commerce Tech Inc. Advent Calendar 2021 Advent Calendar 2021の 10 日目の記事です。

サービスを開発する際、複数のプロジェクト間でプログラムを再利用したいケースがあると思います。この記事では、JavaScript で書かれたプログラムを共通パッケージ化し、社内のみで利用するプライベートパッケージとして運用する方法を記載します。

エイチームコマーステックでは SaaS 版 Gitlab を利用しているため、NPM レジストリにはGitlab Package Registryを採用しました。

要約

  • パッケージレジストリ用のプロジェクトを作成する
  • レジストリにアクセスするためのトークンを発行 & セットする
  • (パッケージ開発側) トークンを利用してnpm publishする
  • (パッケージ利用側) トークンを利用してnpm installする

全体図
全体図

パッケージ開発側

  • パッケージレジストリを設定したら、npm configでレジストリの URL とトークンを指定する
  • npm publishでレジストリにパッケージを公開する

パッケージ利用側(アプリケーションなど)

  • npm configでレジストリの URL とトークンを指定する
  • npm installを実行する

環境

  • macOS 12.0.1
  • node v14.18.1
  • npm 6.14.15

パッケージを開発する

まずは NPM パッケージを作成する方法についてです。

適当なパッケージの作成

npm initを実行し、package.jsonを作成します。
この記事のためのデモパッケージを用意しました。

package.json

package.json
{
  "name": "@hytkgami/my-awesome-package",
  "version": "1.0.0",
  "description": "This package is awesome!!",
  "main": "index.js",
  "type": "commonjs",
  "repository": {
    "type": "git",
    "url": "git+ssh://git@gitlab.com/hytkgami/myawesomepackage.git"
  },
  "author": "hytkgami",
  "license": "MIT",
  "bugs": {
    "url": "https://gitlab.com/hytkgami/myawesomepackage/issues"
  },
  "homepage": "https://gitlab.com/hytkgami/myawesomepackage#readme"
}

index.js

index.js
const packageName = () => {
  return "My Awesome Package";
};
const greet = () => {
  console.log("Hello!");
};

module.exports = {
  packageName: packageName,
  greet: greet,
};

このパッケージのディレクトリ構造は下記のとおりです。

tree
.
├── README.md
├── index.js
└── package.json

トークンの作成

タイトルにプライベートパッケージとあるとおり、Gitlab のプライベートプロジェクトを前提としています。プライベートプロジェクトのため、レジストリにアクセスするためには認証情報となるトークンが必要です。
Gitlab ではトークンの作成方法がいくつかあります。

  • Personal Access Token
  • Deploy Token
  • CI Job Token

企業や団体で開発・運用する場合は、Deploy Token や CI Job Token を利用すると良さそうです。

Personal Access Token の作成手順

Gitlab ユーザーに紐づくトークンです。前提として 2FA を有効にしている必要があります。

  1. Gitlab にログインした状態で https://gitlab.com/-/profile/personal_access_tokens にアクセスする
  2. トークンの名前を入力する
  3. 必要な権限(api, read_registry, write_registry)を選択する

Create personal access token

  1. Create personal access tokenと書かれたボタンをクリック
  2. 表示されるトークンを控えておく
Deploy Token の作成手順

Gitlab プロジェクトやグループに紐づくトークンで、管理できるのはメンテナ権限[2]を持つユーザのみです。
プロジェクトに紐づくため、トークンを作成したユーザがプロジェクトから削除されてもトークンは有効です。

  1. デプロイトークンを作成したいプロジェクトやグループを開く
  2. サイドバーの Settings をクリックする
  3. サイドバーの Repository をクリックする

Gitlab project side bar

  1. トークンの名前を入力する
  2. 必要な権限(write_registry)を選択する

Create deploy token

  1. Create deploy tokenと書かれたボタンをクリック
  2. 表示されるトークンを控えておく
CI Job Token の作成手順

Gitlab CI/CD を利用している場合に有用です。
パイプラインを生成するユーザーの権限を継承します。

Gitlab CI/CD の環境変数CI_JOB_TOKENとして Gitlab で事前定義[3]されているため、特に作成手順はありません。

控えたトークンを利用するようにnpm configを実行する

パッケージの参照先と認証情報を設定します。

npm config set @foo:registry https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/
npm config set -- '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
  • <your_project_id>は Gitlab プロジェクトの ID に置き換えてください
  • <your_token>は、用意したトークンに置き換えてください
  • gitlab.example.comの部分は Gitlab を運用しているドメインに置き換えてください
    • エイチームコマーステックでは SaaS 版を利用しているためgitlab.comとなります

デモパッケージ用の設定に置き換えると、下記のようになります。

npm config set @hytkgami:registry https://gitlab.com/api/v4/projects/31924312/packages/npm/
npm config set -- '//gitlab.com/api/v4/projects/31924312/packages/npm/:_authToken' $DEPLOY_TOKEN

トークンは環境変数$DEPLOY_TOKENにセットしました。
ここまでの設定はnpm configではなく.npmrcとしてファイルにしておくことも可能です。
その場合は下記のようになります。

.npmrc
@hytkgami:registry=https://gitlab.com/api/v4/projects/31924312/packages/npm/
//gitlab.example.com/api/v4/projects/31924312/packages/npm/:_authToken=${DEPLOY_TOKEN}

CI Job Token を利用する場合は、DEPLOY_TOKENの部分をCI_JOB_TOKENに置き換えてください。

パッケージの公開

ここまでの手順で、Gitlab に NPM パッケージをアップロードするためのエンドポイント設定と認証情報の設定が完了しました。
NPM パッケージのプロジェクトルートで下記コマンドを実行します。

npm publish

このように、指定したレジストリにパッケージがアップロードされていれば OK です。

published_private_npm_package
@hytkgami/my-awesome-package がアップロードされている

Gitlab にアップロードされたパッケージを利用する

つづいて、Gitlab にアップロードしたパッケージを利用する側の設定です。
パッケージ利用者も、ここまでの流れと同様にトークンを利用してプライベートパッケージにアクセスします。

トークンの用意

個人の開発環境でnpm installする場合は Personal Access Token、Vercel などにアプリケーションのデプロイを任せている場合は Deploy Token、Gitlab のパイプライン上でnpm installする場合は CI Job Token を利用すると良いと思います。

Personal Access Token の作成手順
  1. Gitlab にログインした状態で https://gitlab.com/-/profile/personal_access_tokens にアクセスする
  2. トークンの名前を入力する
  3. 必要な権限(api, read_registry)を選択する
  4. Create personal access tokenと書かれたボタンをクリック
  5. 表示されるトークンを控えておく
Deploy Token の作成手順
  1. デプロイトークンを作成したいプロジェクトやグループを開く
  2. サイドバーの Settings をクリックする
  3. サイドバーの Repository をクリックする
  4. トークンの名前を入力する
  5. 必要な権限(read_registry)を選択する
  6. Create deploy tokenと書かれたボタンをクリック
  7. 表示されるトークンを控えておく
CI Job Token の作成手順

Gitlab CI/CD の環境変数CI_JOB_TOKENとして Gitlab で事前定義[3:1]されているため、特に作成手順はありません。

プライベートパッケージのインストール

下記のコマンドを実行します。

npm install <your_package>

ここまででプライベートパッケージをインストールすることができたと思います。
公式ドキュメントにはより詳細な内容が書かれていますので、うまくいかない場合や複雑なケースに対応したい場合はぜひご覧ください。

[おまけ] デモパッケージを使った検証

パッケージを利用するためのプロジェクトを作成する

お好きなディレクトリにテスト用プロジェクトを作成します。

mkdir demo_project && cd $_

プライベートパッケージをインストールします。

npm i @hytkgami/my-awesome-package

node_modulesにプライベートパッケージが追加されました。

.
├── node_modules
│   └── @hytkgami
│       └── my-awesome-package
│           ├── README.md
│           ├── index.js
│           └── package.json
└── package-lock.json

検証用の簡単なプログラムを書きます。

touch index.js
const myAwesomePackage = require("@hytkgami/my-awesome-package");
console.log(myAwesomePackage.packageName());
myAwesomePackage.greet();

プログラムを実行します。

node index.js
実行結果
My Awesome Package
Hello!

パッケージで定義した関数を読み込み、利用することができました。

パッケージをアップデートする

NPM パッケージを開発したリポジトリに戻り、下記の変更を加えます。

index.js
 const greet = () => {
   console.log('Hello!');
 }
+const version = () => {
+  return 'v2.0.0';
+}

 module.exports = {
   packageName: packageName,
-  greet: greet
+  greet: greet,
+  version: version
 }
package.json
{
   "name": "@hytkgami/my-awesome-package",
-  "version": "1.0.0",
+  "version": "2.0.0",
   "description": "This package is awesome!!",
   "main": "index.js",
   "type": "commonjs",

パッケージを公開します。

npm publish

Uploaded latest package
新しいパッケージがアップロードされました

アップデートされたパッケージを利用する

再びテスト用プロジェクトに戻り、アップデートされたパッケージをインストールします。

npm i @hytkgami/my-awesome-package

+ @hytkgami/my-awesome-package@2.0.0
updated 1 package and audited 1 package in 1.682s
found 0 vulnerabilities

@hytkgami/my-awesome-package@2.0.0がインストールされたようです。
新しく追加されたversion関数を試してみましょう。ファイルを編集します。

index.js
const myAwesomePackage = require("@hytkgami/my-awesome-package");
console.log(myAwesomePackage.packageName());
myAwesomePackage.greet();
+console.log(myAwesomePackage.version());

プログラムを実行します。

node index.js
実行結果
My Awesome Package
Hello!
v2.0.0

新たに追加された関数を使うことができました。

終わりに

Ateam Commerce Tech Inc. Advent Calendar 2021 Advent Calendar 2021の次回の記事は、@kazzzzzz による「Hasura と Nextjs で快適な開発環境を作る」です。お楽しみに 🕺

脚注
  1. https://docs.gitlab.com/ee/user/packages/npm_registry/index.html ↩︎

  2. Gitlab user permissions ↩︎

  3. Predefined variables reference ↩︎ ↩︎

Discussion