Git is the source of truth. Repeat.
Every Salesforce DevOps failure mode traces back to the same lie: "the sandbox is the source of truth." It isn't. Git is.
Repo layout
sfdx-project.json
force-app/
main/default/ # base package
features/loyalty/ # unlocked package: Loyalty
features/service-bot/ # unlocked package: Service Bot
data/
seed/*.json # sfdmu / dataloader plans
scripts/apex/*.apex
manifest/package.xml
.github/workflows/*.yml
Use Unlocked Packages to break the monolith. Package dependencies are declared; deploys are ordered automatically.
Branching model
main ── production (protected)
release/* ── release train, tagged & deployed to UAT
develop ── integration, auto-deploy to Integration sandbox
feature/* ── one Jira ticket per branch, scratch org per branch
hotfix/* ── cut from main, merges to main + develop
Every PR must:
- Pass
sfdx-scanner(PMD + ESLint rules) - Pass unit tests with 75%+ per class, org-wide 85%+
- Pass destructive change diff review
Pick a tool
- Copado — enterprise-grade, native on Platform, strong for regulated industries
- Gearset — lower ramp, best DX, superb metadata comparison
- SFDX + GitHub Actions — free, more setup, ceiling depends on team maturity
Neither Copado nor Gearset replaces Git discipline — they add pipeline UX on top of it.
Sample GitHub Actions pipeline
name: sf-ci
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: sfdx-actions/setup-sfdx@v1
- run: sf org login sfdx-url --sfdx-url-file <(echo "$SFDX_AUTH_URL")
env: { SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_CI }} }
- run: sf project deploy validate --source-dir force-app --test-level RunLocalTests
- run: npx @salesforce/sfdx-scanner scanner run --target 'force-app/**/*' --format sarif --outfile scan.sarif
Validate, don't deploy on PR. Actual deploy happens on merge to develop/release/*.
Data seeding
Metadata alone isn't enough. Seed reference data with sfdmu:
{
"objects": [
{ "query": "SELECT Name, IsActive FROM PriceBook2", "operation": "Upsert", "externalId": "Name" },
{ "query": "SELECT Name FROM Loyalty_Tier__c", "operation": "Upsert", "externalId": "Name" }
]
}
Test pyramid
/\
/UI\ Provar / UTAM (~30 flows)
/----\
/ Apex \ Apex unit tests (~thousands)
/--------\
/ Jest \ LWC Jest tests (per component)
/____________\ Static analysis (every file)
Cutover discipline
- Data migration runbook rehearsed in a Full Copy sandbox
- Rollback plan written before Go-Live
- Deployment window with silent user comms + Copado hotfix branch pre-armed
- Post-deploy smoke test — 10 minutes, top 5 flows only, gate the "all clear"
DevOpsCopadoGearset
