Start free
Andrew Hanna

Andrew Hanna

2GP CI/CD: unlocked en managed package builds automatiseren

2GP CI/CD: unlocked en managed package builds automatiseren

Kort antwoord: een 2GP CI/CD-pipeline maakt bij elke merge een packageversie, installeert die versie in een verse scratch org, draait de tests ertegen en promoveert alleen wat slaagt. De pipeline zelf is vijf commando's. Wat 2GP-builds maanden later sloopt is niet de pipeline, maar de ancestry- en namespace-keuzes uit week een.

Wat doet een 2GP CI/CD-pipeline precies?

Vijf fasen, in deze volgorde:

  1. Valideer de source. Statische analyse en linting op de pull request, voordat er iets gebouwd wordt.
  2. Bouw een packageversie. Een betaversie, gemaakt vanuit source en niet vanuit een org.
  3. Installeer ergens schoon. Een verse scratch org bewijst dat het pakket installeert, en dat is een andere bewering dan "de code deployt".
  4. Test tegen het geinstalleerde pakket. Code met namespace gedraagt zich anders zodra het verpakt is, dus tests draaien na de installatie.
  5. Promoveer wat slaagt. Promoveren is de poort, en het is de enige stap die moeilijk te triggeren hoort te zijn.

Het onderscheid dat telt: deployen van metadata bewijst dat het compileert in een org die jij beheert. Een packageversie installeren bewijst dat het werkt in een org die jij niet beheert.

Wat verschilt er tussen unlocked en managed 2GP?

  • Unlocked packages zijn voor je eigen orgs of die van een klant. Geen namespace nodig, geen ancestry, geen security review. Versies zijn goedkoop en vervangbaar.
  • Managed 2GP is voor distributie: een geregistreerde namespace, bescherming van intellectueel eigendom, ancestry, upgradepaden voor abonnees en de AppExchange security review.

De vorm van de pipeline is voor beide gelijk. De gevolgen van een verkeerde promote niet: een unlocked versie waar je spijt van hebt vervang je, een gepromoveerde managed versie is voorgoed publieke API.

Hoe bouw je de pipeline, stap voor stap?

  1. Authenticeer de Dev Hub non-interactief. Een JWT bearer flow met een certificaat in je CI-secretstore. De Dev Hub moet de org zijn die de namespace bezit, anders faalt het aanmaken van een versie meteen.
  2. Maak de versie: sf package version create --package MyPackage --code-coverage --installation-key-bypass --wait 60. Leg het resulterende 04t-id vast als pipeline-output.
  3. Start een scratch org: sf org create scratch --definition-file config/project-scratch-def.json --duration-days 1 --wait 10.
  4. Installeer en test: sf package install --package 04tXXXX --wait 20, daarna sf apex run test --test-level RunLocalTests --code-coverage --wait 30.
  5. Promoveer, alleen op de releasebranch: sf package version promote --package [email protected].

Alles voor stap 5 draait op elke pull request. Stap 5 draait op precies een branch, achter een menselijke goedkeuring.

Hoe krijg je ancestry en namespace goed, zodat builds later niet breken?

Ancestry

Ancestry geldt alleen voor managed 2GP, en daar gaan geautomatiseerde pipelines stilletjes de mist in. Salesforce vereist dat de ancestor die je opgeeft het hoogste gepromoveerde versienummer van dat pakket is, en alleen versies die naar managed-released zijn gepromoveerd kunnen als ancestor gelden (Salesforce Developers). Drie regels om in je pipeline vast te leggen:

  • Gebruik het keyword. "ancestorVersion": "HIGHEST" in sfdx-project.json zet de ancestor automatisch op de hoogste gepromoveerde versie, precies wat CI nodig heeft. De alternatieven zijn een expliciete major.minor.patch of een ancestorId.
  • Promoveer nooit een build die maar half slaagde. Een gepromoveerde versie wordt de volgende ancestor. Promoveer je ruis, dan erft je ancestry-lijn die ruis.
  • Weet wat het kost om de lijn te breken. Je kunt lineaire versionering doorbreken met --skip-ancestor-check, maar pakketten upgraden alleen langs de ancestry-lijn, dus elke abonnee op een verlaten versie verliest zijn upgradepad.

Patchversies hebben een eigen regel: een patch kan niet de directe ancestor van een niet-patchversie zijn.

Namespace

  • Koppel de namespace aan de Dev Hub waar je CI op inlogt. Deze ene mismatch is de meest voorkomende fout bij de eerste run.
  • 2GP staat meerdere pakketten in een namespace toe. Splits per package directory in sfdx-project.json en declareer afhankelijkheden tussen pakketten expliciet, met versies.
  • Kom je van 1GP? Salesforce maakte Package Migrations algemeen beschikbaar in Summer '25: het converteert een 1GP-pakket naar 2GP met sf package convert en migreert bestaande abonnees mee.

Hoe houd je een 2GP-pipeline snel?

  • Pool je scratch orgs. Het aanmaken van orgs is doorgaans trager dan het bouwen van pakketten. Voorverwarmde orgs halen die stap van het kritieke pad.
  • Schaal je tests per fase. Relevante tests op de pull request, RunLocalTests voor de promote.
  • Cache de versie. Is de source niet gewijzigd, bouw het pakket dan niet opnieuw.

Je kunt dit allemaal zelf bouwen met de Salesforce CLI plus GitHub Actions, Azure Pipelines of CumulusCI. Serpent geeft je dezelfde pipeline zonder de YAML: native 1GP-, 2GP- en managed-package-workflows, dependency-resolutie tussen pakketten en versiebeheer over abonnee-orgs op elk plan, met voorverwarmde scratch org pooling op Scale. Meer build- en releasegidsen staan in SF Guides.

FAQ

Kun je het aanmaken van 2GP-pakketten volledig automatiseren?

Ja. Versie aanmaken, installeren, testen en promoveren zijn allemaal CLI-commando's, dus de hele cyclus draait onbemand. Houd promoveren toch achter een menselijke goedkeuring.

Wat is package ancestry in 2GP?

De gedeclareerde afstamming tussen managed packageversies. Die bepaalt het upgradepad voor abonnees, want pakketten upgraden alleen langs die lijn.

Hebben unlocked packages een namespace nodig?

Nee. Unlocked packages kunnen zonder, en daarom passen ze bij interne orgs. Managed 2GP vereist een geregistreerde namespace gekoppeld aan je Dev Hub.

Waarom faalt mijn package version create op ancestry?

Meestal omdat de genoemde ancestor geen gepromoveerde, managed-released versie is, of omdat een patchversie als ancestor van een niet-patchversie is gezet.

Moet CI elke groene build promoveren?

Nee. Promoveren is in de praktijk onomkeerbaar en zet de volgende ancestor, dus het hoort op een releasebranch achter een goedkeuring, niet bij elke merge.

Gerelateerde artikelen

Benieuwd naar sneller releasen voordat je instapt? Laten we praten

Vrijblijvend.