It’s been nearly four years since we first released second-generation managed packaging (2GP), which allows our AppExchange partners to build and distribute solutions using a CLI-based, source-driven, and automation-friendly development model.

Since then, we received a ton of great feedback from our developer community, and we continue to innovate in multiple areas around developer experience, performance, metadata type parity with first-generation managed packaging (1GP) and so on. Whenever we meet with ISV developers, we consistently hear about the need for Salesforce to help them and their customers move over to the world of 2GP.

Today, I have some exciting news to share with you all! We are addressing the #1 ask from our ISV developers by introducing a new feature: Package Migrations. In a nutshell, Package Migrations fully automates the process of converting 1GP packages to 2GP and seamlessly migrates customers with installed packages across to 2GP. If you’re an ISV partner that creates managed packages, this blog post is for you!

Before we dive into the details of Package Migrations, let’s take a look at some benefits of using 2GP for package development.

Benefits of using 2GP for package development

At the heart of 2GP is a source-driven development model, where a source code repository such as Git represents the source of truth for your package. This is fundamentally different from the world of 1GP, where you use a packaging org to maintain all the metadata that you want to package and distribute to your customers.

This source-driven development model, powered by the Salesforce CLI, can dramatically boost your team’s productivity and collaboration. Developers can use the Dev Hub to quickly spin up scratch orgs, jointly build a feature, and commit it to source control. When you are ready to distribute a new version of your 2GP, simply pull the relevant branch to a local machine and use the CLI to create your new package version.

Importantly, this CLI-based approach also means that you can easily integrate your packaging process fully into CI/CD, making it easy to fully automate your workflow. You can, for instance, automatically run Salesforce Code Analyzer against a codebase and, provided no problems are found, create a new package version.

In the world of 1GP, you were stuck using a different namespace for each of your packages. In 2GP, your packages can all share the same namespace, allowing you to leverage a truly modular approach to package development to keep your packages well-organized. It’s also possible to explicitly declare dependencies among packages, ensuring that everything works together seamlessly.

With 2GP, you also get flexible versioning, which allows you to abandon package versions that you no longer want to build upon. Instead, you can specify a package version ancestor and effectively create a new branch where you want to continue your development.

Finally, supporting customers has never been easier with 2GP. In the world of 1GP, patches can only be created from a patch org. With 2GP’s source-driven development model, you can simply create a patch package version directly from the CLI and, provided that the patch abides by requirements around minor changes and package ancestry, it gets created and ready to be installed into your customer’s org.

All said, 2GP can add a ton of value to your development process. Now, let’s find out how Package Migrations can help you get to the world of 2GP!

Introducing Package Migrations

Package Migrations extends 2GP functionality with additional CLI commands and additional capabilities to help ISV developers fully transition to the world of 2GP. It is currently in Developer Preview and open for all ISV developers to test on their existing 1GP packages. Read on to find out how to participate in the Developer Preview!

There are two elements to Package Migrations: package conversion and package migration. Diagram showing how a 1GP package version can be converted into a corresponding 2GP package version using the sf package convert command. This converted package is then installed into Subscriber A, who already has an installed 1GP package version, triggering an automated migration of subscriber A’s installed 1GP package version to the converted 2GP package version.

Package conversion is initiated through the new sf package convert command. It takes a specific version of your existing 1GP package (Acme v1.0 in this example) and uses some magic behind the scenes to convert it into a corresponding 2GP package version (Acme v1.0.0.1 using 2GP version numbering).

Once you have a converted 2GP package version, you can migrate customers over to 2GP. If you have a subscriber with Acme v1.0 installed, you would start the process by treating it as a normal package upgrade: via the CLI with sf package install (see docs), URL installation, or push upgrades.

As you’re trying to install your converted 2GP package v1.0.0.1, which matches the major.minor version of the 1GP package installed in subscriber A, we run new logic that starts the package migration process. Without changing any metadata on the customer’s org — and without requiring user intervention if you’re using push upgrades — we simply change the package references to point to the new 2GP package.

Once a customer is migrated to 2GP, any patches or upgrades to this customer’s package will need to use 2GP.

Participating in the Package Migrations Developer Preview

To test out Package Migrations, you need to be an ISV partner with access to the Salesforce Partner Community.

In the Partner Community, you will find a dedicated channel for this Developer Preview. We recommend that you join this channel and set notifications to Email every post to receive the latest updates from the Package Migrations team.

On this channel, you will find a number of useful links, including a form to register for the Developer Preview. We will need some details, such as your Packaging Org ID, so that we can activate the Package Migrations feature.

Importantly, participating in the Developer Preview will not have any impact whatsoever in your 1GP package. So, don’t worry and please do participate as your feedback is essential to help us identify and resolve issues sooner rather than later!

Once you’re activated, you can start testing Package Migrations.

Testing conversion of a first-generation managed package

Alright, let’s get started! First of all, make sure that you have installed the Salesforce CLI.

If you installed it previously, ensure that you’re using the latest version:

sf update

Now make sure that you are running within the context of a SalesforceDX project. You can create a new project using:

sf project generate --name <Your project name>

Link the namespace of your managed 1GP by logging in to your DevHub and follow the steps.

That’s it for setup! Now you can go ahead and try to convert your package.

sf package convert --installation-key mdpTest --package 033xxx --wait 20

Let’s run through the parameters. We are using the installation key mdpTest. It will be required whenever you’re trying to install this package version in the future. Alternatively, you can use --installation-key-bypass to bypass the installation key. You will need to enter your full 1GP package ID starting with 033 after --package. The conversion process might take a little while and therefore we added the option --wait to wait for 20 minutes.

As the conversion process executes, you will get an update on its status. Assuming that everything went well, you will get a success message with the ID and installation URL for the newly converted 2GP package version.

Converting Package... ... Successfully created the package version [08cxxx00000KzFSAA0]. Subscriber Package Version Id: 04txxx00000u1cqAAA
Package Installation URL: https://login.salesforce.com/packaging/installPackage.apexp?p0=04txxx00000u1cqAAA
As an alternative, you can use the "sfdx package:install" command.

Congratulations, your package is now converted to 2GP! If you encountered any issues along the way, please report them back to us using the form in the Partner Community group.

Note: At the time of writing this blog post, this command will convert the latest Managed – Released version of your package. We are working on allowing you to convert older and Beta package versions. On the other hand, during Developer Preview, it’s not possible to promote converted 2GP packages to Released status.

Now that your package is converted, let’s test out migrating a subscriber org.

Testing migration of an installed first-generation managed package

To test out migrating a subscriber, you’ll need to create a scratch org as, during Developer Preview, we only support scratch orgs. You can set up a new scratch org like this:

sf org create scratch -f project-scratch-def.json -a MyScratchOrg

In the code above, -f points to your scratch org definition file. You should make sure your scratch org definition file includes any Salesforce features that your package might depend on. Finally, we’re using MyScratchOrg as the alias for this org.

With the scratch org set-up, go ahead and install the 1GP package version that you converted earlier by using the installation URL that you get from your 1GP packaging org. This should be your latest Managed – Released version at this point in time.

You can confirm the package installed successfully during the installation screen. See the example below.

Screenshot showing a successful installation of the package with version 1.7

And see the Installed Packages section of the Setup menu.

Screenshot showing the list of installed packages in the Setup menu, containing the package with version 1.7

Now that you installed your 1GP in the scratch org, it is ready for migration.

Start the migration process by using the installation URL that you received at the end of the package conversion process:

https://login.salesforce.com/packaging/installPackage.apexp?p0=04txxx00000u1cqAAA

You will now go through the same set of screens as above, but this time for your converted 2GP package.

Screenshot showing a successful installation of the package with version 1.7 (Beta 2)

Currently, the user interface shows the “installation” as having been completed. In reality, what we did was a package migration that was completed successfully.

Note that in this example, I’ve used the second Beta build for version 1.7, which corresponds to the same major.minor version as the 1GP package version installed earlier. As the converted 2GP is, during Developer Preview, created as a Beta version, it shows up as such.

Once again, you can confirm the updated package version in the Installed Packages section of the Setup menu, which also shows, in this example, the version number to be 1.7 (Beta 2).

Screenshot showing the list of installed packages in the Setup menu, containing the package with version 1.7 (Beta 2)

Once you have migrated the package in your scratch org, we recommend that you test it to ensure that it works as expected.

You should also take the opportunity to verify whether apps such, as the License Management app or the Feature Management app, are showing the correct information for your migrated package. If you find anything to be amiss, please raise it as an issue and we’ll investigate.

In the meantime …

It will take a few releases for Package Migrations to be generally available. Your participation in the Developer Preview, by testing your packages and providing us feedback, is essential to help us identify and resolve issues earlier on.

In the meantime, what else can you do? We recommend that you experiment with using second-generation packaging as part of your current 1GP-based development model. Confused? Let me explain.

As I mentioned earlier, there are a number of advantages specific to 2GP. Out of these, there are a few that you can start benefiting from today. Here are the steps you can take:

  1. You can set up your source control and feed it with metadata extracted from your packaging org.
  2. You can create a DevHub and spin-off scratch orgs for development using metadata from your source control.
  3. You can create a 2GP package for internal development and testing that mirrors your 1GP package, but using either an internal-only or the same namespace as your 1GP package. Namespace collisions will prevent 1GP and 2GP packages with the same namespace from being installed in the same environment.
  4. Once you’re happy with the contents of your 2GP package, you can migrate metadata over from the relevant source control branch into your packaging org and issue a new version of your package to distribute to customers.

This will help you dip your toes into the world of 2GP and, once Package Migrations is generally available, you will have the ability to abandon your 1GP development model altogether and fully move to a 2GP development model.

Conclusion

We are very excited about Package Migrations, but we need your help in making sure that it is as good as it can be. If you are an ISV developer, please go ahead and register for the Developer Preview in the Partner Community.

We’re very much looking forward to getting your feedback!

Further Resources

Developer Preview group in the Partner Community

Second-Generation Managed Packaging (documentation)

About the author

John Belo is Director, Product Management for Developer Experience Products, focusing on Package Migrations, Salesforce Code Analyzer, and AppExchange App Analytics. He’s been with Salesforce for over seven years and spent the majority of this time within the AppExchange team. He started by leading a team of ISV Technical Evangelists in EMEA, and is now part of the Developer Experience Product Management team, always intent on helping ISVs be as successful as they can be.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS