Google Cloud Artifact RegistryでUnity Package Managerのプライベートレジストリを作成する

「Google Cloud + Gaming Advent Calendar 2020」の4日目を担当させていただくことになりました、株式会社グレンジの村田です。

# Artifact Registry

Google CloudのArtifact Registryは、11月17日（現地時間）に一般提供を開始した新しいサービスです。Google Container Registryの進化形でもあり、コンテナイメージだけでなく言語パッケージなども管理できます。

Artifact Registryはnpmをサポートしてます。UnityのPackage Managerはnpmをベースにして動作しており、社内でUnity Package Managerのプライベートレジストリのニーズがあったため、Artifact Registryのnpmが利用できないか試しました。結果、設定方法を少し注意すれば使えることがわかったので、本記事ではUnityから利用するための手順を説明しています。

※執筆時点ではnpmがアルファ版のため、アンケートに答えて申請しないと使えません。申請してから約5日間ほどで使えるようになりました。

# npmリポジトリの作成（npmレジストリ）

まずはnpmのリポジトリを作成します。

![スクリーンショット 2020-11-29 23.52.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/b53ad49b-de8f-ea5c-ec5a-ff44b39bcfe4.png)

リポジトリの名前は「advent-calendar」とします。

![スクリーンショット 2020-11-28 16.44.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/d17ee12f-209c-0e6f-a27a-7e8481efe6dd.png)

リポジトリ「advent-calendar」が作成されました。

![スクリーンショット 2020-11-30 0.13.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/ea94987e-8c26-16bc-f5e4-5c0c545742c2.png)


advent-calendarをクリックして、リポジトリの中身を確認してみます。作成直後なのでパッケージは1つもありません。とりあえずリポジトリは作成完了です。

![スクリーンショット 2020-11-28 16.49.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/586c0657-98d9-2ac8-7e20-ab5311b4f304.png)

# リポジトリにログインする

リポジトリにパッケージを追加すること、またUnityでそのパッケージを取得するには、リポジトリにログインする必要があります。以下が一連の手順です。

1. gcloudコマンドの初期化でGoogleアカウント認証
1. .npmrcにリポジトリ設定を追加
1. npxコマンドでnpmリポジトリにログイン（npm publishでパッケージの追加ができるようになる）
1. Unityの設定ファイルにトークンをセット（Unityからパッケージを取得できるようになる）

Artifact Registryのコンソールの「設定の手順」にnpxコマンドまでの手順は書いてありますが、「npmの構成」にある「_password」だと、Unityの設定ファイルに記載するトークンが取れないので、少し変更を加えて.npmrcに設定する必要があります（後述）。

## gcloud の初期化

「Google Cloud SDK のインストール」に従い、gcloud initを実行してください。
https://cloud.google.com/sdk/docs/install?hl=JA#top_of_page

続いて、次のコマンドでも認証しておきます。

```
gcloud auth application-default login
```


## .npmrcにリポジトリ設定を追加

.npmrcはどのディレクトリで作成しても構いません。本記事ではホームディレクトリとします。すでに.npmrcが存在していれば、追記します。

先述の「npmの構成」を参考にしつつ、次の3行のような構成にしてください。

```.npmrc
@adventcalendar:registry=https://asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/
//asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/:_authToken=""
//asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/:always-auth=true
```

「_password」は「_authToken」に変更しており、「username」と「email」の行は削除しています。「<span>@</span>SCOPE」は「<span>@</span>adventcalendar」にしました。
「asia-northeast1-npm」や「YOUR-PROJECT-NAME」は指定したリージョンやお使いのGCPプロジェクト名で変わります。

※この3行の形式はコンソールに表示される「npmの構成」とは別に、次のドキュメントに記載がありました
https://cloud.google.com/artifact-registry/docs/nodejs/quickstart#config

## npxコマンドでリポジトリにログインする

ホームディレクトリに.npmrcがある場合、次のコマンドを実行します。

```
npx google-artifactregistry-auth ~/.npmrc
```

これでnpm publishでパッケージ登録ができる状態になります。

その後、.npmrcファイルを確認すると、_authTokenに値がセットされているはずです（YOUR_TOKENの部分）。この値をメモしておいてください。

```.npmrc
@adventcalendar:registry=https://asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/
//asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/:_authToken="YOUR_TOKEN"
//asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/:always-auth=true
```

※この「_authToken」が必要なため、先ほどの手順で「_password」から「_authToken」に変更しました。

## Unityの設定ファイル.upmconfig.tomlを作成

ホームディレクトリにUnityの設定ファイル「.upmconfig.toml」を作成します。設定例です。

```.upmconfig.toml
[npmAuth."https://asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/"]
token = "YOUR_TOKEN"
email = "not.valid@email.com"
```

npmAuthの後ろは.npmrcのregistryのURLです。YOUR_TOKENは先ほどメモした値をセットしてください。emailはnot.valid<span>@</span>email.comで良いです。これでUnityからもリポジトリにアクセスできるようになりました。

※.upmconfig.tomlについて
https://docs.unity3d.com/Manual/upm-config.html
https://docs.unity3d.com/Manual/upm-config-scoped.html

# リポジトリにパッケージを追加する

パッケージとして登録するUnityプロジェクトに、package.jsonを作成します。作成例。

```package.json
{
  "name": "jp.grenge.sample",
  "displayName": "Advent Calendar Sample",
  "version": "1.0.0",
  "unity": "2020.1",
  "description": "AdventCalendar記事用のサンプルパッケージです。",
  "author": {
    "name": "Grenge"
  }
}
```

ファイル構成例。

```
├── Runtime
│   ├── Prototype.Sample.asmdef
│   ├── Prototype.Sample.asmdef.meta
│   ├── Sample.cs
│   └── Sample.cs.meta
├── Runtime.meta
├── package.json

```

npm publishでリポジトリにパッケージを追加します。--registryオプションで明示的にリポジトリURLを指定します。

```
npm publish --registry https://asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/
```

ハマった点ですが、パッケージ名を「<span>@</span>adventcalendar/sample」とすれば、npm publishのみで--registryオプション無しでも追加可能です。しかし、Unityでは「<span>@</span>adventcalendar」で始まるパッケージ名が、指定のリポジトリURLに変更するという動作が機能してくれませんでした。

今回はパッケージ名を「jp.grenge.sample」として、Unityにて「jp.grenge」で始まるパッケージ名が指定のリポジトリURLにアクセスされることを確認しています（後述）。パッケージ名がスラッシュ区切りか（<span>@</span>adventcalendar/sample）、ピリオド区切りか（jp.grenge.sample）でUnityの処理が異なっていそうです。

# Unityからパッケージを取得する

Packages/manifest.jsonの「dependencies」に「jp.grenge.sample」を追加し、「scopedRegistries」にリポジトリの設定を追加します。「scopes」に「jp.grenge」を指定することにより、パッケージ名「jp.grenge」で始まるパッケージは指定したリポジトリURLから取得するようになります。

```Packages/manifest.json
{
  "dependencies": {
    "com.unity.collab-proxy": "1.3.9",
　　 (省略)
    "jp.grenge.sample": "1.0.0"
  },
  "scopedRegistries": [
    {
      "name": "advent-calendar",
      "url": "https://asia-northeast1-npm.pkg.dev/YOUR-PROJECT-NAME/advent-calendar/",
      "scopes": [
        "jp.grenge"
      ]
    }
  ]
}
```

UnityのPackage Managerで確認。無事取得できました（Unity 2020.1.13f）

![スクリーンショット 2020-11-29 21.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/6f5e8fa5-82c9-4f4c-a706-e022099f52aa.png)

# リポジトリにアクセスするユーザーの管理

IAMでリポジトリにアクセスするユーザーを管理できます。任意のGoogleアカウントを、ロールを選択して追加するだけです。

![スクリーンショット 2020-11-30 0.35.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18212/fc470f8e-2bce-3d1f-29a4-21a4a0bb0e4f.png)

# おわりに

verdaccioを使い、グローバルIPでアクセス制限を設けてプライベートレジストリを構築することを検討していたのですが、Artifact Registryの登場により選択肢が増えました。IAMでユーザーの権限管理できるのも良いです。
しばらくはArtifact Registryで運用して、使い勝手を把握しようと思います。

※参考にさせて頂いた記事
https://monry.hatenablog.com/entry/2020/03/07/015041