Quality gates
Manual release-owner checklist
Detailed page. Use “On this page” to jump directly to the section you need.
Use this checklist when an authorized maintainer turns a green release pull request into one promoted Record Health Check package. It is the manual companion to the release runtime matrix and the complete release runbook.
The release owner decides when to create and promote a package and when scratch-org testing is worth its quota. An automation assistant may perform those actions when the owner explicitly asks.
Quota policy: One retained pair per release
Section titled “Quota policy: One retained pair per release”Each release may own only two active release scratch orgs: one LWS and one Locker subscriber org. The same org performs clean-install validation, is reset by uninstalling the candidate, and then performs the exact current-stable-to-candidate upgrade. Do not create separate source, clean-install, or older-base orgs for a release.
Pull-request and push CI consume no scratch-org or package-version creation quota. The subscriber release-pair workflow is manual-only, requires the complete no-org preflight, and runs LWS and then Locker one at a time. The source workflow is for contributor investigation outside the release pair; do not dispatch it as an additional release stage. Capacity checks are not reservations and cannot protect against unrelated Dev Hub activity.
Never repeatedly rerun an org-consuming workflow while its first failure is unexplained. Inspect
the original error and existing evidence, correct the cause, and repeat no-org validation first.
Scratch-org workflows are optional release evidence. They are never implied by a release request:
the owner must explicitly authorize the release-pair workflow before it starts. Retain at most two
release pairs. When work starts on N+2, delete the N pair before creating the new pair. An org
that expires within Salesforce’s 30-day maximum is not recreated merely for retention.
Package creation is an owner-run final build after local validation passes, not a debugging tool. No GitHub workflow creates or promotes a package. Optional clean-install, upgrade, and sandbox tests may follow creation when the owner authorizes their environments.
Values to record
Section titled “Values to record”Record these values in the pull request or retained release evidence before starting:
| Value | Example or source |
|---|---|
| Semantic release | MAJOR.MINOR.PATCH from package.json |
| Exact package version | MAJOR.MINOR.PATCH.BUILD from config/release-runtime-matrix.json |
| Release branch | The pull-request head branch |
| Release commit | Full output of git rev-parse HEAD |
| Upgrade bases | Every entry in upgradeBases in config/release-runtime-matrix.json |
| Candidate package ID | The new 04t returned by package creation |
| Optional hosted evidence | Workflow URLs only when the owner authorized those scratch-org runs |
Do not reuse evidence from another commit, pull-request merge commit, branch head, package build, or
04t.
1. Prepare the release branch
Section titled “1. Prepare the release branch”-
In GitHub Desktop, fetch the origin and switch to the release branch.
-
Confirm every intended release change is committed and pushed.
-
Keep the pull request open and do not delete or advance the release branch until package promotion is complete.
-
Confirm the pull request’s required static checks pass on the exact release commit.
-
In a terminal opened at the repository root, run:
Terminal window git status --shortgit rev-parse HEADnpm run check:version-syncnpm run release:preflight -
Stop if the worktree is not clean. Preserve local test and analyzer evidence under its approved ignored evidence directory; do not delete evidence merely to satisfy the clean-worktree gate.
-
Confirm
check:package-boundaryreports side-effect-free example defaults and portable example documentation. No public Example Check or Check Set may enable diagnostics or event publication, and no public example may require a third-party namespace. -
When an AI prompt or metadata contract changed, confirm the four provider-neutral reference drafts pass
check:ai-prompts, containFormulaResultType__c=AUTOfor every Evaluation Type unless a reviewed Formula needs an explicit type, and use(omit from metadata)rather than a literalN/Avalue for unused fields. This check is offline and requires no model credential.
A green pull request summary is source evidence only. A pull-request run in which Salesforce jobs were skipped is not hosted release evidence.
2. Configure the hosted credential
Section titled “2. Configure the hosted credential”The repository Actions secret SFDX_AUTH_URL must contain the Dev Hub SFDX authorization URL. Only
the release owner may create or replace this secret.
-
Obtain the value locally:
Terminal window sf org display --target-org <dev-hub-alias> --jsonSF_DISABLE_LOG_FILE=true sf org auth show-sfdx-auth-url \--target-org <dev-hub-alias> \--json | jq -r '.result.sfdxAuthUrl' | pbcopyContinue only when
sf org displayreturns"status": 0. The second command copies the actualforce://credential directly to the macOS clipboard. The redactedSfdx Auth Urlrow fromsf org displayis a safety notice, not a usable credential. -
In GitHub, open Settings → Secrets and variables → Actions.
-
Create or replace the repository secret named
SFDX_AUTH_URL. -
Paste the clipboard value directly into the secret. Do not print or inspect it.
The secret-presence job proves only that the value is nonempty. The Authenticate Dev Hub step
must also pass. Hosted workflows use a mode-600 temporary file because pinned CLI versions can
change stdin-flag parsing; a tracked structural gate rejects the previously broken stdin/alias
command shape.
Treat this value like a password. Never paste it into an issue, pull request, chat, terminal log, or tracked file.
3. Optional contributor source validation outside a release
Section titled “3. Optional contributor source validation outside a release”Do not dispatch this workflow as additional release evidence after adopting the two-org release pair. It remains available for explicitly authorized contributor investigation outside a release.
- Open Actions → Salesforce source validation (non-release).
- Select Run workflow.
- Select the release branch, not
mainand not a stale branch. - Set
authorize_scratch_org_creationtotrue, then run the workflow. - Confirm
offline-preflightpasses, then confirmCheck release-matrix scratch-org capacitypasses with two daily and active slots available. The complete source matrix creates two scratch orgs. Deleting an org restores an active slot but does not restore a daily creation. Do not run unrelated scratch-org creation concurrently with the release gate. - Open the completed run and confirm that all of these jobs executed and passed:
offline-preflightrequire-dev-hub-secretpackage-source-testslocker-browser-tests (namespaced)
- Confirm the run’s head SHA is the recorded release commit.
- Retain the workflow URL and uploaded evidence.
After any workflow-source fix, commit and push it and start a new workflow run. Rerunning an older run keeps the older commit and workflow definition, so it cannot validate the fix.
Treat incomplete results as failed optional evidence. They do not block package creation.
When the release changes Apex plugin discovery or namespace handling, install one currently
available public namespaced package in one of the authorized source orgs and exercise a qualified
class name from it. Record the install ID and exact RHC reason code. This proves foreign-namespace
resolution and rejection provenance only; it does not prove NS-03 unless that package implements
rhc.RecordHealthCheckPlugin. Keep the successful compatible-plugin topology pending until the Dev
Hub has a genuinely different registered namespace. The selected public control is DLRS
2.25 (04tKA000000cCA1YAM), and RHCForeignApexNamespaceIT must prove that
dlrs.RollupService resolves and returns PLUGIN_INTERFACE_INVALID.
3a. Complete the human documentation review
Section titled “3a. Complete the human documentation review”Before package creation, a named reviewer other than the author must read the affected user pages in navigation order and record the review in the pull request or retained release evidence. The reviewer must confirm:
- every published example uses objects and fields available in an ordinary Salesforce org;
- examples show diagnostics, run events, result events, and error events off by default;
- the Apex AI prompt proposes
FormulaResultType__c=AUTOand never exportsN/A; - PASS, FAIL, SKIPPED, UNABLE_TO_EVALUATE, and ERROR guidance matches the runtime contract; and
- installation, upgrade, rollback, and troubleshooting links lead to one maintained owner page.
Automated documentation checks prove structure and known invariants, not human usefulness. Do not record this step complete without the reviewer’s name and review date.
4. Create exactly one package candidate
Section titled “4. Create exactly one package candidate”Return to the same clean local release branch and run:
npm run package:create -- --dev-hub <dev-hub-alias> --release-readyThe guarded command repeats release preflight, checks package-version capacity, and creates only the
exact four-part version declared in the runtime matrix. Record the returned 04t package-version ID
and preserve the ignored creation-evidence file
under packages/record-health-check/.package-evidence/.
Do not create another candidate because validation failed. Correct the cause first; an additional candidate requires the documented reviewed override and is not a normal retry mechanism.
5. Optionally dispatch the retained installed-package pair
Section titled “5. Optionally dispatch the retained installed-package pair”Do not perform this section unless the release owner explicitly authorizes creation of the exact two-org pair for this release.
- Before creation, delete the pair two releases behind according to the rolling retention policy.
- Open Actions → Subscriber release-pair validation.
- Select Run workflow and choose the unchanged release branch.
- Enter the exact candidate
04tinpackage_version_id. - Set
authorize_scratch_org_creationtotrue, then run the workflow once. - Confirm
offline-preflightpasses. Then confirmCheck subscriber-stage scratch-org capacitypasses before the two selected jobs run sequentially. - Require both jobs to execute and pass, one under Lightning Web Security and one under Lightning Locker. Each job proves a clean candidate install, resets that org, installs the exact current stable version, and upgrades it to the candidate while preserving subscriber configuration.
- Confirm the workflow title identifies the exact candidate and the run’s head SHA is the release commit.
- Retain install requests, the complete subscriber Apex inventory (including
RHCSubscriberFlowSmokeTest), browser evidence, and both upgrade-preservation snapshots.
The one subscriber dispatch creates and retains exactly two orgs for up to 30 days. Workflow concurrency serializes creation but does not reserve capacity against other tools or people. Deleting scratch orgs does not refund daily creations.
A successful source deployment does not prove upgrade behavior. Record each optional result for what it actually tested.
6. Optionally verify a representative sandbox
Section titled “6. Optionally verify a representative sandbox”When the release owner requests human acceptance, install or upgrade the exact candidate in an approved representative sandbox with the affected CPQ Quote page and customer-owned configuration. Coordinate access with its owner; never use production as the test environment. Record the org, permission assignments, expected/actual outcome, and a safe evidence reference for each scenario below. Do not include credentials or customer record contents.
| Scenario | Acceptance evidence required |
|---|---|
cpq-quote-lifecycle | The affected Quote page loads, runs manually and on load, saves, refreshes, and navigates without the reported error, duplicate execution, or an RHC loading overlay. Builder and configuration previews remain quiet. |
existing-page-and-access-preservation | Existing page placements and customer Check Sets survive the upgrade. Admin, Card User, User, and a user without Run permission behave as documented; diagnostics require the separate entitlement. |
four-type-business-outcomes | Representative Formula, Query, Compare Two Queries, and Apex Checks return the expected outcomes, including failure, no-data, and restricted-data cases. A successful transaction alone is insufficient. |
existing-automation | Existing Flow, Apex, REST/MCP, and asynchronous consumers still return their expected results and publish only requested events. Existing validation rules, triggers, and flows remain enabled. |
configuration-recovery | Customer metadata and page-placement backups exist, the documented restore procedure is rehearsed in the sandbox, and a forward-fix/rollout-stop plan is recorded. Do not assume an in-place package downgrade. |
Copy config/release-acceptance-template.json to
packages/record-health-check/.package-evidence/<candidate-04t>-acceptance.json. Fill in the exact
candidate ID, full creation commit, reviewer, ISO verification timestamp, and each scenario’s result
and evidence reference. Leave untested scenarios pending. The file stays ignored and local; retain a
redacted copy with the release evidence. This remains useful human evidence, but promotion does not
require the local acceptance file.
7. Promote the exact candidate
Section titled “7. Promote the exact candidate”From the same working copy, unchanged branch, and exact creation commit, run:
npm run package:promote -- --dev-hub <dev-hub-alias> --package <candidate-04t>Promotion fails unless the worktree is clean, local creation evidence binds the 04t to the current
commit, and the Dev Hub reports the configured package and exact version. Hosted and sandbox
evidence may be retained when it was explicitly authorized, but it is not a promotion prerequisite.
Record the production and sandbox installation URLs printed by the promotion command.
8. Publish the promoted release
Section titled “8. Publish the promoted release”After promotion:
- Update
config/package-releases.json:- move the former
stableentry toprevious; - set
stable.subscriberPackageVersionIdto the promoted04t; - update the production and sandbox installation URLs.
- move the former
- Update
CHANGELOG.mdwith the promoted version, exact04t, user-visible behavior, upgrade impact, and rollback guidance. - Update public install redirects to the promoted
04tand verify both destinations. - Commit and push the publication changes with GitHub Desktop.
- Wait for the pull request’s complete CI workflow to pass again.
- Merge the pull request into
main. - Create the matching semantic-version tag and GitHub release.
- Verify the release page, registry, changelog, tag, and both install links all identify the same
promoted
04t.
Do not announce a candidate as released before promotion and publication are complete.
The release registry, changelog, package chooser, and public production/sandbox redirects must name
the same promoted 04t. Redirect changes are distribution controls, not package downgrade paths.
Stop conditions
Section titled “Stop conditions”Stop the release immediately when any required package or publication condition occurs:
- the local branch advances after package creation and before promotion;
- the worktree is dirty;
- package-version capacity is unavailable;
- a required local source gate or Salesforce package build fails;
- version metadata, package report, registry, install links, or release notes disagree.
Fix the cause and repeat the affected gates. Never reinterpret a skipped or partial result as a pass.
Lessons retained for every release
Section titled “Lessons retained for every release”- A passing mock cannot prove Salesforce lifecycle compatibility. Keep the exact RefreshView regression, and use real browser gates when the owner authorizes their orgs.
- Discover and reconcile every Apex test, including real subscriber Flow interviews; never maintain a one-class smoke list that silently omits a new test.
- Prove all four Check types actually execute in manual and on-load fixtures. A fixture’s label or a completed job is not evidence of type coverage or correct business outcomes.
- Keep each browser run’s evidence separate and reject skipped or flaky results. Never let a later browser run overwrite an earlier failure’s evidence.
- Treat restricted-user first login as a tested prerequisite: wait for the password form or Lightning Home rather than checking visibility once after a redirect. Locate password inputs by label, and require the actual Home path after submission. A Home return URL, a hidden heading, or a login/error page is not success. Keep delayed-form and failure-path regressions runnable without consuming scratch-org quota; hosted browser validation remains optional.
- When upgrade rehearsal is authorized, use the immediately preceding promoted release and record whether customer configuration was preserved.
- Pin and verify the CLI/authentication command, enforce dependency and coverage checks, and record quota limits before dispatch. Fix the cause instead of lowering the gate.
- Authentication success does not prove that a default Dev Hub is configured. Every workflow
scratch-creation command must explicitly select the authenticated
devhubalias with--target-dev-hub devhub. The offline regression gate rejects missing or incorrect Hub targets before any creation attempt; do not rely on a runner’s saved defaults. - Run the actual Code Analyzer commands locally before handing off hosted validation; passing configuration, suppression-inventory, and source checks does not mean the analyzer passed. Test-only Flows need fault connectors too. Fault paths must return explicit failure outputs, not silently continue. Check description findings against the Metadata API schema: action parameters do not support descriptions, so adding invalid XML is not a valid remediation.
- Inspect converted object metadata, not only source-file/manifest parity. A Setup list view
under
objects/CustomPermissioncauses a non-customizableCustomObjectentry during 2GP packaging. Keep real custom permissions incustomPermissions/; the artifact gate rejects this unsupported object/list-view representation before another package build is attempted. - Bind every release decision to the same commit and immutable package ID. A green PR, old artifact, or source deployment is not proof that the package is ready.
- Keep public examples inert on install. The package-boundary gate must reject diagnostics or event publication enabled by default and third-party namespace dependencies in the example library.
- Treat AI output as deployable metadata, not prose. Literal
N/Ais never a stored value; unused fields are omitted, and every drafted Check carries an explicit Formula Result Type.
These controls reduce regression risk; they cannot promise that an unknown defect will never occur.