Releasing to an environment
sfp release installs the artifacts named in a release definition into a target org. It is the step after generating a release definition.
The definition reaches the command one of two ways, and they are mutually exclusive — one of them is required:
--releasecandidate domain:releaseNamefetches it from sfp server. This is the normal path.-p, --releasedefinition <path>reads a YAML file from disk.
Releasing a candidate
sfp release \
--releasecandidate core:Release-2.0.0 \
--targetorg production \
--repository myorg/myrepo--releasecandidate takes the domain:releaseName identifier the candidate was published under. Because the candidate lives on the server, --repository is required to locate it, and --sfp-server-url must point at the server — the latter usually comes from SFP_SERVER_URL. sfp fetches the definition from the server; nothing is read from disk.
Two conditions stop the release before anything is deployed: the candidate does not exist, or it has been aborted. A candidate in any other status can be deployed, finalized included — redeploying a completed release to another org is a normal operation, not an override.
Releasing several domains at once
--releasecandidate accepts more than one candidate, comma-separated or as repeated flags:
sfp release \
--releasecandidate core:Release-2.0.0,sales:Release-2.0.0 \
--targetorg production \
--repository myorg/myrepoAll candidates are fetched first, so a missing or aborted one stops the release before any artifact is installed. sfp then sets the deployment order itself rather than following the order you passed. Each definition is placed by its first package that belongs to no other definition: the earlier that package sits in sfdx-project.json, the earlier the definition deploys. A definition whose packages all appear in another sorts last. A changelog is produced per domain.
Releasing from a file
sfp release -p releases/Release-2.0.0.yml --targetorg productionNo server lookup happens, so --repository is not needed. One difference in behaviour: with --generatechangelog, a file-based definition must carry a changelog block or the command fails up front, and the changelog is built from a git worktree rather than from server-side release history.
What a release does
- Fires a
release.startedwebhook, unless--dryrun. - Fetches every artifact named in the definitions into
./artifacts. Artifacts come from sfp server's internal registry;--npmadds a fallback to an external registry, and the.npmrcis pulled from the repository's configured integration when--npmrcpathis not supplied. - Sorts the definitions, then installs managed package dependencies —
--keyscarries installation keys,--waittimethe per-package timeout. - Deploys the artifacts of each definition in turn.
- Publishes release metadata to the server for each deployment that installed at least one package. This is what advances a release candidate from
pendingtoin_progress, and, whenautoReleaseFinalizationis enabled for the project, what finalizes it once it has reached every release environment for its domain. - Generates the changelog, when
--generatechangelogis set.
A deployment is fully successful only when no package in it failed. A partial deployment — some packages installed, others failed — still publishes its metadata and still produces a changelog, so a candidate can advance on a run that did not deploy cleanly.
Promotion
When a definition sets promotePackagesBeforeDeploymentToOrg and its value matches --targetorg, unlocked packages are promoted before they are installed. That promotion needs a Dev Hub, so -v, --devhubalias becomes mandatory for that release — without it the command stops with DevHub is mandatory when promote is used within release definition, before deploying anything.
Generated candidates carry this attribute by default: the release config's value, or the first active release environment registered for the repository. So the first environment in your release order is normally the one that promotes.
Command attributes
| Flag | Description | Required |
|---|---|---|
-o, --targetorg | Username or alias of the target org | Yes |
--releasecandidate | Release candidate(s) to fetch from the server, as domain:releaseName. Mutually exclusive with -p | One of the two |
-p, --releasedefinition | Path(s) to release definition YAML. Mutually exclusive with --releasecandidate | One of the two |
--repository | Repository identifier. Required with --releasecandidate | No |
--sfp-server-url | URL of sfp server. Required with --releasecandidate. Can be set via SFP_SERVER_URL | No |
-v, --devhubalias | Dev Hub alias. Required when the definition promotes packages to this org | No |
--npm | Fall back to an external NPM registry when an artifact is not in sfp server | No |
--scope | Registry scope. Defaults to the internal registry scope when a server is configured | No |
--generatechangelog | Create a release changelog | No |
--dryrun | Run the release without deploying anything to the target org | No |
--forceinstall | Override skipIfAlreadyInstalled for this run, re-deploying packages the org already reports as installed | No |
--runtests | Force tests during deployment. Tests are skipped by default on sandbox and scratch orgs, always run in production | No |
--keys | Installation keys for managed package dependencies, as packageA:pw123 packageB:pw123 | No |
--waittime | Wait time for package installation. Defaults to 120 | No |
-t, --tag | Label the release, for identification in metrics | No |
The complete flag set is in the CLI reference.
Rehearsing a release
--dryrun runs everything up to deployment — artifacts are fetched and the order is resolved — without installing into the org. Webhooks and release metadata are suppressed, so a dry run never advances a release candidate's status. The flag is hidden from --help, so it does not appear in the command's listed options.
sfp release --releasecandidate core:Release-2.0.0 --targetorg production --repository myorg/myrepo --dryrunWhen a release fails
Either --releasedefinition or --releasecandidate must be provided— neither source was given.--repository is required when using --releasecandidate, and the same for--sfp-server-url. Both are checked before the release starts.- The candidate is aborted. Aborted candidates cannot be deployed. Generate a new one.
DevHub is mandatory when promote is used within release definition— pass-v, --devhubalias. See Promotion.No artifacts to deploy found in artifacts— no artifact named in the definition could be fetched. Usually the artifacts were never published, or the registry scope is wrong.