Andrew Hanna

Andrew Hanna

CI/CD 2GP : automatiser les builds de packages unlocked et managés

CI/CD 2GP : automatiser les builds de packages unlocked et managés

Réponse courte : un pipeline CI/CD 2GP crée une version de package à chaque merge, installe cette version dans une scratch org neuve, exécute les tests contre elle et ne promeut que ce qui passe. Le pipeline lui-même tient en cinq commandes. Ce qui casse vraiment les builds 2GP des mois plus tard, ce n'est pas le pipeline, ce sont les décisions d'ancestry et de namespace prises la première semaine.

Que fait concrètement un pipeline CI/CD 2GP ?

Cinq étapes, dans cet ordre :

  1. Valider la source. Analyse statique et linting sur la pull request, avant toute construction.
  2. Construire une version de package. Une version bêta, produite depuis la source et non depuis une org.
  3. Installer dans un environnement propre. Une scratch org neuve prouve que le package s'installe, ce qui n'est pas la même affirmation que "le code se déploie".
  4. Tester contre le package installé. Le code sous namespace se comporte différemment une fois packagé, donc les tests s'exécutent après l'installation.
  5. Promouvoir ce qui passe. La promotion est la porte, et c'est la seule étape qui doit être difficile à déclencher.

La distinction qui compte : déployer des métadonnées prouve que cela compile dans une org que vous contrôlez. Installer une version de package prouve que cela fonctionne dans une org que vous ne contrôlez pas.

Qu'est-ce qui change entre unlocked et managed 2GP ?

  • Les packages unlocked servent à votre propre parc d'orgs ou à celui d'un client. Pas de namespace obligatoire, pas d'ancestry, pas de security review. Les versions sont bon marché et jetables.
  • Le managed 2GP sert à la distribution : namespace enregistré, protection de la propriété intellectuelle, ancestry, chemins de mise à niveau pour les abonnés et security review AppExchange.

La forme du pipeline est identique. Les conséquences d'une mauvaise promotion, non : une version unlocked regrettée se remplace, une version managé promue devient une API publique pour toujours.

Comment construire le pipeline, étape par étape ?

  1. Authentifier le Dev Hub sans interaction. Un flux JWT bearer avec un certificat stocké dans le coffre de votre CI. Le Dev Hub doit être l'org propriétaire du namespace, sinon la création de version échoue immédiatement.
  2. Créer la version : sf package version create --package MyPackage --code-coverage --installation-key-bypass --wait 60. Récupérez l'identifiant 04t comme sortie de pipeline.
  3. Lancer une scratch org : sf org create scratch --definition-file config/project-scratch-def.json --duration-days 1 --wait 10.
  4. Installer et tester : sf package install --package 04tXXXX --wait 20, puis sf apex run test --test-level RunLocalTests --code-coverage --wait 30.
  5. Promouvoir, uniquement sur la branche de release : sf package version promote --package [email protected].

Tout ce qui précède l'étape 5 tourne sur chaque pull request. L'étape 5 tourne sur une seule branche, derrière une validation humaine.

Comment réussir ancestry et namespace pour que les builds ne cassent pas plus tard ?

Ancestry

L'ancestry ne concerne que le managed 2GP, et c'est là que les pipelines automatisés dérapent en silence. Salesforce exige que l'ancêtre indiqué soit le numéro de version promue le plus élevé du package, et seules les versions promues à l'état managed-released peuvent servir d'ancêtre (Salesforce Developers). Trois règles à coder dans votre pipeline :

  • Utilisez le mot-clé. "ancestorVersion": "HIGHEST" dans sfdx-project.json fixe automatiquement l'ancêtre à la version promue la plus élevée, exactement ce dont la CI a besoin. Les alternatives sont un major.minor.patch explicite ou un ancestorId.
  • Ne promouvez jamais un build à moitié vert. Une version promue devient l'ancêtre suivant. Promouvez du bruit et votre lignée en hérite.
  • Sachez ce que coûte la rupture de la lignée. Vous pouvez briser le versionnage linéaire avec --skip-ancestor-check, mais les packages ne se mettent à jour que le long de la lignée : tout abonné reste sur une version abandonnée perd son chemin de mise à niveau.

Les versions patch ont leur propre règle : un patch ne peut pas être l'ancêtre direct d'une version non patch.

Namespace

  • Liez le namespace au Dev Hub auquel votre CI s'authentifie. Ce seul décalage est l'échec le plus fréquent au premier passage.
  • Le 2GP autorise plusieurs packages dans un même namespace. Séparez par répertoire de package dans sfdx-project.json et déclarez explicitement les dépendances entre packages, avec leurs versions.
  • Vous venez du 1GP ? Salesforce a rendu Package Migrations généralement disponible en Summer '25 : conversion d'un package 1GP en 2GP avec sf package convert et migration des abonnés installés.

Comment garder un pipeline 2GP rapide ?

  • Mutualisez vos scratch orgs. La création d'org, et non celle du package, est généralement l'étape la plus lente. Des orgs préchauffées la sortent du chemin critique.
  • Calibrez les tests par étape. Tests pertinents sur la pull request, RunLocalTests avant la promotion.
  • Mettez la version en cache. Si la source n'a pas changé, ne reconstruisez pas le package.

Vous pouvez assembler tout cela avec la CLI Salesforce plus GitHub Actions, Azure Pipelines ou CumulusCI. Serpent vous donne le même pipeline sans le YAML : workflows natifs 1GP, 2GP et managed package, résolution des dépendances entre packages et gestion des versions chez les abonnés sur tous les plans, avec pooling de scratch orgs préchauffées sur Scale. D'autres guides de build et de release sont dans SF Guides.

FAQ

Peut-on automatiser entièrement la création de packages 2GP ?

Oui. Création de version, installation, tests et promotion sont tous des commandes CLI, donc le cycle complet tourne sans intervention. Gardez malgré tout la promotion derrière une validation humaine.

Qu'est-ce que l'ancestry en 2GP ?

La filiation déclarée entre versions de package managé. Elle définit le chemin de mise à niveau des abonnés, car les packages ne se mettent à jour que le long de cette lignée.

Les packages unlocked ont-ils besoin d'un namespace ?

Non. Ils peuvent s'en passer, d'où leur intérêt pour un parc d'orgs interne. Le managed 2GP exige un namespace enregistré et lié à votre Dev Hub.

Pourquoi ma création de version échoue-t-elle sur l'ancestry ?

Le plus souvent parce que l'ancêtre indiqué n'est pas une version promue en managed-released, ou parce qu'une version patch a été définie comme ancêtre d'une version non patch.

La CI doit-elle promouvoir chaque build vert ?

Non. La promotion est irréversible en pratique et fixe l'ancêtre suivant : elle appartient à une branche de release derrière une validation, pas à chaque merge.

Articles similaires

Curieux de livrer plus vite avant de vous lancer ? Parlons-en

Sans engagement.