Salesforce 2nd generation package(2GP) 新キーワード HIGHEST と NONEを試す

こんにちは、CLBです。
プライベートがひと段落したので久しぶりに記事を書きました。
今回のお題は Salesforce 2nd generation package(2GP) で新たに追加された
ancestor version の新キーワード HIGEST と NONE についてです。

# 結論
- 2GP で ancestorVersion を手動で設定している人は HIGEST へ移行すると幸せになれる。
- 既に ancestorVersion がある場合、 NONE を設定することはできない。
- ancestorVersion が最新のパッケージバージョンを指定しない場合、パッケージ作成時にエラーになるようになった。

# 難しいパラメータ、ancestorVersion
これまでの 2GP ではリリースの度に ancestorVersion(上位パッケージ) を設定する必要がありました。
ancestorVersionとは現在のパッケージがどのバージョンからアップグレードできるかを示すパラメータで、
大体は一つ前のバージョンを指定するパラメータです。

例えば、

```sfdx-project.json
{
  "packageDirectories": [
      {
          "path": "force-app",
          "default": true,
          "package": "Sample",
          "versionName": "ver 0.2",
          "ancestorVersion" : "0.1.0",
          "versionNumber": "0.2.0.NEXT"
      }
  ],
  "name": "sfdx",
  "namespace": "NAME_SPACE",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "54.0",
  "packageAliases": {
      "Sample": "ID",
      "Sample@0.1.0-1": "ID",
      "Sample@0.2.0-1": "ID"
  }
}
```
という `sfdx-project.json` があったとします。
この場合、作成するバージョンは 0.2.0 で 0.1.0 からアップグレード可能であること示しています。
問題ありませんね。

しかし次に 0.3.0 を作成する際に、ancestorVersion を 0.1.0 にしたまま作成するとどうなるでしょうか？
**答えは簡単、0.2.0 → 0.3.0 のアップグレードができなくなってしまうのです！**

# HIGEST と NONE キーワードの誕生
この問題を鑑みて、 [Salesforce Spring'22](https://help.salesforce.com/s/articleView?id=release-notes.rn_packaging_ancestor_enhancements.htm&type=5&release=236) で HIGEST と NONE のキーワード指定が追加されました。
これによりancestorVersionが自動的にリリース済みの最上位バージョンが選択されるため、
アップグレードできなくなる問題を回避することが可能です。

# キーワードの乗り換えを試す
それではこれらのキーワードを使って、業務を効率化することを試してみます。
前提として以下のようなシナリオを考えます。

- A社ではこれまで ancestorVersion を手動で更新してパッケージを作成していた。
- 今回、HIGEST と NONE キーワードへ乗り換えを検討したい。

そのため、パッケージを以下のような順番で作成します。

1. `Sample 0.1.0`を作成する。
1. 手動で ancestorVersion を設定し、パッケージを promote (リリース)する。
1. HIGEST と NONE を設定したパッケージを作成する。

#### 実際にこの実験を行ったリポジトリ
以下に実際にこの実験を行ったリポジトリを貼ります。
(Idが含まれるため、`sfdx-project.json` は `sfdx-project-sample.json` にサンプルデータのみをコミットしております。 )

https://github.com/altyjp/try-new-keyword-in-2GP


## 手動で ancestorVersion を設定し、パッケージを promote (リリース)するまで

この記事では 2GP 経験者人向けに大まかな手順のみを説明します。
また前提として2GPでパッケージングを行えるアカウント(無料で用意できます)を保持しており、
sfdxコマンドでパッケージを作成できる状態であるものとします。

詳細は以下の公式ドキュメントをご確認ください。
(既にパッケージを作成・promoteした事がある方はこの章を読み飛ばしてもらっても構いません。)

- [第二世代管理パッケージを作成する前に](https://developer.salesforce.com/docs/atlas.ja-jp.236.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_before.htm)
- [第二世代パッケージのワークフロー](https://developer.salesforce.com/docs/atlas.ja-jp.236.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_workflow.htm)

なにはともあれ、まずは `sfdx force:project:create` コマンドでプロジェクトを作成します。
```
sfdx force:project:create --outputdir 'YOUR_DIR' --projectname 'NAME'
```

またパッケージの作成には資産が必要なので、適当な Apex クラスを作成します。
私は `sfdx/force-app/main/default/classes` に `Hello.cls` とそのテストクラス `HelloTest.cls` 作成しました。
具体的なファイルは[このリンク](https://github.com/altyjp/try-new-keyword-in-2GP/tree/main/sfdx/force-app/main/default/classes)から確認可能です。

そして、 `sfdx-project.json` を以下のように記載します。
```sfdx-project(0.1.0).json
{
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "Sample",
      "versionName": "ver 0.1",
      "versionNumber": "0.1.0.NEXT"
    }
  ],
  "name": "sfdx",
  "namespace": "<YOUR_NAMESPACE>",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "54.0",
  "packageAliases": {
    "Sample": "ID",
    "Sample@0.1.0-1": "ID"
}
}
```
[実際のファイル](https://github.com/altyjp/try-new-keyword-in-2GP/blob/d08193f15d105a7a74c39a5ee24ccbaaee038c0c/sfdx/sfdx-project-sample.json)

パッケージとパッケージバージョンを作成し、リリースします。
```
# パッケージの作成
sfdx force:package:create --name "Sample" --path force-app --packagetype Managed
# パッケージバージョンの作成
sfdx force:package:version:create --package "Sample" -w 10 --installationkey "installationkey" -c
# リリース
sfdx force:package:version:promote --package "ID"
```

これで初期バージョンをリリースできたので、ancestorVersionを設定し、パッケージバージョンを作成します。
```sfdx-project(0.2.0).json
{
  "packageDirectories": [
      {
          "path": "force-app",
          "default": true,
          "package": "Sample",
          "versionName": "ver 0.2",
          "ancestorVersion" : "0.1.0",
          "versionNumber": "0.2.0.NEXT"
      }
  ],
  "name": "sfdx",
  "namespace": "NAME_SPACE",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "54.0",
  "packageAliases": {
      "Sample": "ID",
      "Sample@0.1.0-1": "ID",
      "Sample@0.2.0-1": "ID"
  }
}
```
[実際のファイル](https://github.com/altyjp/try-new-keyword-in-2GP/blob/628079544362605784b000bee9e0b75efdec3058/sfdx/sfdx-project-sample.json)
```
# パッケージバージョンの作成
sfdx force:package:version:create --package "Sample" -w 10 --installationkey "installationkey" -c
# リリース
sfdx force:package:version:promote --package "ID"
```

## HIGEST と NONE を設定したパッケージを作成する。
### HIGEST を試す
さて、ついにここで HIGEST キーワードの登場です。
早速sfdx-project.jsonに組み込みます。

```sfdx-project(0.3.0).json
{
  "packageDirectories": [
      {
          "path": "force-app",
          "default": true,
          "package": "Sample",
          "versionName": "ver 0.3",
          "ancestorVersion": "HIGHEST",
          "versionNumber": "0.3.0.NEXT"
      }
  ],
  "name": "sfdx",
  "namespace": "NAME_SPACE",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "54.0",
  "packageAliases": {
      "Sample": "ID",
      "Sample@0.1.0-1": "ID",
      "Sample@0.2.0-1": "ID"
  }
}
```
[実際のファイル](https://github.com/altyjp/try-new-keyword-in-2GP/blob/ad454404f61e05c642cd5a6ef050723f3cd1460a/sfdx/sfdx-project-sample.json)

パッケージバージョンの作成とリリースします。
```
# パッケージバージョンの作成
sfdx force:package:version:create --package "Sample" -w 10 --installationkey "installationkey" -c
# リリース
sfdx force:package:version:promote --package "ID"
```

特に問題なく成功した。
0.2パッケージをインストールしてHIGHESTを利用した0.3をインストールしてみる。

```
# 0.2.0 パッケージのインストール
sfdx force:package:install -p "0.2.0のId" -k "installationkey" -w 10
# 0.3.0 パッケージのインストール
sfdx force:package:install -p "0.3.0のId" -k "installationkey" -w 10
```
特に問題なく成功した。アップグレードも可能だと考えられる。

### NONE を試すが・・・
試しに NONE も試してみる。
```sfdx-project(0.4.0).json
{
  "packageDirectories": [
      {
          "path": "force-app",
          "default": true,
          "package": "Sample",
          "versionName": "ver 0.4",
          "ancestorVersion": "NONE",
          "versionNumber": "0.4.0.NEXT"
      }
  ],
  "name": "sfdx",
  "namespace": "NAME_SPACE",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "54.0",
  "packageAliases": {
      "Sample": "ID",
      "Sample@0.1.0-1": "ID",
      "Sample@0.2.0-1": "ID"
  }
}
```
[実際のファイル](https://github.com/altyjp/try-new-keyword-in-2GP/blob/e61b564e52b7b5a33b004cb9c9d64f0c0492338f/sfdx/sfdx-project-sample.json)

パッケージバージョンを作成するが、エラーになった。
```
# パッケージバージョンの作成
sfdx force:package:version:create --package "Sample" -w 10 --installationkey "installationkey" -c

ERROR running force:package:version:create:
Can’t create package version because you didn’t specify a package ancestor.
Set the ancestor version to 0.3.0, and try creating the package version.
You can also specify --skipancestorcheck to override the ancestry requirement.
```

嫌な予感がするが、 `--skipancestorcheck` をつけて再チャレンジする。
```
sfdx force:package:version:create --package "Sample" -w 10 --installationkey "installationkey" -c --skipancestorcheck
```
一応成功した。インストールしてみる。
```
# 0.3.0 パッケージのインストール
sfdx force:package:install -p "0.3.0のId" -k "installationkey" -w 10
# 0.4.0 パッケージのインストール
sfdx force:package:install -p "0.4.0のId" -k "installationkey" -w 10

ERROR:  Encountered errors installing the package!,Installation errors: 
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンには
このバージョンと共通する上位バージョンがありません。

ERROR running force:package:install:  Installation errors: 
1) 無効なアップグレードです。, Details: 現在インストールされているバージョンには
このバージョンと共通する上位バージョンがありません。
```
ですよね。

# 結論(最初と同じ)
- 2GP で ancestorVersion を手動で設定している人は HIGEST へ移行すると幸せになれる。
- 既に ancestorVersion がある場合、 NONE を設定することはできない。
- ancestorVersion が最新のパッケージバージョンを指定しない場合、パッケージ作成時にエラーになるようになった。