【第二世代管理パッケージ(2GP)】 バージョニングとアップグレードの注意点

第二世代管理パッケージ(以下、2GP)のまとめシリーズ第 2 弾となる今回は、“バージョンニング” と “アップグレードの注意点” についてまとめてみます。

2GP では、バージョニングについても第一世代管理パッケージ(以下、1GP)から多少変更されており、主な点としては、ベータバージョンとリリースバージョンの関係が変更されていること、バージョンブランチが可能となったことが挙げられます。

今回の記事では、まず 1GP におけるバージョニングについておさらいし、その上で 2GP で変更があった点について確認していきます。その後、具体的にバージョンを進めていく手順と、アップグレードの際に気をつけるべきルールの詳細について解説します。

過去の連載記事は [連載]第二世代管理パッケージ(2GP)をご覧ください。

2022.7.1追記

Spring ’22で「新しいキーワードを使用した上位パッケージの指定」がリリースされ、ancestorIdまたはancestorVersionに「HIGHEST」キーワードを指定することによって、線形にバージョンを進めて行くに場合には、新しいバージョン作成する際に明示的に上位バージョンを指定する必要がなくなりました。

AppExchange向けの管理パッケージの場合には、線形にバージョンを管理することがベストプラクティスなため、現時点で以下の記事は参考程度の内容になります。AppExchange開発で2GPを使用する際にバージョニングについててっとり速く知りたい方は「ベストプラクティス」を参照ください。

2GP と 1GP のバージョニングの違い

2GP におけるバージョンと、その進め方について、1GP と比較しつつ解説します。

1GP のおさらい

まずは、1GP のバージョン番号の形式のおさらいから。

1GP のバージョンは「2.1.3」のように 3 つのパートに分けて管理され、左からメジャーバージョン、マイナーバージョン、パッチバージョンを表されます。

参照: パッケージバージョンについて

1GP では、パッケージ開発組織でパッケージをアップロードすると、現在のバージョン番号を元に自動で採番されます。このとき自動でバージョンが上がるのはマイナーバージョンです。

以下の例は、現在のバージョンが「1.32」のときにアップロードを開始した場合「1.33」が自動入力されます。

一方で、大きな機能追加があった場合など「メジャーバージョンを上げたいとき」は、手動で明示的に入力する必要があります。

とはいえ、基本的に普段はマイナーバージョンのインクリメントにまかせているといった運用をされているパッケージが多いのではと思います。若干融通は利かないですが、「考える部分が少なく、設計は楽」な仕組みとも言えます。

あとは、パッチバージョンですが、パッチバージョンはパッチ開発専用のパッチ組織を作成して、そこで開発する必要がある特別なバージョンで、パッチの特徴としては以下の制限があります。

・ パッケージコンポーネントは追加できません。

・ 既存のパッケージコンポーネントは削除できません。

・ API およびダイナミック Apex アクセスコントロールをそのパッケージ用に変更できません。

・ Apex コードは廃止できません。

・ extends などの新しい Apex クラスリレーションは追加できません。

・ virtual や global などの Apex アクセス修飾子は追加できません。

・ 新しい Web サービスは追加できません。

・ 機能の連動関係は追加できません。

パッチの作成およびアップロード

前回の記事でも振れましたが、弊社ではパッチバージョンの制限の厳しさと、パッチ組織の運用の面倒さから、パッチバージョンを利用した運用はこれまでしていませんでした。

2GP のバージョンニング

2GP のバージョニングの考え方は、基本的には 1GP と同じです。

1GP との違いは、2GP では新たに「4 桁目のビルドバージョンが追加された」ことです。

ビルドバージョンは、パッケージバージョンを作成(ビルド)するごとにインクリメントさせるか、明示的に指定することができる番号で、1GP のベータバージョンに近いものです。

ビルドバージョンのいずれかを選択し、リリースバージョンとして昇格することになります。

参考: パッケージバージョンの生成

2GP のバージョンの進め方

2GP ではメジャー・マイナーバージョンを作成する際、明示的に前のバージョン(祖先)を指定する必要があります。(実際は指定しなくても作成できますが、アップグレードはできない “はぐれバージョン” になってしまいます。)

前のバージョンを指定するには、新規パッケージバージョンを作成する際に祖先(AncestorId または AncestorVersion)を指定します。

Salesforce のドキュメントに合わせると上記の図になりますが、以下のように直線的にバージョンが続いていくイメージになります。

参照: パッケージの上位

2GP ではバージョンをブランチできる

2GP で導入されたバージョンの新機能として、以下のようにバージョンをブランチすることができます。

ただし、実質的にはブランチは使用できませんので、注意が必要です。詳しくは「ブランチしたバージョンのアップグレード」で解説しています。

参考: 第二世代管理パッケージでのブランチの使用

バージョンの作成手順

前回の記事の「2GP パッケージの作成手順」でも SFDX コマンドを使ってパッケージ バージョンを作成する手順について解説しましたが、ここでは、いわゆるバージョンアップ=既存のバージョンの次のバージョンを作成する手順について確認します。

パッケージ バージョンを作成しリリース済みとする手順は以下ようにコマンドを実行しますが、2 番目以降のパッケージ バージョンを作成するには Ancestor(上位パッケージ)を指定して force:package:version:create を実行する必要があります。

$ sfdx force:package:version:create --package "2GP App" --wait 10 -c -x
$ sfdx force:package:version:promote --package "2GP App@0.1.0-1"

Ancestor の指定は、package:version:create を実行する前に sfdx-package.json の AncestorId または AncestorVersion を直接書き換えて保存します。(2021 年 10 月現在、残念ながら Ancestor を指定するコマンドオプションはありません。)

例えば、上記「2GP のバージョンの進め方」の図の例で「2.0.0.1」を作成するためには、sfdx-project.json の AncestorId にパッケージ バージョンの Id「04t5h000000XXXXAAE」を指定します。

{
    "packageDirectories": [
        {
            "path": "sfdx-src",
            "default": true,
            "package": "2GP App",
            "versionName": "ver 2.0",
            "versionNumber": "2.0.0.NEXT",
            "ancestorId": "04t5h000000XXXXAAE"
        }
    ],

ancestorVersionを利用する場合は以下のようにバージョン番号を指定します。

{
    "packageDirectories": [
        {
            "path": "sfdx-src",
            "default": true,
            "package": "2GP App",
            "versionName": "ver 2.0",
            "versionNumber": "2.0.0.NEXT",
            "ancestorVersion": "1.1.0-1"
        }
    ],

パッチバージョンを作成する際も AncestorId の指定が必須です。次で説明しますが、パッチバージョン間はバージョンが上がる方向、つまりアップグレードであれば Ancestor のツリーをまたがってもインストール可能なので、起点となるマイナーバージョンを Ancestor として指定しておけば OK のようです。

アップグレード互換なバージョンと注意点

ここから、実際に登録者組織にパッケージ バージョンをインストールし、検証してみてわかった「アップグレード可能なパターン」と「不可能なパターン」について解説します。

パッチ間のアップグレード

パッチバージョンは、元となるマイナーバージョンが共通でさえすれば、Ancestor を辿らなくても、バージョンが上がる方向であればアップグレード可能です。

検証した結果について解説します。

以下のパッケージ バージョン(リリース済み)が作成されている状態から確認します。

$ sfdx force:package:version:displayancestry -p "2GP App"
─┬ 0.1.0.1
 ├─┬ 0.1.1.1
 │ └─┬ 0.1.2.1
 │   └─┬ 0.1.4.1
 │     └── 0.1.6.1
 ├── 0.1.5.1
 └─┬ 1.0.0.1
   └── 1.1.0.1

「 0.1.4.1」がインストールされている組織でに「 0.1.5.1」をインストールできるか確認してみます。

先に、登録者組織にインストールされている現在のバージョンを「package:installed:list」コマンドで確認しておきます。

$ sfdx force:package:installed:list -u admin@subscriber.com
=== Installed Package Versions [5]
ID                  Package ID          Package Name                 Namespace      Package Version ID  Version Name  Version
──────────────────  ──────────────────  ───────────────────────────  ─────────────  ──────────────────  ────────────  ────────
0A37F000000WNBXSA4  0335h000000Y4AsAAK  2GP App    

「0.1.4.1」から「 0.1.5.1」へ更新されるようにパッケージをインストールしてみます。

$ sfdx force:package:install --package "2GP App@0.1.4-1" -u admin@subscriber.com -w 10
Waiting for the package install request to complete. Status = IN_PROGRESS
Successfully installed package [04t5h000000YWo5AAG]

$ sfdx force:package:installed:list -u admin@subscriber.com
=== Installed Package Versions [5]
ID                  Package ID          Package Name                 Namespace      Package Version ID  Version Name  Version
──────────────────  ──────────────────  ───────────────────────────  ─────────────  ──────────────────  ────────────  ────────
0A37F000000WNBXSA4  0335h000000Y4AsAAK  2GP App    

パッチは Ancestor に関係なくアップグレードすることが確認できました。

このバージョンツリーの例では、同様に「0.1.5.1」から別のブランチとなる「0.1.6.1」へのアップグレードはパッチバージョン間ですので可能です。

ところで、パッチであってもダウングレードはこれまで通りできません。「 0.1.2.1」に戻そうとすると以下のエラーが出力されます。

$ sfdx force:package:install --package "2GP App@0.1.2-1" -u admin@subscriber.com -w  10
Waiting for the package install request to complete. Status = IN_PROGRESS
ERROR:  Encountered errors installing the package!,Installation errors: 
1) インストールできません。, Details: このパッケージより新しいバージョンが現在インストール済みです。
ERROR running force:package:install:  Installation errors: 
1) インストールできません。, Details: このパッケージより新しいバージョンが現在インストール済みです。

パッチから次のメジャー・マイナーバージョンへのアップグレード

パッチバージョンから次のメジャー・マイナーバージョンへのアップグレードは、派生したメジャー・マイナーバージョンの、どのパッチバージョンからでもアップグレード可能です。


上の図の場合は、「1.1.0.1」の Ancestor である「1.0.0.1」のパッチは、いずれからでも「1.1.0.1」にアップグレードできます。

例えば、以下のようなバージョンがあるとします。

$ sfdx force:package:version:displayancestry -p "2GP App"
─┬ 0.1.0.1
 ├─┬ 0.1.1.1
 │ └─┬ 0.1.2.1
 │   └─┬ 0.1.4.1
 │     └── 0.1.6.1
 ├── 0.1.5.1
 └─┬ 1.0.0.1
   └── 1.1.0.1

「0.1.4.1」がインストールされている組織で 「 1.0.0.1」にアップグレード可能なことを確認してみます。

登録者組織のにインストールされている現在のバージョンを「package:installed:list」コマンドで確認します。

$ sfdx force:package:installed:list -u admin@subscriber.com
=== Installed Package Versions [5]
ID Package ID Package Name Namespace Package Version ID Version Name Version
────────────────── ────────────────── ─────────────────────────── ───────────── ────────────────── ──────────── ────────
0A37F000000WNBXSA4 0335h000000Y4AsAAK 2GP App hrendoh2gp 04t5h000000YWo0AAG ver 0.1 0.1.4.1

ここに、「1.0.0.1」をインストールしてみます。インストールは成功しアップグレードされたことが確認できます。

$ sfdx force:package:install --package "2GP App@1.0.0-1" -u admin@subscriber.com -w  10
Waiting for the package install request to complete. Status = IN_PROGRESS
Successfully installed package [04t5h000000YWo5AAG]

$ sfdx force:package:installed:list -u admin@subscriber.com
=== Installed Package Versions [5]
ID Package ID Package Name Namespace Package Version ID Version Name Version
────────────────── ────────────────── ─────────────────────────── ───────────── ────────────────── ──────────── ────────
0A37F000000WNBXSA4 0335h000000Y4AsAAK 2GP App hrendoh2gp 04t5h000000YWo5AAG ver 1.0 1.0.0.1

メジャー・マイナーバージョンのアップグレード

メジャー・マイナーバージョンのアップグレードは 1GP とほぼ同じで、Ancestor の子孫方向にアップグレードが可能です。ダウングレードはできません。

ところで、「これであれば、そもそも Ancestor は不要なのでは?」と疑問が浮かびます。しかし、2GP の仕組み上、直線的なバージョニングであっても Ancestor が必須となります。

以下のようなバージョンツリーの場合に Ancesor を指定していない「1.2.0.1」は一見、『「1.0.0.1」または「1.1.0.1」からのアップグレード』または『「2.0.0.1」および「2.1.0.1」へのアップグレード』が可能なように見えますが、Ancestor を指定していないため実際はどちらもエラーとなります。

こちらも検証結果を解説します。

以下のバージョンツリーでは「0.2.0.1」は Ancestor を持たない “はぐれバージョン” です。

$ sfdx force:package:version:displayancestry -p "2GP App"
─┬ 0.1.0.1
 ├─┬ 0.1.1.1
 │ └─┬ 0.1.2.1
 │   └── 0.1.4.1
 ├── 0.1.5.1
 └─┬ 1.0.0.1
    └── 1.1.0.1
── 0.2.0.1

例えば、以下は「0.1.5.1」がインストールされている登録者組織に「0.2.0.1」をインストールした結果ですが、たしかにエラーとなり、アップグレードはできませんでした。

$ sfdx force:package:install --package "2GP App@0.2.0-1" -u admin@subscriber.com -w  10
Waiting for the package install request to complete. Status = IN_PROGRESS
ERROR: Encountered errors installing the package!,Installation errors:
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンにはこのバージョンと共通する上位バージョンがありません。
ERROR running force:package:install: Installation errors:
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンにはこのバージョンと共通する上位バージョンがありません。

ブランチしたバージョンのアップグレード

最後に、メジャー・マイナーバージョンをブランチしたケースですが、ブランチしてしまったバージョンは Ancestor を辿れないため “はぐれバージョン” と同様にアップグレードはエラーとなります。

以下のバージョンツリーの場合、例えば「1.0.0.1」がインストールされている組織に「1.2.0.1」をインストールすることはできません。

$ sfdx force:package:version:displayancestry -p "2GP App"
─┬ 0.1.0.1
  ├─┬ 0.1.1.1
  │  └─┬ 0.1.2.1
  │      └─┬ 0.1.4.1
  │          └── 0.1.6.1
  ├── 0.1.5.1
  ├─┬ 1.0.0.1
  │  └── 1.1.0.1
  └── 1.2.0.1

「1.0.0.1」がインストールされている組織に「1.2.0.1」をインストールしてみます。

$ sfdx force:package:installed:list -u admin@subscriber.com
ID Package ID Package Name Namespace Package Version ID Version Name Version
────────────────── ────────────────── ─────────────────────────── ───────────── ────────────────── ──────────── ────────
0A37F000000WNyySAG 0335h000000Y4AsAAK 2GP App hrendoh2gp 04t5h000000YWo5AAG ver 1.0 1.0.0.1

以下の通りエラーとなることが確認できました。

$ sfdx force:package:install --package "2GP App@1.2.0-1" -u admin@subscriber.com -w  10
Waiting for the package install request to complete. Status = IN_PROGRESS
ERROR:  Encountered errors installing the package!,Installation errors: 
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンにはこのバージョンと共通する上位バージョンがありません。
ERROR running force:package:install:  Installation errors: 
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンにはこのバージョンと共通する上位バージョンがありません。

ベストプラクティス

すべての登録者組織に同じバージョンを利用してもらう製品の場合は、基本的に Ancestor はツリー状(ブランチ)ではなく 1 本にする必要があります。

つまり、バージョニングについては 1GP と同様の運用にする必要があります。

1GP 同様のバージョニングで問題ないのであれば、パッケージ バージョンを作成するスクリプトで sfdx-project.json の AncestorId に既存のリリースバージョンの最新を自動でセットするようにすれば良さそうです。CI でバージョンを作成するのであればこのスクリプトを登録します。

スクリプトの例などについては、社内のプロジェクトが進んで来て運用が固まった時点でまた TIPS として紹介できればと思います。

2GPで線形にバージョンを進めていく際には、ancestorIdまたはancestorVersionに「HIGHEST」を指定しておけばOKです。「HIGHEST」キーワードを指定しておけば、リリース済みバージョンのうち最新のバージョンが上位バージョンとして自動で選択されます。

{
    "path": "force-app",
    "package": "2GP App",
    "versionName": "ver 0.1",
    "versionNumber": "0.1.0.NEXT",
    "ancestorVersion": "HIGHEST",
    "default": false,
    "apexTestAccess": {
        "permissionSets": [
            "user",
            "admin"
        ]
    }
},

「HIGHTEST」を指定している場合は、作成するバージョンにパッチバージョン以上のバージョン番号を指定する必要があります。以下、バージョンを指定しない場合のメッセージ

ERROR running force:package:version:create:  パッケージバージョン番号が無効です。新しいパッチバージョンを作成する場合は、パッチバージョン番号を 1 以上にする必要があります。パッチではない新しいパッケージバージョンを作成する場合は、パッチ番号を 0 にする必要があります。パッケージバージョン番号は major.minor.patch.build の形式で設定してください。

そのため、バージョンを作成するスクリプトでは、デフォルトは作成済みのリリースバージョンからマイナーバージョンをインクリメントして「-n (–versionnumber)オプション」にバージョン番号を渡せるようにしておき、必要に応じてメジャー、パッチバージョンを作成できるようにしておくのが良さそうです。

以下のコマンド例の–versionnumberの「0.2.0.1」を変数として渡すようにします。

$ sfdx force:package:version:create --package  "2GP App"  --versionnumber=0.2.0.1 --wait 10 -x -c

まとめ


今回は 2GP 大きく変更となったバージョニングとその進め方について解説しました。まとめとしては、以下の 2 つになるかと思います。

  • AppExchange 向けパッケージのバージョニングについては、結局は 1GP 同じ運用とする。
  • パッチ組織の運用がなくなり、パッチの活用は楽になりそう。

次回は、転送アップグレードについて解説します。こちらも、2GP ではどうすればよいのか「Salesforce DX 開発者ガイド」を読んでも腑に落とすことが難しいテーマですので、ぜひご期待ください。

過去の連載記事は [連載]第二世代管理パッケージ(2GP)をご覧ください。