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:releaseName fetches 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/myrepo

All 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 production

No 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

  1. Fires a release.started webhook, unless --dryrun.
  2. Fetches every artifact named in the definitions into ./artifacts. Artifacts come from sfp server's internal registry; --npm adds a fallback to an external registry, and the .npmrc is pulled from the repository's configured integration when --npmrcpath is not supplied.
  3. Sorts the definitions, then installs managed package dependencies — --keys carries installation keys, --waittime the per-package timeout.
  4. Deploys the artifacts of each definition in turn.
  5. Publishes release metadata to the server for each deployment that installed at least one package. This is what advances a release candidate from pending to in_progress, and, when autoReleaseFinalization is enabled for the project, what finalizes it once it has reached every release environment for its domain.
  6. Generates the changelog, when --generatechangelog is 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

FlagDescriptionRequired
-o, --targetorgUsername or alias of the target orgYes
--releasecandidateRelease candidate(s) to fetch from the server, as domain:releaseName. Mutually exclusive with -pOne of the two
-p, --releasedefinitionPath(s) to release definition YAML. Mutually exclusive with --releasecandidateOne of the two
--repositoryRepository identifier. Required with --releasecandidateNo
--sfp-server-urlURL of sfp server. Required with --releasecandidate. Can be set via SFP_SERVER_URLNo
-v, --devhubaliasDev Hub alias. Required when the definition promotes packages to this orgNo
--npmFall back to an external NPM registry when an artifact is not in sfp serverNo
--scopeRegistry scope. Defaults to the internal registry scope when a server is configuredNo
--generatechangelogCreate a release changelogNo
--dryrunRun the release without deploying anything to the target orgNo
--forceinstallOverride skipIfAlreadyInstalled for this run, re-deploying packages the org already reports as installedNo
--runtestsForce tests during deployment. Tests are skipped by default on sandbox and scratch orgs, always run in productionNo
--keysInstallation keys for managed package dependencies, as packageA:pw123 packageB:pw123No
--waittimeWait time for package installation. Defaults to 120No
-t, --tagLabel the release, for identification in metricsNo

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 --dryrun

When 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.

On this page