· tutorials · 5 min read

How to use Unlocked Packages - Tutorial

Leverage unlocked packages in Salesforce development to segment your features.

Leverage unlocked packages in Salesforce development to segment your features.

In Salesforce development, there are two ways of managing code. Org development, and package development.

Org development is the idea of keeping all code inside an individual Salesforce organization. In this model, all apex code, custom fields, and any other metadata are all tracked inside the org. This is sometimes referred to as Happy Soup.

This is a great way of developing Salesforce software. It is also what most developers are familiar with. But using this approach can lead to issues with:

  • Distributing to more than one production org
  • Managing dependencies

To circumvent this, we can organize features inside of packages. With the package development model, we can distribute our code as-is to many orgs. Packages come in flavors like:

  • Managed packages (from the appexchange)
  • Unlocked packages

We are going to dive into unlocked packages, as they are a great way of segmenting feature sets into individual packages.

Requirements

Before we get started, we’ll need a few boxes checked.

First, ensure you have the SF CLI installed.

Additionally, you will need a DevHub org to link these packages to. If you don’t have a DevHub, you can:

  1. Go to developer.salesforce.com
  2. Create a new org
  3. Go to Setup -> DevHub
  4. Enable Dev Hub
  5. Enable Unlocked packages.

Then, you can authenticate your dev hub with the following command:

sf org login web --set-default-dev-hub --alias MyDevHub

Dev Environment Setup

Now that you are authenticated, it’s time to write some code. We need a project to store this code. My favorite way of performing this is using the template I built to make a new repo, then pull the repo into my local machine.

Initial Package Creation

Then, you can create your package with this command.

sf package create --name "Clever Package Name" --path force-app --package-type Unlocked
  • You pass in a package name
  • Tell it where the code lives with --path
  • Specify that we are using an unlocked package

We can see these details inside the sfdx-project.json. This is the file that showcases:

  • Package Name
  • Version Name
  • Version Number
  • Version Description

We can also add additional fields like:

  • releaseNotesUrl to showcase the patch notes

We also need a place to do some of this customization. We can use a scratch org to develop and make customizations as needed.

Using the following command, we can create a scratch org:

sf org create scratch --edition developer --alias scratch-org

We can then open the scratch org, using the following command:

sf org open --target-org scratch-org

Then we can add any customizations needed. This can be in the form of custom fields, custom apex, or any other Salesforce related metadata.

For Apex classes, we can create them like usual. Create an apex class and some accompanying test code, and we’re good to go.

public with sharing class HelloWorld {
    public static void setHelloWorld(Account a){
        a.hello_world__c = true;
    }
}
@isTest
public class HelloWorldTest {

    @isTest(seeAllData=false)
    static void testHelloWorld() {
        Account a = new Account();
        a.Name = 'Subscribe!';
        insert a;
        Test.startTest();
        HelloWorld.setHelloWorld(a);
        Test.stopTest();

        System.assert(a.Hello_World__c, 'Not Hello World!');
    }
}

But you’ll notice that we have a custom field that isn’t in our package. With Org development, we could use change sets to deploy and manage these custom fields. But that’s not an option in Package development. To get this field metadata inside our package we need to:

  • Create a manifest/package.xml
  • Add the definition under the CustomField
  • Retrieve the changes from the org.

Now that we have all of the metadata we want to distribute, let’s bundle this into a package version.

Creating a Package version

We can use the following command to create a new package

sf package version create --package "Clever Package Name" -x --wait 10

We pass in the reference to the package name in either a name or id with the --package flag.

We specify that we don’t want a password with the -x flag. If we did, we could use -k followed by the password. One of these two flags is required.

And we can keep the command open using the --wait flag to prevent the need from polling Salesforce with addtional commands.

We can then use the url in the output, or take the id use the following command to install the package inside our sandbox or scratch org:

sf package install --package 04tak0000002WevAAE --target-org MyDevHub --wait 10

The package created is a beta package. This is useful for testing in a sandbox, but cannot be installed in production orgs.

Preparing Package for Production

We can create another package version, that specifies the -c flag.

sf package version create --package "Clever Package Name" -x -c --wait 10

We need to use this flag to get test coverage.

We can then check the code coverage of our package using the following command:

sf package version report --package 04tak0000002WrpAAE

Promote Unlocked Package Version

Since our test coverage is met, it is time to promote our package. We can get a production ready package by using the following command:

sf package version promote --package 04tak0000002WrpAAE

And once the package is ready, we can install this package inside our production org:

sf package install --package 04tak0000002WrpAAE --target-org MyDevHub --wait 10

Bumping package versions

We can promote 1 package per minor version. Inside the sfdx-project.json, we can see package versions:

{
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true,
      "package": "Jira Integration",
      "versionName": "ver 0.2",
      "versionNumber": "0.2.0.NEXT",
      "versionDescription": ""
    }
  ]
}

We can increment the versionNumber field, where:

  • X.y.z the first number is the major version
  • x.Y.z the second a minor version
  • x.y.Z and the third a patch.

Incrementing any of these will suffice.

We can then run the same command to make a new version.

sf package version create --package "Jira Integration" -x -c --wait 10

Need Our Help To Get Your Data Into Salesforce?

Join dozens of other companies by learning how you can get all your company's data in one place.

Back to Blog