Use this action to build a package.xml (or use your own) and deploy to a specified Salesforce environment. After deployment, it writes a job summary on the Actions run (including metrics, component changes—name, type, and create/change/delete/unchanged/failed—and optional failure details) and exposes outputs for downstream steps.
DRY_RUN:
description: "Validate deploy and run Apex tests but don't save to the org."
type: boolean
TEST_LEVEL:
description: "Deployment Apex testing level."
type: choice
default: "RunLocalTests"
options:
- NoTestRun
- RunSpecifiedTests
- RunLocalTests
- RunAllTestsInOrg
- RunRelevantTests
WAIT:
description: "Number of minutes to wait for command to complete and display results."
type: number
default: 30
SOURCE_DIRECTORY:
description: "Path to the local source files to deploy (used only when MANIFEST_PATH is not set)."
type: string
default: "force-app"
MANIFEST_PATH:
description: "If set, deploy this manifest instead of generating one from SOURCE_DIRECTORY."
type: string
POST_DESTRUCTIVE_CHANGES:
description: "If set, passed to sf project deploy start as --post-destructive-changes."
type: string
SFDX_AUTH_URL:
description: "The auth url tied to your deployment environment"
type: string
required: true
DEPLOYMENT_ID:
description: "The deployment id from a validation/ dry run."
type: string| Output | Description |
|---|---|
deployment_id |
Salesforce deployment job id. |
deploy_status |
Status from the CLI (e.g. Succeeded, Failed). |
tests_run |
Apex tests run during deploy (empty if not in the CLI JSON). |
tests_failed |
Apex test failures (empty if not in the CLI JSON). |
apex_org_wide_coverage_percent |
Approximate org-wide line coverage from deploy codeCoverage rows, e.g. 87.42 (empty if no coverage data—e.g. NoTestRun or CLI shape differs). |
Coverage is derived from runTestResult.codeCoverage in the deploy result. It is a lines-hit / lines-total rollup across returned rows, not the same as every Salesforce UI metric.
The summary includes a Component changes table built from the deploy result’s componentSuccesses and componentFailures:
| Modification | Meaning |
|---|---|
created |
created on the DeployMessage (new in org). |
change |
changed (updated). |
deleted |
deleted. |
unchanged |
Deployed but same as org (created/changed/deleted all false). |
failed |
Row from componentFailures. |
The manifest artifact row package.xml is omitted. Large deploys list at most 500 rows, with a note if more exist.
This action does not run sfdx-git-delta. In your workflow, install the plugin, run sf sgd source delta, then pass the generated paths into this action.
- Use
MANIFEST_PATHfor the incrementalpackage.xml(for examplesgd-out/package/package.xml). - Set
POST_DESTRUCTIVE_CHANGESwhen you also want post-destructive deletes in the same deploy (for examplesgd-out/destructiveChanges/destructiveChanges.xml). Omit it when that file does not exist or you are not deleting metadata. - For comparisons against
origin/main(or similar), useactions/checkoutwith enough history (for examplefetch-depth: 0) so git can resolve both refs. - Avoid deploying an empty
package.xml; follow SGD’s guidance and branch in your workflow when there is nothing to deploy.
Example fragment (same job must have the Salesforce CLI available before SGD):
- name: Install Salesforce CLI
run: npm install -g @salesforce/cli
- name: Install SGD
run: echo y | sf plugins install sfdx-git-delta
- name: Delta manifest
run: sf sgd source delta --from "origin/main" --to "HEAD" --output-dir sgd-out --source-dir force-app
- name: Deploy
uses: your-org/github-actions@main
with:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL }}
MANIFEST_PATH: sgd-out/package/package.xml
POST_DESTRUCTIVE_CHANGES: sgd-out/destructiveChanges/destructiveChanges.xml(Adjust the action reference and wire POST_DESTRUCTIVE_CHANGES only when that file exists, for example with a conditional step or if: in your workflow.)
To get the SFDX_AUTH_URL, enter the following command in your terminal:
sf org display --verbose --json -o <MY_TARGET_ORG_ALIAS>Copy down the value of sfdxAuthUrl for later.
You can see how these work by checking my write-up or YouTube video.