【Unity】GCP Artifact RegistryでPrivateなUPMレジストリを構築する
ゲームエンジンUnityの内製パッケージを社内だけ等、限定配布を行いたい場合、Verdaccioを使う事例が多いと思います。柔軟な設定が出来る(あと他に選択肢があまりない)一方、こうしたサーバーアプリケーションのホスティングは、クライアントエンジニアにはハードルが高いと感じる事も多いでしょう。
そこで今回はGoogleCloudPlatformのArtifactRegistryを使ってPrivateなUPMレジストリを構築し、認証付きでパッケージの配布を行う手順をまとめました。比較的簡単に、かつマネージドサービスなので手間をかけずに構築できます。
環境構築
-
Node.js
- 現在LTSのバージョンならどれでも大丈夫な筈です(本記事は24.6.0を使いました)
- 本記事では
npm
npx
を使う為です
-
gcloud CLI
- 課金設定を行ったGCPプロジェクトは作成しておいて下さい
リポジトリ作成
まずはリポジトリ作成を行います。
$ gcloud artifacts repositories create <リポジトリ名(好きにつけてOK)> --repository-format=npm --location=<ロケーション名> --description="Unity Packages"
続いてnpmの設定を書き出すコマンドがあります。
$ gcloud artifacts print-settings npm --project=<プロジェクト名> --repository=<リポジトリ名> --location=<ロケーション名>
標準出力で下記のような設定が出てきます。
# Insert the following snippet into your project .npmrc
registry=https://<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/
//<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/:always-auth=true
コメントには.npmrcに書き出せ
と書かれていますが、あえてそれ以外のファイル名でテキストファイルを作成して下さい[1](ここではauth.txt
とします)
パッケージ公開(Publish)用の認証設定
次にパッケージ公開を行うための認証用アクセストークンを取得します。
$ npx google-artifactregistry-auth --repo-config=./auth.txt --credential-config=./auth.txt
このコマンドを実行すると、先ほど作成したauth.txt
に1行追記されます。
//<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/:_authToken=<アクセストークン>
なおこのアクセストークンの有効期限は60分ですので作業中断時はご注意下さい。期限が切れた場合は再度npx google-artifactregistry-auth
を実行すれば、アクセストークンだけが更新されます。
パッケージの公開
公開したいUnityパッケージのpackage.jsonと同じディレクトリにauth.txt
をコピーし、.npmrcという名前にリネームします。そして同ディレクトリ内で以下を実行します。
$ npm publish
エラーが出なければ公開完了です。この時点では認証情報が無いので、まだUnityから参照する事は出来ません。
Unityから参照するための認証設定
UnityからはGCPのサービスアカウントの認証情報を使ってパッケージを参照しましょう。[2]
$ gcloud iam service-accounts create <サービス名(好きにつけてOK)> --display-name="Unity Package Viewer Service Account" --project=<プロジェクト名>
サービスアカウントが出来たら、サービスアカウントにリポジトリの参照ロールを付けます。
$ gcloud artifacts repositories add-iam-policy-binding <リポジトリ名> --location=<ロケーション名> --member="serviceAccount:<サービス名>@<プロジェクト名>.iam.gserviceaccount.com" --role="roles/artifactregistry.reader"
サービスアカウントのJSONキーを取得します。
$ gcloud iam service-accounts keys create ./key.json --iam-account=<サービス名>@<プロジェクト名>.iam.gserviceaccount.com
パッケージ参照用のアクセスキーの取得
ここから少しややこしいです。設定書き出しコマンドでサービスアカウントのJSONキーを読み込ませます。
$ gcloud artifacts print-settings npm --project=<プロジェクト名> --repository=<リポジトリ名> --location=<ロケーション名> --json-key=./key.json
次の出力が得られます。
# Insert the following snippet into your project .npmrc
registry=https://<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/
//<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/:always-auth=true
# Insert the following snippet into your user .npmrc
//asia-northeast1-npm.pkg.dev/studio-app-utility/private-package-sample/:_password="<base64のコード>"
//asia-northeast1-npm.pkg.dev/studio-app-utility/private-package-sample/:username=_json_key_base64
//asia-northeast1-npm.pkg.dev/studio-app-utility/private-package-sample/:email=not.valid@email.com
ここで得られた<base64のコード>をデコードし、下記の様な文字列をつくります。
_json_key_base64:<デコードしたコード>
そしてこの文字列を再度base64にエンコードしたものがアクセスキーとなります。[3]
UnityからPackageを参照する
ユーザーディレクトリ以下に.upmconfig.toml
を作成し、以下のフォーマットで書き込みます。
[npmAuth."https://<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/"]
_auth = "<アクセスキー>"
alwaysAuth = true
続いて参照したいUnityプロジェクトのPackages/manifest.json
に書き込みましょう。今回入れたいパッケージはcom.example.sample-package:1.0.0
とします。
{
"dependencies": {
"com.example.sample-package": "1.0.0"
},
"scopedRegistries": [
{
"name": "Private Registry",
"url": "https://<ロケーション名>-npm.pkg.dev/<プロジェクト名>/<リポジトリ名>/",
"scopes": [
"com.example"
]
}
]
}
これでUnityがプロジェクトを開いていれば、指定したパッケージが依存関係も解決してインポートされます。
作業手順は以上になります。
npm search
は対応していない
余談1:パブリックなOpenUPMなどのレジストリではnpm search
に対応している為、ScopedRegistry対象に存在するPackageの一覧がUPM上で確認することが出来ますが、今回作成したPrivateRegistryはそれに対応していない為、PackageManagerのウィンドウ上から一覧の形で選んでインストール、といった事は出来ません(Package名を知らないとダメという事。尤も用途的に必要になる事はあまりないでしょう)
余談2:npmのScopedレジストリについて
npmについて知識があればScopedレジストリでない事を不思議に思うかもしれませんが、UPMでは@
付きのパッケージ名が読み込めない為にこのような構成になっています
Discussion