GitLabプライベートプロジェクトをNPM公開する

# はじめに

この記事は[ユニークビジョン株式会社 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/uniquevision) 12日目の記事です。

社内ライブラリをnpmプライベートパッケージとして公開したのですが、これがとても便利だったので記事にしようと思いました。プライベートなプロジェクトだからNPMに公開できないと思っている方は是非試して欲しいです。

当記事ではGitLabのプライベートプロジェクトをNPMパッケージとして公開する手順、及びGitLab CI/CDを使ったリリースの自動化手順、公開したパッケージのインストール手順を紹介します。

ちなみに同手順の公式ドキュメントは[こちら](https://docs.gitlab.com/ee/user/packages/npm_registry/)になります。

# NPMパッケージを公開するメリット

- ライブラリを導入するプロジェクトから完全に切り離して開発ができる。
- 独自ライブラリをnpmの管理下にできる。
 - ライブラリの導入が簡単になる。
 - ライブラリバージョン管理できる


# プライベートなGitLabプロジェクトをNPMパッケージとして公開

公開までの手順は以下になります。

1. パッケージ名の命名規則
1. パッケージレジストリへの認証設定を`.npmrc`に記述
1. パーソナルアクセストークンの取得
1. パッケージの公開

## パッケージ名の命名規則

パッケージ名は`@scope/package-name`のような形式である必要があります。

- `scope`： GitLabプロジェクトのルート名前空間です。
   例えばプロジェクトが`https://gitlab.example.com/my-org/engineering-group/team-amazing/analytics`場合、ルート名前空間は`my-org`になります。

- `package-name`： 好きなパッケージ名を指定できます。

命名規則に沿った`package.json`は以下のようになります。

```json:package.json
{
  "name": "@scope/package-name",
  "version": "0.1.0",
  ...
}
```

## パッケージレジストリへの認証設定を`.npmrc`に記述

```:.npmrc
@scope:registry=https://gitlab.example.com/api/v4/projects/${GITLAB_PROJECT_ID}/packages/npm/
//gitlab.example.com/api/v4/packages/npm/:_authToken=${GITLAB_ACCESS_TOKEN}
//gitlab.example.com/api/v4/projects/${GITLAB_PROJECT_ID}/packages/npm/:_authToken=${GITLAB_ACCESS_TOKEN}
```

- `scope`： GitLabプロジェクトのルート名前空間に置き換えます。パッケージ名の`scope`と同一です。
- `gitlab.example.com`： ドメイン名に置き換えます。
- `GITLAB_PROJECT_ID`： プロジェクトのホームページにあるプロジェクトIDです。環境変数として指定します。
- `GITLAB_ACCESS_TOKEN`： パーソナルアクセストークンまたはデプロイトークンです。後述する手順でトークンを取得します。環境変数として指定します。


 プロジェクトのホームページにあるプロジェクトIDです。
<your_token> パーソナルアクセストークンまたはデプロイトークンです。
gitlab.example.comドメイン名に置き換えます。

## パーソナルアクセストークンの取得

※ 後述するGitLab CI/CDからリリースする手順では別のトークンを利用するため、ここで作成したトークンはローカルからの実行のみに使います。

1. パーソナルアクセストークンはGitLabのWebページから作成できます。
2. 「設定」→「アクセストークン」からアクセストークン画面を開きます。
3. `名前` `有効期限日(任意)` を入力し、`スコープ`は`api`をチェックします。
   <img width="500px" alt="スクリーンショット 2020-12-11 23.35.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/a1be11af-93a7-b70e-e2c1-9f3d47ee1323.png">

4. 「Create personal access token」をクリックするとトークンが生成されます。
5. 取得したトークンを`GITLAB_ACCESS_TOKEN`環境変数にセットします。

## パッケージの公開

`GITLAB_PROJECT_ID`と`GITLAB_ACCESS_TOKEN`の環境変数を設定し、`npm publish`コマンドを実行します。

以下コマンド例

```
$ GITLAB_PROJECT_ID=12345678 GITLAB_ACCESS_TOKEN=_nk4przrfWPLMCppDW9s npm publish
```
※ このコードの`GITLAB_ACCESS_TOKEN`は失効済みです。

### `403 Forbidden`エラーが発生した場合
`npm publish`する際はパッケージ名とバージョンがユニークである必要があります。すでに一度公開していた場合、バージョン番号が公開済みのものと重複していると思われますので`package.json`の`version`を変更してリトライしましょう。

# GitLab CI/CDでリリースを更に簡単に

## `.gitlab-ci.yml`ファイルの作成

以下のような`.gitlab-ci.yml`ファイルサンプルコードを用意しました。

```yaml:.gitlab-ci.yml
stages:
  - publish

variables:
  GITLAB_PROJECT_ID: '$CI_PROJECT_ID'
  GITLAB_ACCESS_TOKEN: '$CI_JOB_TOKEN'

publish:
  image: node:14
  stage: publish
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
      when: on_success
    - when: never
  script:
    - npm publish
```

`$CI_PROJECT_ID`： CI/CDで使えるプロジェクトIDの環境変数です。
`$CI_JOB_TOKEN`： CI/CDで使えるジョブトークンの環境変数です。パッケージレジストリの認証にはこのトークンも使用できます。

このサンプルコードでは`rules`でWebページから実行されたときだけ公開されるようになっています。
必要ならテストやビルドも含めることもできます。詳細はGitLab CI/CDで調べてみてください。

## リリース手順

前述の`.gitlab-ci.yml`ファイルの場合の手順を載せています。

1. `package.json`の`version`を変更してプッシュします。
2. GitLab Webページ CI/CD画面の「パイプラインを実行」からリリースしたいブランチを選んで実行します。

# 公開したパッケージのインストール手順

公開したパッケージのインストール手順は以下になります。

1. パッケージレジストリへの認証設定を`.npmrc`に記述
1. パーソナルアクセストークンの取得
1. パッケージをインストール

## パッケージレジストリへの認証設定を`.npmrc`に記述

インストール手順としては以下のようなコマンドを用意しましょう。

```
$ echo "@scope:registry=https://gitlab.example.com/api/v4/projects/<GITLAB_PROJECT_ID>/packages/npm/" >> .npmrc
$ echo "//gitlab.example.com/api/v4/packages/npm/:_authToken=${GITLAB_ACCESS_TOKEN}" >> .npmrc
$ echo "//gitlab.example.com/api/v4/projects/<GITLAB_PROJECT_ID>/packages/npm/:_authToken=${GITLAB_ACCESS_TOKEN}" >> .npmrc
```

- `scope`： GitLabプロジェクトのルート名前空間に置き換えます。パッケージ名の`scope`と同一です。
- `gitlab.example.com`： ドメイン名に置き換えます。
- `<GITLAB_PROJECT_ID>`： プロジェクトのホームページにあるプロジェクトIDに置き換えます。
- `GITLAB_ACCESS_TOKEN`： パーソナルアクセストークンまたはデプロイトークンです。後述する手順でトークンを取得します。環境変数として指定してもらいます。


## パーソナルアクセストークンの取得

インストール時に必要なトークンを取得してもらいます。
手順は公開時のトークン取得とほぼ同じですが、要求されるスコープが`read_api`でも良くなります。

1. パーソナルアクセストークンはGitLabのWebページから作成できます。
2. 「設定」→「アクセストークン」からアクセストークン画面を開きます。
3. `名前` `有効期限日(任意)` を入力し、`スコープ`は`read_api`（`api`でも良い）をチェックします。
   <img width="500px" alt="スクリーンショット 2020-12-12 2.33.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/45e9be21-d821-e8c7-d450-e59334a63c64.png">

4. 「Create personal access token」をクリックするとトークンが生成されます。
5. 取得したトークンを`GITLAB_ACCESS_TOKEN`環境変数にセットします。

## パッケージをインストール

`GITLAB_ACCESS_TOKEN`環境変数にトークンをセットして`npm install`を実行します。

```
$ GITLAB_ACCESS_TOKEN=_nk4przrfWPLMCppDW9s npm i @scope/package-name
```

トークンの持ち方はもう少し考えたほうが良いですが、これでインストールできます。

# まとめ

以上でGitLabプライベートプロジェクトのNPM公開手順になります。
これらの環境を整えてからライブラリのリリースとインストールがとても簡単になりました。
特にCIが強力で毎日リリースしても全然苦では無いのでとても便利になります。
社内で共有しているライブラリがあればぜひ活用してください。