Can 2GP upgrade 1GP packages?
That’s the idea of this article. I’m using a slightly different format this time. I’ll be documenting each step along the way so I’ll be discovering the outcomes as I go.
My goal here is to document the process of packaging in both 1GP and 2GP, and to have a bit of fun along the way. I hope to make a discovery or two along the way as well. Enjoy!
What’s the plan?
Here’s a rough outline of the plan.
- Create up a Developer Edition
- Set up a namespace
- Create a 1GP package
- Start documenting (We are here)
- Add some simple code and a simple unit test
- Release 1GP package
- Create DevHub
- Register Namespace (Can we do this?)
- Build SFDX/2GP Project, specifying 1GP package id as ancestor.
- Add same code, try to release 2GP package
Skip the easy stuff (DE, Namespace, Package)
You’re probably already familiar with creating a Developer Edition, assigning a Namespace and defining a package. But if not here are some articles on how to do this stuff.
I’ve probably missed some stuff here, but there’s also a trailhead if you prefer a guided approach: https://trailhead.salesforce.com/content/learn/modules/isv_app_development/isv_app_development_packaging
If you google around you’ll probably see a bunch of SFDX or Second Generation Packaging articles. I am intentionally doing things the old way here. Those who cannot remember the past are condemned to repeat it. Right? Actually… you’d probably be fine just learning SFDX today and skipping 1GP, but that’s not my goal here.
Sample Code
I’m using an old Developer Edition (DE) org here since creating new namespaces and packages for 1GP packages feels like a waste at this time. You’ll see ‘ContactNewOverride’ - this is an artefact of re-using this DE.
For the components I’m just going to add a trigger, a class, and a simple unit test.
Just in case you’re not reading the code as we go - please do not install this in any customer orgs. This will break data. You’ve been warned.
Here’s what my managed package looks like after I add the components.
Go ahead and upload it as a “Managed Released” package. When done you should be given an install URL, it looks something like this (don’t worry, by the time you read this, I’ll have killed this package so that you can’t install it): https://login.salesforce.com/packaging/installPackage.apexp?p0=my1GPPackageVersionId
We want just the package id, here’s mine, if I used the above sanitized URL: my1GPPackageVersionId
Write this down somewhere safe, and let’s get on to creating our SFDX/2GP environment.
2GP Phase
In order to begin development on a 2GP app we have a few things to get out of the way. This topic has been covered ad nauseam in the wild, so I’ll make it quick.
Step 1 - create a new developer org, log in, configure it as a Dev Hub. Make sure you also enable Second Generation Managed Packages, and enable My Domain and deploy it to users. I always forget to do this part - especially the deployment piece.
Step 2 - try to register the namespace the from the DE where we created the 1GP packge. To do this I used the standard Link Namespace, and on the OAuth popup I logged into the DE I created the 1GP package in. I’m honestly shocked this worked, but I’ll take it. Now I don’t have to end the article here.
Step 3 - Let’s make the new package, write some code and see if we can release it.
Here are the commands for the web auth flow to save some googling:
I then updated the sfdx-project.json
to look like this, notice the ancestorId is the package version id we grabbed earlier from the 1GP DE:
Now let’s add some code, and see if we can release it. We’ll be adding the same code as we added to the DE. In my IDE it looks like this:
The commands to build the package, again so you don’t have to google it:
Here’s where it gets sad folks. SFDX/2GP isn’t seeing the ancestor as a valid package. Here’s the error I get:
I think the key sentence here is this one: It's possible that this package was created on a different Dev Hub.
And I can’t combat the statement, it was built using an entirely different packaging org.
“But, but!” and Conclusion
At this point you might be asking, “What if we nominate the original DE as the DevHub?” I thought about this too. Unfortunately it won’t work, since we would need to register the namespace in a separate DE, and it would have been registered in the DE/Packaging Org/DevHub. Put differently, a DevHub cannot use itself as the namespace registry.
So I think we’re blocked here. If you plan to convert an existing 1GP managed package into a 2GP managed package you’ll have to replace it entirely. I wish I had better news.
On the other hand, we learned that we can recycle the namespace from the 1GP DE packaging org. So we don’t have to lose that at least.
If I’ve missed something along the way, please reach out and let me know. I hope you enjoyed this short journey.