The B2C Developer Tooling project provides official GitHub Actions for automating B2C Commerce operations in your CI/CD pipelines.
The official actions handle CLI installation, credential configuration, and Node.js setup automatically — so your workflow files stay focused on what you want to deploy rather than how to configure the tooling. High-level actions provide typed inputs for common operations like code deployment and data import, while a raw command passthrough covers everything else.
The actions are available from the SalesforceCommerceCloud/b2c-developer-tooling repository and support:
- Code deployment — deploy cartridges with reload
- Data import — import site archives in a single step
- MRT deployment — push and deploy MRT storefront bundles
- Job execution — run B2C jobs with wait and timeout
- WebDAV uploads — upload files for data import, content, etc.
- Any CLI command — raw passthrough for operations not covered by high-level actions
All actions are composite YAML — no compiled JavaScript, fully transparent and auditable. They cache the npm install across runs and expose structured JSON outputs for downstream workflow steps.
Store credentials as GitHub repository secrets and non-sensitive configuration as repository variables.
Recommended secrets:
| Secret | Description |
|---|---|
SFCC_CLIENT_ID |
OAuth Client ID |
SFCC_CLIENT_SECRET |
OAuth Client Secret |
SFCC_USERNAME |
WebDAV username |
SFCC_PASSWORD |
WebDAV password/access key |
MRT_API_KEY |
MRT API key |
Recommended variables:
| Variable | Description |
|---|---|
SFCC_SERVER |
B2C instance hostname |
MRT_PROJECT |
MRT project slug |
MRT_ENVIRONMENT |
MRT environment |
Credentials can be passed per-action or set once with the setup action so they're available to all subsequent steps.
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Install the B2C CLI and configure credentials for subsequent steps
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
username: ${{ secrets.SFCC_USERNAME }}
password: ${{ secrets.SFCC_PASSWORD }}
# Run your build steps as usual
- run: npm ci
- run: npm run build
# Generate a code version from the branch name and date
- name: Set code version
id: version
run: |
BRANCH=$(echo "$GITHUB_REF_NAME" | tr '/' '-')
echo "code-version=${BRANCH}-$(date +%Y%m%d-%H%M%S)" >> "$GITHUB_OUTPUT"
# Deploy cartridges — only operation-specific inputs needed
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/code-deploy@v1
with:
code-version: ${{ steps.version.outputs.code-version }}
reload: trueThe setup step installs the CLI and configures credentials for all subsequent steps. Everything after that — your build, version calculation, and deploy — can focus on your project's needs.
uses: SalesforceCommerceCloud/b2c-developer-tooling@v1
Combines setup and command execution. Pass a command to run a CLI command, or omit it for setup-only.
| Input | Default | Description |
|---|---|---|
command |
— | CLI command to run |
version |
latest |
CLI version to install |
node-version |
22 |
Node.js version |
json |
true |
Append --json flag and parse output |
working-directory |
. |
Working directory |
| Auth inputs | — | See Authentication |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
Installs the CLI and writes credentials to environment variables. Use this when you need multiple steps after setup.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
plugins: |
@myorg/b2c-plugin-custom
sfcc-solutions-share/b2c-plugin-intellij-sfcc-configPlugins are installed after the CLI and cached across runs. Each line is an npm package name or GitHub owner/repo.
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/run@v1
Executes any CLI command. Pairs with the setup action.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/run@v1
with:
command: 'sandbox list --realm abcd'| Input | Default | Description |
|---|---|---|
command |
(required) | CLI command to run |
json |
true |
Append --json and parse output |
working-directory |
. |
Working directory |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/code-deploy@v1
Deploy cartridges with typed inputs.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/code-deploy@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
username: ${{ secrets.SFCC_USERNAME }}
password: ${{ secrets.SFCC_PASSWORD }}
code-version: ${{ vars.SFCC_CODE_VERSION }}
reload: true
cartridges: 'app_storefront_base,app_custom'| Input | Default | Description |
|---|---|---|
cartridge-path |
. |
Path to cartridge source directory |
reload |
true |
Activate code version after deploy |
code-version |
— | Code version (overrides env) |
cartridges |
— | Comma-separated cartridges to include |
exclude-cartridges |
— | Comma-separated cartridges to exclude |
delete |
false |
Delete existing cartridges first |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/data-import@v1
Import a site archive. Handles upload, job execution, waiting, and cleanup in one step.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/data-import@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
username: ${{ secrets.SFCC_USERNAME }}
password: ${{ secrets.SFCC_PASSWORD }}
target: './export/site-import.zip'
timeout: 600| Input | Default | Description |
|---|---|---|
target |
(required) | Local file, directory, or zip to import |
timeout |
— | Timeout in seconds |
keep-archive |
false |
Keep archive on instance after import |
show-log |
true |
Show job log on failure |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/mrt-deploy@v1
Push and deploy an MRT bundle.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/mrt-deploy@v1
with:
mrt-api-key: ${{ secrets.MRT_API_KEY }}
project: ${{ vars.MRT_PROJECT }}
environment: ${{ vars.MRT_ENVIRONMENT }}
build-directory: build
message: 'Deploy from CI'| Input | Default | Description |
|---|---|---|
project |
— | MRT project slug |
environment |
— | Target environment |
build-directory |
build |
Local build directory |
message |
— | Bundle message |
bundle-id |
— | Deploy existing bundle by ID |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/job-run@v1
Execute a B2C job and optionally wait for completion.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/job-run@v1
with:
job-id: 'sfcc-site-archive-import'
wait: true
timeout: 600
parameters: |
ImportFile=site-import.zip
ImportMode=merge| Input | Default | Description |
|---|---|---|
job-id |
(required) | Job ID to execute |
wait |
true |
Wait for completion |
timeout |
900 |
Timeout in seconds (when wait=true) |
parameters |
— | KEY=VALUE pairs, one per line |
show-log |
true |
Show job log on failure |
uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/webdav-upload@v1
Upload files via WebDAV.
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/webdav-upload@v1
with:
local-path: './export/site-import.zip'
remote-path: 'src/instance/'
root: IMPEX| Input | Default | Description |
|---|---|---|
local-path |
(required) | Local file or directory |
remote-path |
(required) | Remote destination path |
root |
IMPEX |
WebDAV root (IMPEX, TEMP, CARTRIDGES, etc.) |
Import a site archive:
name: Data Import
on:
workflow_dispatch:
inputs:
import-file:
description: 'Path to the site import archive'
required: true
default: 'export/site-import.zip'
jobs:
import:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/data-import@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
username: ${{ secrets.SFCC_USERNAME }}
password: ${{ secrets.SFCC_PASSWORD }}
target: ${{ github.event.inputs.import-file }}
timeout: 600Build and deploy an MRT storefront on release:
name: MRT Deploy
on:
release:
types: [published]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build storefront
run: npm run build
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/mrt-deploy@v1
with:
mrt-api-key: ${{ secrets.MRT_API_KEY }}
project: ${{ vars.MRT_PROJECT }}
environment: ${{ vars.MRT_ENVIRONMENT }}
build-directory: build
message: 'Release ${{ github.event.release.tag_name }}'When json is enabled (the default), the result output contains the command's structured JSON. Reference it directly in downstream steps:
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/code-deploy@v1
id: deploy
with:
code-version: v25_03_1
reload: true
- name: Show deploy result
run: echo '${{ steps.deploy.outputs.result }}'{
"cartridges": [
{ "name": "app_storefront_base", "dest": "app_storefront_base", "src": "..." },
{ "name": "app_custom", "dest": "app_custom", "src": "..." }
],
"codeVersion": "v25_03_1",
"reloaded": true
}Actions exit with the CLI's exit code, so a failed job will fail the step. Use continue-on-error and fromJSON() when you need to inspect the result after a failure:
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/job-run@v1
id: job
continue-on-error: true
with:
job-id: 'sfcc-site-archive-import'
wait: true
- name: Handle job failure
if: steps.job.outputs.exit-code != '0'
run: echo "Job failed with status ${{ fromJSON(steps.job.outputs.result).exit_status.code }}"Use the version input to pin the CLI version:
- uses: SalesforceCommerceCloud/b2c-developer-tooling@v1
with:
version: '0.4.1'Use @v1 for the latest stable action version (recommended). The floating v1 tag is updated on each backward-compatible release.
Note: High-level actions (
code-deploy,data-import,job-run,mrt-deploy,webdav-upload) and the root action internally referenceactions/setup@v1andactions/run@v1. This means even if you pin the outer action to a specific SHA or tag, the setup and run steps resolve to the latestv1release. For full SHA-level reproducibility, useactions/setup+actions/rundirectly — each can be pinned independently to an exact SHA. For most users,@v1on the high-level actions is the recommended approach.
The CLI supports plugins for custom configuration sources, HTTP middleware, and more. Install plugins in CI with the plugins input on the setup action:
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
with:
client-id: ${{ secrets.SFCC_CLIENT_ID }}
client-secret: ${{ secrets.SFCC_CLIENT_SECRET }}
server: ${{ vars.SFCC_SERVER }}
plugins: |
@myorg/b2c-plugin-custom
sfcc-solutions-share/b2c-plugin-intellij-sfcc-configEach line is an npm package name or GitHub owner/repo. Plugins are installed after the CLI and cached across workflow runs.
The setup action accepts a log-level input that sets SFCC_LOG_LEVEL for all subsequent steps:
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
with:
log-level: debugAvailable levels (most to least verbose): trace, debug, info (default), warn, error, silent.
You can also set the environment variable directly in your workflow:
env:
SFCC_LOG_LEVEL: debugLogs are always human-readable on stderr. The --json flag only controls the structured result on stdout. If you need machine-readable log lines (e.g., for log aggregation), set SFCC_JSON_LOGS=true.
All actions automatically configure:
NO_COLOR=1— clean log output without ANSI colors
Enable Safety Mode in CI/CD to prevent accidental destructive operations:
jobs:
deploy:
runs-on: ubuntu-latest
env:
# Prevent accidental deletions
SFCC_SAFETY_LEVEL:NO_DELETE
steps:
- uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1
- name: Deploy code
run: b2c code deploySafety Levels for CI/CD:
NO_DELETE(Recommended for most CI/CD) - Prevents deletions but allows deployments and updatesNO_UPDATE(Strict) - Only allows read and create operations, blocks updates and deletionsREAD_ONLY(Monitoring/Reporting) - Only allows read operations
Example: Production deployment with safety:
deploy-production:
environment: production
env:
SFCC_SAFETY_LEVEL: NO_DELETE
steps:
- name: Deploy
run: |
b2c code deploy # ✅ Allowed
b2c sandbox start prod # ✅ Allowed
b2c sandbox delete test # ❌ Blocked by safety mode