⚙️ SFDX CLI Setup
This repository implements a simple GitHub composite action for installing the Salesforce CLI and related plugins. The CLI installation is done via npm.
Usage
In a GitHub workflow, the use of the action after the initial checkout step and selecting the Node.js version to be used could look like this:
jobs:
validation:
name: Validation
runs-on: ubuntu-latest
permissions:
contents: read # least-privilege GITHUB_TOKEN - this job only reads the repository
steps:
- name: Checkout
uses: actions/checkout@v7.0.1
with:
persist-credentials: false # the GITHUB_TOKEN is not needed after the checkout - don't leave it in .git/config
- name: Select Node Version
uses: svierk/get-node-version@v1.5.1
- name: Install Dependencies
run: npm ci
- name: Install SF CLI
uses: svierk/sfdx-cli-setup@v1.2.0
with:
version: 2.32.8
plugins: 'sfdx-git-delta,@salesforce/plugin-packaging'Two optional parameters for the sfdx-cli-setup action can be used to set a specific CLI version if needed, in this example 2.32.8, as well as the CLI plugins to be installed, in this case sfdx-git-delta and @salesforce/plugin-packaging. The Node.js version in this example workflow is selected by using the action get-node-version that automatically pulls the version to be used from the package.json file of the SFDX project.
List input (comma-separated or multi-line)
The plugins input accepts a comma-separated string as well as a multi-line block, and the two notations can be mixed freely within one step. A comma-separated string keeps short lists on a single line, a block stays readable once a list grows:
- name: Install SF CLI
uses: svierk/sfdx-cli-setup@v1.2.0
with:
plugins: | # multi-line block
sfdx-git-delta
@salesforce/plugin-packaging
code-analyzer@5.0.0Surrounding whitespace and blank lines are ignored, so 'sfdx-git-delta, @salesforce/plugin-packaging' is read exactly like the tightly packed 'sfdx-git-delta,@salesforce/plugin-packaging'. Each entry is passed to sf plugins install as is, so a version (code-analyzer@5.0.0) or a git URL works as well.
The JSON array notation used up to v1.1.x, e.g. "['sfdx-git-delta','@salesforce/plugin-packaging']", is still supported, so existing workflows keep working unchanged. A malformed input, such as a space-separated list or an unclosed array, fails the step with an explicit error message instead of installing something unintended.
Inputs
| Name | Required | Default | Description |
|---|---|---|---|
plugins | no | SF CLI plugins to install, comma-separated or multi-line, e.g. @salesforce/plugin-packaging,sfdx-git-delta. The JSON array notation "['@salesforce/plugin-packaging','sfdx-git-delta']" is still supported. | |
version | no | SF CLI version to install, e.g. 2.32.8. Installs the latest version if omitted. | |
step-summary | no | true | Write a result section to the GitHub Actions job summary. Set to false to avoid collisions with a custom workflow summary. |
Overriding the version via repository variable
Installing the latest SF CLI version is the recommended default, since Salesforce ships fixes and features at a high cadence. However, sometimes you temporarily need to pin the pipeline to a fixed, known-good CLI version - ideally without touching the workflow file at all. For this, wire the version input to a repository variable (organization and environment variables work the same way):
- name: Install SF CLI
uses: svierk/sfdx-cli-setup@v1.2.0
with:
version: ${{ vars.SF_CLI_VERSION_OVERRIDE }}This wiring is safe to keep in place permanently: as long as the variable is unset or blank, the expression evaluates to an empty string and the action installs the latest version as usual. Only when the variable is populated does it take precedence - so a temporary pin becomes a pure configuration change, and removing the variable's value restores the default behaviour. The job summary always shows the CLI version that was actually installed.
Security & versioning
Every uses: reference in the snippets above is pinned to an exact release version, e.g. svierk/sfdx-cli-setup@v1.2.0. Do the same in your own pipelines:
- Never reference a mutable ref such as
@mainor@v1. It runs whatever code sits on that branch/tag at run time - with access to your org credentials - so a compromised or rewritten ref would run unnoticed. - Good - pin to an exact release tag (
@v1.2.0). Readable, concrete, and bumped through reviewed pull requests. - Strictest - pin to a full-length commit SHA (
@a1b2c3d…) with the version as a trailing comment. A SHA can never be re-pointed by the publisher; the cost is readability. - Enable Dependabot for
github-actionsin the repository that consumes this action, so those pins are bumped for you instead of silently ageing.
This action itself needs no secrets and no GITHUB_TOKEN permissions - it only installs the Salesforce CLI and its plugins. Grant the calling job the least privilege it needs (contents: read is enough for the example above) and use persist-credentials: false on the checkout so the token is not written to .git/config where the CLI or a plugin could pick it up.
If you pass credentials to other steps of the same workflow, reference them in shell steps as environment variables ("$SFDX_AUTH_URL"), never by interpolating ${{ secrets.… }} into the script itself - that would allow command injection and can leak values into the log. The steps of this action follow that rule for all of their inputs.
Releases
Latest release notes can be found on the release page.
License
The scripts and documentation in this project are released under the MIT License.
➡️ Full source & releases: svierk/sfdx-cli-setup
