
Andrew Hanna

Andrew Hanna

Salesforce development is ver verwijderd van handmatige Change Sets. Zodra teams groeien en vaker releasen, worden handmatige deployments snel een bottleneck.
Daarom is CI/CD (Continuous Integration and Continuous Delivery) belangrijk. Een goede pipeline valideert, test en promoot wijzigingen automatisch van development naar production.
In deze gids kijken we hoe Salesforce CI/CD werkt, hoe je een pipeline bouwt met GitHub Actions, en wanneer DIY automation genoeg is of juist te kwetsbaar wordt.
Salesforce teams deployen geen gecompileerde app, maar metadata en configuratie zoals:
Apex classes en triggers
Lightning Web Components
Flows en automation
Profiles, permission sets, objects, fields en layouts
Zonder automation ontstaan snel drift tussen omgevingen, ontbrekende dependencies, handmatige fouten en weinig zicht op wat er echt is gewijzigd.
CI/CD pipelines lossen dit op door:
wijzigingen automatisch te valideren
tests te draaien vóór deployment
Git als source of truth te gebruiken
alleen goedgekeurde wijzigingen te promoten
Dit blijft het meest gebruikte model. Developers werken in sandboxes, metadata wordt naar Git gehaald en CI/CD promoot die metadata door de omgevingen.
Developer Sandbox
↓
QA
↓
UAT / Staging
↓
Production
Package-based development gebruikt modulaire packages in plaats van de volledige org metadata als één geheel te promoten. Dit past goed bij ISVs, AppExchange partners en enterprise teams met meerdere workstreams.
Developer Sandbox
↓
Retrieve to Git
↓
Pull Request validation
↓
Build unlocked package version
↓
Install in Staging / QA Sandbox
↓
Install same package version in Production
Dit werkt wanneer het team klein is, releases vaak plaatsvinden en één staging of QA omgeving genoeg is voor signoff.
Grotere teams hebben meestal aparte QA en UAT nodig. QA valideert geïntegreerde source changes; UAT valideert de release artifact die naar production gaat.
Developer Sandbox
↓
Feature branch
↓
Pull Request validation
↓
Merge to develop
↓
Deploy source to QA
↓
Create release branch
↓
Build unlocked package version
↓
Install package in UAT
↓
Install same package version in Production
ISVs starten vaak package-led. Grote orgs groeien meestal naar modular unlocked packages, bijvoorbeeld voor sales, service operations, onboarding en core automation.
Kies eerst hoe werk door Git beweegt. De meest voorkomende opties zijn GitFlow en trunk-based development.
main → production history
develop → integration branch
feature/* → work item branches
release/* → release candidate branches
hotfix/* → urgent production fixes
GitFlow past goed bij teams met QA, UAT, scheduled releases en expliciete release candidate branches. Trunk-based development past beter bij kleine mature teams met sterke tests en frequente deployments.
Voor de meeste groeiende Salesforce teams raden we dit model aan:
Developer Sandbox
↓
Retrieve metadata to Git
↓
Feature branch
↓
Pull Request validation
↓
Merge to develop
↓
Deploy source to QA
↓
Create release branch
↓
Build unlocked package version
↓
Install package in UAT
↓
Regression testing and signoff
↓
Install same package version in Production
Source deploys naar QA zijn snel voor integratietests. De package version wordt daarna de stabiele release artifact voor UAT en production.
| Categorie | Package.xml | Source tracking + unlocked packages | Serpent workflow |
|---|---|---|---|
| Model | Manifest-driven deployment | Git-driven development met package promotion | Task-driven workflow rond Git, omgevingen en releases |
| Best voor | Hotfixes en legacy teams | Moderne teams met versioned releases | Teams die snelheid, zichtbaarheid en minder friction willen |
| Dependencies | Handmatig | Beter, maar discipline nodig | Ondersteund door metadata analyse en workflow logica |
| Samenwerking | Grotendeels handmatig | Git-centric en developer-friendly | Geschikt voor developers, admins, testers en release managers |
package.xml is het traditionele manifest voor metadata die je wilt ophalen of deployen.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>AccountService</members>
<name>ApexClass</name>
</types>
<version>61.0</version>
</Package>
Het geeft expliciete controle, maar is handmatig, dependency-prone en moeilijker te beheren bij grote releases.
Source tracking laat Salesforce CLI vergelijken wat in een org is gewijzigd ten opzichte van lokale source:
sf project retrieve start
sf project deploy start
Voor de meeste moderne teams werkt source tracking tijdens development het best, met unlocked packages voor release promotion.
Een sandbox bevat vaak meerdere losse wijzigingen. Het veiligere patroon is alles ophalen, alleen de componenten van één feature selecteren en die scope naar een feature branch committen.
sf project retrieve start
git status
git add force-app/main/default/classes/PricingService.cls
git add force-app/main/default/triggers/OpportunityTrigger.trigger
git commit -m "Feature: pricing approval flow"
Met Serpent wordt dit makkelijker omdat work items, metadata selection en dependency analysis in dezelfde workflow zitten.
Delta deployments zijn nuttig voor snelle PR validation en kleine geïsoleerde features.
sf sgd source delta \
--to HEAD \
--from origin/develop \
--output-dir delta \
--generate-delta
sf project deploy validate --source-dir delta --test-level RunLocalTests
sf project deploy start --source-dir delta
Full deployments zijn beter voor destructive changes, revert commits en het resetten van drift in gedeelde omgevingen.
sf project deploy start --source-dir force-app
Unlocked packages maken releases explicieter: je promoot een versioned artifact in plaats van losse metadata. Dat geeft betere traceability, eenvoudigere UAT-to-production promotion en duidelijkere rollback planning.
sf package create --name SalesApp --package-type Unlocked --path force-app
sf package version create --package SalesApp --wait 20 --installation-key-bypass
sf package install --package 04tXXXXXXXXXXXX --target-org myUATOrg --wait 20
sf package install --package 04tXXXXXXXXXXXX --target-org myProdOrg --wait 20
GitHub Actions is geschikt voor teams die de mechanics willen begrijpen en hun eigen CI/CD foundation willen bouwen. Workflows staan als YAML naast de code.
feature/* → developer work item branches
develop → deployed to QA
release/* → package version build
main → production history
hotfix/* → urgent production fixes
name: Salesforce CI/CD
on:
pull_request:
branches: [develop]
push:
branches:
- develop
- 'release/*'
workflow_dispatch:
inputs:
package_version_id:
required: false
env:
PROJECT_DIR: force-app
QA_ALIAS: qa
UAT_ALIAS: uat
PROD_ALIAS: prod
PACKAGE_NAME: SalesApp
jobs:
pr-validate:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install @salesforce/cli --global
- run: sf plugins install sfdx-git-delta
- run: echo "${{ secrets.SF_JWT_KEY_QA }}" > server.key
- run: |
sf org login jwt \
--client-id ${{ secrets.SF_CLIENT_ID_QA }} \
--jwt-key-file server.key \
--username ${{ secrets.SF_USERNAME_QA }} \
--instance-url ${{ secrets.SF_INSTANCE_URL_QA }} \
--alias $QA_ALIAS
- run: |
sf sgd source delta --to HEAD --from origin/develop --output-dir delta --generate-delta
sf project deploy validate --source-dir delta --target-org $QA_ALIAS --test-level RunLocalTests
In production voeg je meestal aparte jobs toe voor deploy to QA, package version build, install in UAT en handmatige promotion naar production.
Maak een Connected App in Salesforce App Manager.
Zet callback URL op http://localhost:1717/OauthRedirect.
Selecteer OAuth scopes api en refresh_token, offline_access.
Upload een certificaat en bewaar de private key in GitHub Secrets.
openssl genrsa -out server.key 2048
openssl req -new -x509 -days 1825 -key server.key -out server.crt
| Error | Waarschijnlijke oorzaak | Fix |
|---|---|---|
INVALID_LOGIN |
JWT key of client ID klopt niet | Controleer secrets en trailing newlines. |
INSUFFICIENT_ACCESS |
Connected App permissies | Controleer scopes en activatie voor de integration user. |
| Tests failing on deploy | Code coverage onder 75 procent | Draai sf apex run test lokaal en verhoog coverage. |
Salesforce DevOps draait niet om één tool of één perfecte pipeline. Het gaat om een betrouwbaar proces waarin Git de source of truth is, wijzigingen automatisch worden gevalideerd, releases versioned zijn en omgevingen consistent blijven.
GitHub Actions helpt teams de onderliggende automation te begrijpen. Naarmate Salesforce omgevingen complexer worden, helpen tools zoals Serpent om snelheid te behouden zonder controle, zichtbaarheid en release confidence te verliezen.

Andrew Hanna

Serpent Team

Tekunda Team

Tekunda Team

Tekunda Team

Andrew Hanna