Salesforceの第二世代管理パッケージを試してみたメモ

# 1. やってみたこと

Salesforceの第二世代管理パッケージを作成して、作成したパッケージをスクラッチ組織にインストールして見てみた

## 1.1. 免責

試した際のものを書き起こしただけのメモです
再度確認はしていないので、メッセージやボタン名が少し違うかもしれないです

# 2. バージョンや背景など

- Summer '23 Patch 10.8 (2023/7/7時点)
- sfdx-cli/7.206.6 darwin-x64 node-v18.15.0
```shell
% sfdx version
sfdx-cli/7.206.6 darwin-x64 node-v18.15.0
```
- Dev Hub組織はDeveloper Edition


# 3. 試したこと

[第二世代管理パッケージ](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp.htm)
こちらを参考にして試していきます

## 3.1. Dev Hub の有効化

[組織で Dev Hub 機能を有効にする](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_setup_enable_devhub.htm)
こちらに記載の通りに実施します

- `設定 > 開発 > Dev Hub`をクリックします
- `Dev Hub を有効化`を有効にします

NOTE:
> Dev Hub を有効にした後は、無効にすることはできません。

## 3.2. ロック解除された第 2 世代の管理パッケージの有効化

[ロック解除された第 2 世代の管理パッケージを有効にする](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_setup_enable_secondgen_pkg.htm)
こちらに記載の通りに実施します

- `設定 > 開発 > Dev Hub`をクリックします
- `ロック解除済みパッケージと第二世代管理パッケージを有効化`を有効にします

:::note info
NOTE
> 第 2 世代パッケージを有効にすると、無効にすることはできません。
:::


## 3.3. 第二世代管理パッケージの名前空間の作成と登録

### 3.3.1. 名前空間のための組織の作成

https://developer.salesforce.com/signup?d=70130000000td6N
こちらからサインアップを行い、組織を作成します

ここでサインアップした組織を以降は`名前空間組織`と呼ぶことにします

### 3.3.2. 名前空間の作成

- 名前空間組織にログインします
- `設定 > アプリケーション > パッケージマネージャ`をクリックします
- `名前空間設定`の`編集`をクリックします
- `名前空間プレフィックス`に名前空間を入力して、` [参加可能か調べる]`をクリックします
- `保存`します

:::note warn
注意
> 重要
> 名前空間を作成する場合、ユーザにとって便利で有益なものを使用します。ただし、名前空間の名前にユーザに関する情報 (ユーザの名前、ニックネーム、個人情報など) は使用しないでください。
:::


### 3.3.3. 名前空間をDev Hub組織にリンク

- Dev Hub組織にログインします
- `アプリケーションランチャー`から`名前空間レジストリ`をクリックします
- `名前空間をリンク`をクリックします
- ポップアップ表示されるログイン画面で名前空間組織にログインします
- リンクされた名前空間プレフィックスが表示されます

ここで試した際には、名前空間をリンクしようと際にポップアップ表示されるはずのログイン画面がエラーになりました
その際の対処は[Appendix 4.1.](#41-名前空間をdev-hub組織にリンクする際にポップアップ画面でエラーが出た)に記載しました


## 3.3. アプリケーションの作成

[第二世代管理パッケージのワークフロー](https://developer.salesforce.com/docs/atlas.ja-jp.242.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_workflow.htm)
こちらを参考にして試していきます

### 3.3.1. SFDXプロジェクトの作成

任意のフォルダで以下のようなコマンドを実行します
`NAMESPACE`の箇所は作成した名前空間プレフィックスを指定します
```shell
sfdx project generate --namespace NAMESPACE --name demo
```

SFDXプロジェクトの雛形が作成されます
- `sfdx-project.json`を見ると、`namespace`に指定した名前空間プレフィックスが設定されていることが分かります


### 3.3.2. スクラッチ組織の作成

- SFDXプロジェクトのフォルダに移動します
```shell
cd demo
```
- 以下のようなコマンドを実行して、スクラッチ組織を作成します
  - Dev Hub組織はデフォルトDev Hub組織に設定しているとします
  - `alias`は任意のものを指定します
```shell
sfdx org create scratch --definition-file config/project-scratch-def.json --alias demo-app
```

### 3.3.3. メタデータの作成

アプリケーションに含めるメタデータを作成します
今回は以下のものを含めました
- SObject
  - Name
    - Item__c
  - Fields
    - ID
    - Name
      - 自動採番。フォーマットは`{0}`
    - Item Name
      - テキスト
      - 必須
    - Description
      - テキストエリア
      - 必須ではない
  - 検索レイアウト
    - `最近参照したデータ`ビューで以下の項目を表示するように設定しました ([Appendix 4.2.](#42-最近参照したデータビューの項目を編集する))
      - Name
      - Item Name
      - Description
      - 作成者
      - 作成日
      - 最終更新者
      - 最終更新日
    - `すべて選択`ビューで以下の項目を表示するように設定しました
      - Name
      - Item Name
      - Description
      - 作成者
      - 作成日
      - 最終更新者
      - 最終更新日
- タブ
  - `Item__c`オブジェクトを対象とするカスタムオブジェクトタブ
- 権限セット
  - `Item__c`に対する以下の権限を付与
    - タブの設定
      - `利用可`、`参照可能`をチェックします
    - オブジェクト権限
      以下の権限を`有効`にします
      - 参照
      - 作成
      - 編集
      - 削除
    - 項目権限
      以下の権限をチェックします
      - Description
        - 参照アクセス権
        - 編集アクセス権
      - Item Name
        - 参照アクセス権
        - 編集アクセス権


### 3.3.4. メタデータの動作確認

画面操作して動作に問題ないことを確認します


### 3.3.5. スクラッチ組織からソースをPULL

VS CodeなどのIDEで実施するのが簡単です

以下のようなコマンドでもPULLすることができます
```shell
sfdx project retrieve start -o demo-app
```

### 3.3.6. 不要なメタデータの除外および削除

PULLしたメタデータにプロファイルが含まれていました
配布するアプリケーションには不要のため、同期または変換時のソースから除外します
[同期または変換時のソースの除外方法](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm)

- `.forceignore`ファイルに以下を記載します
```
**/profiles/**
```

- プロファイルのメタデータを削除します

- 念の為、スクラッチ組織とPUSHして同期します

VS CodeなどのIDEで実施するのが簡単です

以下のようなコマンドでもPUSHすることができます
```shell
sfdx project deploy start -o demo-app
```

## 3.4. パッケージの作成

メタデータの準備ができたら、パッケージを作成します

以下のようなコマンドを実行します
`--name`オプションにはパッケージ名を指定します
```shell
sfdx package create --name "Demo App" --path force-app --package-type Managed
```

成功したら以下のようにパッケージIDが表示されます
```
=== Ids

 NAME       VALUE              
 ────────── ────────────────── 
 Package Id 0Ho*************** 
```

`sfdx-project.json`ファイルを確認します
- `packageDirectories`の内部に`versionName`や`versionNumber`が追加されています
- `packageAliases`が追加されています


- 以下のコマンドでパッケージの一覧を確認できます
```shell
sfdx package list
```
- 以下のような一覧が表示されます
```
=== Packages [1]

 Namespace Prefix Name     Id                 Alias    Description Type    
 ──────────────── ──────── ────────────────── ──────── ─────────── ─────── 
 NAMESPACE        Demo App 0Ho*************** Demo App             Managed 
```


## 3.5. パッケージバージョンの作成

以下のようなコマンドでパッケージバージョンを作成します
- `--installation-key`に値を設定した場合は、パッケージを別組織にインストールする際に必要になります
```shell
sfdx package version create --package "Demo App" --code-coverage --installation-key ****** --wait 10
```

成功したら以下のような結果が表示されます
```
Version create.... Create version status: Success
Successfully created the package version [08c***************]. Subscriber Package Version Id: 04****************
Package Installation URL: https://login.salesforce.com/packaging/installPackage.apexp?p0=04****************
As an alternative, you can use the "sfdx package:install" command.
```

- 以下のコマンドでパッケージバージョンの一覧を確認できます
```shell
sfdx package version list
```
- 以下のような一覧が表示されます
```
=== Package Versions [1]

 Package Name Namespace Version Name Version Subscriber Package Version Id Alias            Installation Key Released Validation Skipped Ancestor Ancestor Version Branch 
 ──────────── ───────── ──────────── ─────── ───────────────────────────── ──────────────── ──────────────── ──────── ────────────────── ──────── ──────────────── ────── 
 Demo App     NAMESPACE ver 0.1      0.1.0.1 04****************            Demo App@0.1.0-1 true             false    false                                               
```


## 3.6. パッケージインストールの確認

### 3.6.1. インストール確認用のスクラッチ組織を作成

- 以下のようなコマンドでインストール確認用のスクラッチ組織を作成します
  - ここでは`alias`を`demo-userorg`とします
  - `--no-namespace`を指定して、名前空間を設定しません
```shell
sfdx org create scratch --edition developer --no-namespace --alias demo-userorg
```


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

- 以下のようなコマンドでパッケージをインストールします
  - `--package`オプションには`Package Version Id`もしくは`Alias`を指定することができます
  - `Alias`は`Demo App@0.1.0-1`のように`Package Name`と`Version`が連結されたものです。パッケージバージョンの一覧で確認すると良いでしょう
  - パッケージバージョンの作成の際に、`--installation-key`を設定した場合はここでその値を指定します
```shell
sfdx package install --package 04**************** -o demo-userorg --installation-key ****** --wait 10 --publish-wait 10
```
- 成功すると以下のように表示されます
```
10 minutes remaining until timeout. Publish status: Querying Status... done
Waiting 10 minutes for package install to complete.... done
Successfully installed package [04****************]
```


## 3.7. パッケージのリリース

[第二世代管理パッケージのリリース](https://developer.salesforce.com/docs/atlas.ja-jp.242.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_create_pkg_ver_promote.htm)

パッケージバージョンの作成時にはベータとしてマークされています
AppExchangeに登録され、顧客の組織にインストールできるものはリリースされたパッケージバージョンのみになります

- 以下のようなコマンドでリリースします
  - `--package`オプションには`Package Version Id`もしくは`Alias`を指定することができます
```shell
sfdx package version promote --package "Demo App@0.1.0-2"
```
- 成功すると以下のように表示されます
```
Successfully promoted the package version, ID: 04****************, to released. Starting in Winter ‘21, only unlocked package versions that have met the minimum 75% code coverage requirement can be promoted. Code coverage minimums aren’t enforced on org-dependent unlocked packages.
```


- 以下のコマンドでパッケージの詳細を確認します
- 
```shell
sfdx package version report --package "Demo App@0.1.0-2"
```
- 以下のように表示されます
  - `Released`が`true`になっています
```
=== Package Version

 Name                           Value              
 ────────────────────────────── ────────────────── 
 Name                           ver 0.1            
 Subscriber Package Version Id  04**************** 
 Package Id                     0Ho*************** 
 Version                        0.1.0.2            
 Description                                       
 Branch                                            
 Tag                                               
 Released                       true               
 Validation Skipped             false              
 Ancestor                                          
 Ancestor Version                                  
 Code Coverage                  100.00%            
 Code Coverage Met              true               
 Org-Dependent Unlocked Package N/A                
 Release Version                58.0               
 Build Duration in Seconds      75.0               
 Managed Metadata Removed       No                 
 Created By                     00**************** 
```

:::note info
注意
> 昇格とリリースは、各パッケージバージョン番号に対して 1 回だけ実行可能で、この変更は元に戻せません。
:::


## 3.8. バージョンアップ

[co-meeting社のTips記事 > 【第二世代管理パッケージ（2GP）】 バージョニングとアップグレードの注意点](https://www.co-meeting.co.jp/2gp-get-started-vol2/)
こちらを参考にしました

要件によりバージョンツリーは決定するかと思いますが、今回はこの記事に記載の`線形にバージョンを進めていく`を試します

- `sfdx-project.json`の`packageDirectories`に`"ancestorVersion": "HIGHEST"`を追加します
```json
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "Demo App",
      "versionName": "ver 0.1",
      "versionNumber": "0.1.0.NEXT",
      "ancestorVersion": "HIGHEST",
      "versionDescription": ""
    }
  ],
```


### 3.8.1. パッチバージョンアップ

- `sfdx-project.json`の`versionNumber`を以下のように変更します
  - 変更前
    - `0.1.0.NEXT`
  - 変更後
    - `0.1.1.NEXT`
```json
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "Demo App",
      "versionName": "ver 0.1",
      "versionNumber": "0.1.1.NEXT",
      "ancestorVersion": "HIGHEST",
      "versionDescription": ""
    }
  ],
```
- パッケージバージョンを作成します
- 以下のようなエラーが表示されました
```
Error (1): パッチバージョンを作成できません。Salesforce パートナーコミュニティでケースを登録し、このパッケージの名前空間を作成した組織でパッチバージョン設定を有効にするように依頼してください。
Version create.... done
```

どうやらパッチバージョンはSalesforceパートナーでないとダメなようです
今回は断念します


### 3.8.2. マイナーバージョンアップ

- `sfdx-project.json`の`versionNumber`を以下のように変更します
  - 変更前
    - `0.1.0.NEXT`
  - 変更後
    - `0.2.0.NEXT`
- `versionName`にもマイナーバージョンが記載あるのでここも`ver 0.2`に変更します
```json
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "Demo App",
      "versionName": "ver 0.2",
      "versionNumber": "0.2.0.NEXT",
      "ancestorVersion": "HIGHEST",
      "versionDescription": ""
    }
  ],
```
- パッケージバージョンを作成します
- 成功すると以下のように表示されます
```
Version create.... Create version status: Success
Successfully created the package version [08****************]. Subscriber Package Version Id: 04****************
Package Installation URL: https://login.salesforce.com/packaging/installPackage.apexp?p0=04****************
As an alternative, you can use the "sfdx package:install" command.
```
- 以下のコマンドでパッケージバージョンの一覧を確認してみます
```shell
sfdx package version list
```


# 4. Appendix

## 4.1. 名前空間をDev Hub組織にリンクする際にポップアップ画面でエラーが出た

ポップアップでログイン画面が表示されるはずが、以下のエラーメッセージが表示されました
```
error=redirect_uri_mismatch&error_description=redirect_uri%20must%20match%20configuration
```

接続アプリケーション`SalesforceDX Namespace Registry`のコールバックURLに以下が設定されていました
`https://ap16.salesforce.com/environmenthub/soma-callback.apexp`

Dev Hub組織はずいぶん前に作成して、名前空間のリンクを試した時の接続アプリケーションの設定が残っているためかと推測されました
コールバックURLを以下のようにインスタンスURLで修正します
`https://MyDomain.my.salesforce.com/environmenthub/soma-callback.apexp`
しばらく時間を置いて再度試すとログイン画面が表示されて、名前空間をリンクすることができました

## 4.2. `最近参照したデータ`ビューの項目を編集する

[最近表示したリストに表示するフィールドを選択する](https://help.salesforce.com/s/articleView?id=sf.customize_recent_records_list_lex.htm&type=5)
こちらに記載の通りに実施します

`オブジェクト > 検索レイアウト`が表示しない場合は、`オブジェクトの定義の編集`で`検索を許可`をチェックします


# 参考

- [第二世代管理パッケージ](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp.htm)
- [co-meeting 社のTips記事 > TAG: [連載]第二世代管理パッケージ（2GP）](https://www.co-meeting.co.jp/tag/%e9%80%a3%e8%bc%89%e7%ac%ac%e4%ba%8c%e4%b8%96%e4%bb%a3%e7%ae%a1%e7%90%86%e3%83%91%e3%83%83%e3%82%b1%e3%83%bc%e3%82%b8%ef%bc%882gp%ef%bc%89/)



おわり。