
Andrew Hanna

Andrew Hanna

Salesforce development a beaucoup évolué depuis les Change Sets manuels. Quand les équipes grandissent et que les releases deviennent plus fréquentes, les deployments manuels deviennent rapidement un goulot d'étranglement.
C'est là que CI/CD (Continuous Integration and Continuous Delivery) intervient. Une bonne pipeline valide, teste et promeut automatiquement les changements de development jusqu'à production.
Dans ce guide, nous voyons comment fonctionne Salesforce CI/CD, comment construire une pipeline avec GitHub Actions, et quand une automation DIY commence à montrer ses limites.
Les équipes Salesforce ne livrent pas une application compilée. Elles déploient des metadata et de la configuration:
Apex classes et triggers
Lightning Web Components
Flows et automation
Profiles, permission sets, objects, fields et layouts
Sans automation, les équipes rencontrent du drift entre environnements, des dependencies manquantes, des erreurs manuelles et peu de visibilité sur ce qui a réellement changé.
Les pipelines CI/CD répondent à cela en:
validant les changements automatiquement
lançant les tests avant deployment
gardant Git comme source of truth
promouvant seulement les changements approuvés
C'est encore le modèle le plus courant. Les developers travaillent dans des sandboxes, les metadata sont récupérées dans Git, puis les pipelines CI/CD les promeuvent entre environnements.
Developer Sandbox
↓
QA
↓
UAT / Staging
↓
Production
Le package-based development utilise des packages modulaires au lieu de promouvoir tout l'arbre metadata comme un seul bloc. C'est fréquent chez les ISVs, AppExchange partners et grandes équipes enterprise.
Developer Sandbox
↓
Retrieve to Git
↓
Pull Request validation
↓
Build unlocked package version
↓
Install in Staging / QA Sandbox
↓
Install same package version in Production
Ce modèle fonctionne quand l'équipe est petite, coordonnée et qu'un seul environnement staging ou QA suffit pour le signoff.
Les équipes plus grandes ont souvent besoin de QA et UAT séparés. QA valide les source changes intégrés, tandis que UAT valide l'artifact de release destiné à production.
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
Les ISVs partent souvent d'un workflow package-led. Les grandes orgs adoptent ensuite des modular unlocked packages pour sales, service operations, onboarding ou core automation.
Avant de construire la pipeline, décidez comment le travail circule dans Git. Les deux modèles courants sont GitFlow et trunk-based development.
main → production history
develop → integration branch
feature/* → work item branches
release/* → release candidate branches
hotfix/* → urgent production fixes
GitFlow convient aux équipes avec QA, UAT, releases planifiées et branches release candidates. Trunk-based development convient mieux aux petites équipes matures avec des tests solides et des deployments fréquents.
Pour la plupart des équipes Salesforce en croissance, le flow recommandé est:
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
Le source deploy vers QA est rapide pour les tests d'intégration. La package version devient ensuite l'artifact stable validé en UAT et promu en production.
| Catégorie | Package.xml | Source tracking + unlocked packages | Workflow Serpent |
|---|---|---|---|
| Modèle | Deployment piloté par manifest | Développement Git-driven avec package promotion | Workflow task-driven autour de Git, environnements et releases |
| Idéal pour | Hotfixes et legacy teams | Équipes modernes avec versioned releases | Équipes voulant vitesse, visibilité et moins de friction |
| Dependencies | Manuel | Mieux, mais demande de la discipline | Assisté par metadata analysis et workflow logic |
| Collaboration | Surtout manuelle | Git-centric et developer-friendly | Adapté aux developers, admins, testers et release managers |
package.xml est le manifest traditionnel qui liste les metadata à retrieve ou deploy.
<?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>
Il donne un contrôle explicite, mais reste manuel, fragile côté dependencies et plus difficile à maintenir quand le périmètre de release grandit.
Source tracking compare les changements d'une org avec la source locale:
sf project retrieve start
sf project deploy start
Pour la plupart des équipes modernes, source tracking est meilleur pendant development, tandis que les unlocked packages gèrent la release promotion.
Une sandbox contient souvent plusieurs changements. Le pattern sûr consiste à tout retrieve, sélectionner seulement les composants d'une feature, puis committer ce scope dans une feature branch.
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"
Avec Serpent, cela devient plus simple car work items, metadata selection et dependency analysis sont dans le même workflow.
Les delta deployments sont utiles pour une PR validation rapide et les petites features isolées.
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
Les full deployments sont meilleurs pour destructive changes, revert commits et reset de drift dans les environnements partagés.
sf project deploy start --source-dir force-app
Les unlocked packages rendent les releases explicites: vous promouvez un versioned artifact plutôt qu'un ensemble de metadata. Cela améliore traceability, promotion UAT vers production et planning de rollback.
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 est un bon choix pour comprendre les mechanics et construire une fondation CI/CD dans le repository. Les workflows sont définis en YAML.
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
En production, on ajoute généralement des jobs séparés pour deploy to QA, package version build, install in UAT, puis promotion manuelle vers production.
Créez une Connected App dans Salesforce App Manager.
Définissez la callback URL sur http://localhost:1717/OauthRedirect.
Sélectionnez les OAuth scopes api et refresh_token, offline_access.
Uploadez un certificat et stockez la private key dans GitHub Secrets.
openssl genrsa -out server.key 2048
openssl req -new -x509 -days 1825 -key server.key -out server.crt
| Error | Cause probable | Fix |
|---|---|---|
INVALID_LOGIN |
JWT key ou client ID incorrect | Vérifiez les secrets et les trailing newlines. |
INSUFFICIENT_ACCESS |
Permissions Connected App | Contrôlez les scopes et l'activation pour l'integration user. |
| Tests failing on deploy | Code coverage sous 75% | Lancez sf apex run test localement et améliorez coverage. |
Salesforce DevOps ne dépend pas d'un seul outil ou d'un format de pipeline parfait. Il s'agit de créer un processus fiable où Git est la source of truth, les changements sont validés automatiquement et les releases sont versioned et traceable.
GitHub Actions aide les équipes à comprendre l'automation sous le capot. Lorsque les environnements Salesforce deviennent plus complexes, des outils comme Serpent aident à garder vitesse, contrôle, visibilité et release confidence.

Andrew Hanna

Serpent Team

Tekunda Team

Tekunda Team

Tekunda Team

Andrew Hanna