Pipeline steps
The pipeline is defined in bitbucket-pipelines.yml. It runs on a pinned salesforce/cli:<version>-full
image with a full clone (clone.depth: full, so delta base refs and tags resolve) and a global
max-time of 120 minutes — Bitbucket accepts 1-720 minutes here, and individual steps override the
global value where they need more or less (see the table below). Every step that runs the toolchain
begins with npx -y npm@11.19.0 ci --prefer-offline --no-audit --ignore-scripts; the npx fetch is
the only registry fetch at pipeline time. The reasons behind that line are in
the codebase and the CLI.
The build, validate, deploy, and pool steps then link only the SF CLI plugins they need via
npm run ci:install:tools -- --only <plugin>; the content-sync and cleanup pipelines skip that step.
Step definitions
Steps are declared once as YAML anchors and referenced from the triggers below.
| Step | Runs | Purpose | max-time |
|---|---|---|---|
| Scan Secrets | git fetch of the destination branch, pipe atlassian/git-secrets-scan:3.2.0 (gitleaks, git mode, --log-opts=origin/<destination>..HEAD, --config=.gitleaks.toml) |
Secret gate on every PR: fails on a credential in any commit the PR adds, including ones removed again before HEAD. Posts a Code Insights security report. No npm ci. |
120 |
| Audit Node Dependencies | ci:audit:node:dependencies |
Supply-chain gate on PRs touching package.json/lockfile/.npmrc: blocks on malware advisories only. Runs uncached. |
120 |
| Validate | ci:install:tools --only code-analyzer, validate |
Static gate: build, format:check, lint (code-analyzer), Jest tests. No org involved. |
120 |
| Validate against Scratch | gate → ci:auth:devhub, create:scratch … --use-pool, conditional test apex; teardown after |
Deploys the PR metadata into a claimed pool scratch org as a fail-fast closed-unit check. Self-gated. | 105 |
| Validate against Org | ci:auth:deploy, deploy:validate --wait 40 [--delta-from origin/<target>] |
Check-only deploy against the real stage org; publishes the validation deploy-id as a commit build status. | 120 |
| Validate against Production | ci:auth:deploy --environment production, deploy:validate … |
Twin of Validate against Org with the environment fixed to production. |
120 |
| Deploy to Org | ci:auth:deploy, deploy --wait 40 |
The real deploy. Quick-deploys from the published validation id, else delta, else full. | 120 |
| Maintain Scratch Org Pool | ci:auth:devhub, org:pool:prepare --tag "$PoolTag" --debug |
Tops a pool up toward maxAllocation in batches; seeds each org and stamps its baseline SHA. |
115 |
All org-touching steps run git fetch origin "+refs/heads/*:refs/remotes/origin/*" || true so delta
and seed base refs resolve on the runner. Artifacts published across steps: dist/**, logs/**,
test-reports/**.
Triggers
graph TD
push["Push to any other branch"] --> V1["Validate"]
prOpen["Pull request (any source)"] --> SS["Scan Secrets"] --> VS["Validate against Scratch"] --> VO["Validate against Org"]
dev["Push to develop"] --> depSIT["Validate → Deploy to SIT (auto)"]
uat["Push to uat"] --> depUAT["Validate → Deploy to UAT (auto) → Validate vs Production (manual)"]
main["Push to main/master/trunk"] --> depProd["Validate → Validate vs LIVE (auto) → Deploy to Production (manual)"]
| Trigger | Steps |
|---|---|
default (any other push) |
Validate |
pull-requests: '**' |
Scan Secrets → [Audit Node Dependencies, on lockfile changes] → Validate against Scratch → Validate against Org |
branch develop |
Validate → Deploy to SIT (deployment: sit, automatic) |
branch uat |
Validate → Deploy to UAT (automatic) → Validate against Production (manual) |
branch {main,master,trunk} |
Validate → Validate against LIVE (automatic) → Deploy to Production (manual) |
Custom pipelines
Triggered manually or on a schedule from the Bitbucket UI:
| Pipeline | Variable | What it does |
|---|---|---|
| Maintain CI Scratch Org Pool | PoolTag=ci |
Two parallel Maintain-pool batches for the ci pool. |
| Maintain Dev Scratch Org Pool | PoolTag=dev |
Two parallel batches for the dev pool. |
| Cleanup Scratch Org Pools | PoolTag=ci |
org:pool:cleanup --tag "$PoolTag" — deletes pool orgs wholesale. |
| Sync Content | OrgName, Metadata |
Retrieves selected metadata from an org into the branch. |
| Sync Email Templates | — | Retrieves classic email templates from production. |
| Update Code Analyzer Baseline | — | Regenerates the suppression baseline and pushes it back (schedulable against the default branch). |
| Audit Node Dependencies | — | The supply-chain audit as a schedulable pipeline; reports malware advisories published after a lockfile merged. A green run is silent. |
| Scan Secrets History | — | The secret scan over the whole history of the branch the pipeline runs on (--log-opts=--full-history HEAD; without it gitleaks scans every ref in the clone). Same pipe and rules as the PR step. Manual trigger; no schedule. |
Pool pipelines are per-tag because schedules can't set variables
Bitbucket scheduled pipelines cannot override pipeline variables, so each pool gets its own
custom pipeline with the PoolTag baked in as the default.
For the deploy behaviour behind the deploy/validate steps, see delta deployments and quick deploys.