A ready-made release system for Salesforce teams. I built it so each release ships only what actually changed, proves the change with Apex tests, and rolls itself back automatically if anything fails. The same delta-deployment logic is templated across five CI platforms, with secrets handling built in. Two VSCode extensions sit on top: Pipeline Manager sets the pipeline up once per project, and Developer Tools handles the daily development work.
Every push reads ci-config.json to decide what happens next. A feature branch runs a check-only validation and stops there, so a pull request is proven against the target org before it merges. An environment branch runs the whole sequence: authenticate, work out the delta, deploy it, run the tests, then tag on success or roll back on failure.
flowchart TD
A["Git Push"] --> B["Read ci-config.json"]
B --> C{"Branch type?"}
C -->|"feature/*"| D["feature/* branch"]
D --> F["Validate only
(check-only)"]
F --> G["Apex tests"]
G --> H["PR into base"]
C -->|"env branch"| E["env branch
(dev / sit / qa / uat / staging / main)"]
E --> I["Authenticate org
(SFDX Auth URL)"]
I --> J["sfdx-git-delta
detect changed metadata"]
J --> K["Generate destructiveChanges.xml
for deletions"]
K --> L["sf project deploy start
deploy the delta"]
L --> M["sf apex run test
gate on test results"]
M --> N{"Success?"}
N -->|"Yes"| O["Tag deployed/<env>"]
N -->|"No"| P["scripts/rollback.sh"]
%% Blueprint tokens as literal hex (Mermaid cannot parse CSS vars or color-mix)
classDef trigger fill:#e0be621f,stroke:#e0be62,stroke-width:1.5px;
classDef ci fill:#8b93e81f,stroke:#8b93e8,stroke-width:1.5px;
classDef sf fill:#62d99a1f,stroke:#62d99a,stroke-width:1.5px;
classDef decision fill:#e0be621f,stroke:#e0be62,stroke-width:1.5px;
classDef ok fill:#62d99a1f,stroke:#62d99a,stroke-width:1.5px;
classDef fail fill:#e697521f,stroke:#e69752,stroke-width:1.5px;
class A trigger;
class C,N decision;
class B,D,E,F,G,H ci;
class I,J,K,L,M sf;
class O ok;
class P fail;
Map any branch pattern to any org alias. The default uses feature/* for validation, a base branch for integration, and named environment branches (dev, sit, qa, uat, staging, main) for sequential promotion.
With no deployed/<env> tag to diff against, the first run deploys everything from package.xml. Every run after that is a delta from the last successful tag.
Each release ships only the things that actually changed. sfdx-git-delta diffs the current commit against the last successful deploy tag to work out exactly what moved, including anything deleted, so removals get cleaned out of Salesforce in the same release. A commit that only touches docs skips the deploy entirely: an empty delta never fires.
A one-file change deploys one file. No full-org deploy on every push, so release time does not balloon as the org grows.
Touching only the changed components keeps each deploy scoped to the work in flight, which means fewer unintended side effects.
Anything deleted from the project is removed from Salesforce in the same release. sfdx-git-delta generates destructiveChanges.xml for it, so there is no hand-maintained delete manifest and nothing gets left behind.
The delta-deploy logic is identical across platforms. Each template just handles its own quirks: how to fetch full git history, what the branch variable is called, how secrets are injected, and how test results are published.
fetch-depth: 0 for full history. Secrets via secrets.<NAME>. Test artifacts via upload-artifact.
Full clone via fetchDepth: '0'. Auth URLs injected via env block. Results via PublishTestResults.
GIT_DEPTH: 0 for history. Base image node:20. JUnit via artifacts:reports:junit.
GitSCM checkout with shallow: false. Credentials via credentials(). Results via junit post step.
clone: depth: full. Base image node:20. Pipelines can be toggled on via REST API.
Each deploy is preceded by a metadata backup via sf project retrieve. If the deploy errors or a test fails, scripts/rollback.sh restores the org from that backup before the pipeline exits.
After each deploy, scripts/run-tests.sh runs local Apex tests via sf apex run test. Results publish as JUnit artifacts, and any failure triggers rollback before the run ends.
SFDX Auth URLs live as CI secrets, never in source. One secret per org alias, named <ORGALIAS_UPPER>_AUTH_URL. The Pipeline Manager extension generates the checklist of exactly which secrets to add.
| Secret name | Purpose |
|---|---|
| DEV_AUTH_URL | Dev environment, feature validation target |
| SIT_AUTH_URL | SIT environment |
| QA_AUTH_URL | QA environment |
| UAT_AUTH_URL | UAT environment |
| STAGING_AUTH_URL | Staging environment |
| PROD_AUTH_URL | Production |
The single source of truth for pipeline behaviour. Generated by the setup wizard, validated by a JSON schema, and read at runtime. Branch-to-org mappings, deploy options and test settings all live here.
The Pipeline Manager extension writes everything from the setup wizard. Nothing here needs to be handwritten.
Two VSCode extensions split the work cleanly. Pipeline Manager is the one-time setup tool: a wizard generates and tracks the pipeline. Developer Tools is the daily driver: deploy, validate, test and manage orgs without leaving the editor.
Set up once per project. A 4-step wizard generates every pipeline file for the chosen CI platform and tells you exactly which secrets to add. An activity-bar panel shows the live config afterwards, so the pipeline stays easy to look after.
The daily driver. Deploy the current file or a full delta, validate check-only, run Apex tests, switch orgs, rotate pipeline credentials, and export a Confluence space to Markdown, all without leaving the editor.