Skip to content

ci: automate release safety checks and main->dev back-merge - SFS-3247#3410

Open
eduardoformiga wants to merge 5 commits into
devfrom
ci/release-workflow-automation
Open

ci: automate release safety checks and main->dev back-merge - SFS-3247#3410
eduardoformiga wants to merge 5 commits into
devfrom
ci/release-workflow-automation

Conversation

@eduardoformiga

Copy link
Copy Markdown
Member

What's the purpose of this pull request?

Implements the automation roadmap from our release-workflow RFC, turning
several manual/error-prone release steps into CI guards and automation.
The goal is to prevent the classes of failures we hit during the v4 launch
(partial publishes, missing repository.url/provenance, silent "no changed
packages", and forgotten maindev back-merges) without changing the
day-to-day flow.

How it works?

Each commit is a self-contained piece, ordered from smallest guard to the
larger automation:

  1. ci: validate repository.url in release:verifyrelease:verify
    now also fails when a publishable package is missing/mismatched on
    repository.url or has a wrong repository.directory. This is the
    cause of the v4 E422 on @faststore/diagnostics.
  2. ci: force all packages on graduation and v3 releaserelease
    uses --force-conventional-graduate (plain --force-publish is ignored
    alongside --conventional-graduate) and release:v3 uses
    --force-publish, so all 8 packages always graduate/publish together in
    fixed mode.
  3. ci: warn when no packages would be versioned — non-blocking step
    that runs lerna changed and explains the "No changed packages to
    version" situation instead of a confusing silent no-op.
  4. ci: flag packages missing npm provenance — informational,
    non-blocking CI job that warns when a package's latest version has no
    provenance attestation (symptom of a manual publish rather than the CD
    OIDC Trusted Publisher).
  5. ci: automate main to dev back-merge after release — a
    workflow_run-triggered workflow that, after CD on main, opens a
    chore: update dev with main PR. Deterministic conflicts (version fields
    and CHANGELOGs) are resolved by a script; generated files and the lockfile
    are regenerated; any other conflict is auto-resolved to the dev side and
    the PR opens as a draft flagged for manual review.

Both new CI checks (3 and 4) are non-blocking by design — they only emit
warnings.

How to test it?

  • pnpm release:verify passes for the current 8 packages and fails if you
    temporarily blank a package's repository.url.
  • node ./scripts/diagnose-changed.mjs prints the warning on an
    already-released HEAD and a "changed packages detected" message otherwise.
  • node ./scripts/check-provenance.mjs lists each package's latest version
    and flags any without provenance.
  • The back-merge workflow only triggers from a successful CD run on main;
    the resolver (scripts/back-merge-resolve.mjs) was validated on a simulated
    version + CHANGELOG conflict.

References

  • Release-workflow RFC (internal) — automation roadmap (high/medium items).
  • Lerna docs: --conventional-graduate / --force-conventional-graduate.

Checklist

  • PR title and commit messages follow Conventional Commits
  • Added a label according to the PR goal

Made with Cursor

Extend scripts/verify-publish-manifests.mjs to fail the build when a
publishable package is missing/mismatched on repository.url (compared to
the root repo) or has a repository.directory that does not point at the
package. A missing repository.url fails npm provenance with E422 — the
exact failure that hit @faststore/diagnostics during the v4 launch.
In fixed-version mode all packages must move together. Use
--force-conventional-graduate on `release` (plain --force-publish is
ignored when combined with --conventional-graduate) and --force-publish
on `release:v3`, so the latest / v3-latest tags never end up with a
partially published set of packages.
Add a non-blocking diagnostic (scripts/diagnose-changed.mjs) wired into
the release workflow that runs `lerna changed` and emits a warning
explaining the "No changed packages to version" situation, instead of a
silent no-op that reads like a broken release.
Add an informational, non-blocking CI job (scripts/check-provenance.mjs)
that inspects each published package's latest version and warns when it
lacks a provenance attestation — the symptom of a manual publish instead
of the CD OIDC Trusted Publisher, which broke @faststore/diagnostics in
the v4 launch.
Add a workflow_run-triggered workflow that opens a PR back-merging main
into dev after every release (push cannot be used because the release
commit is `[no ci] Release: x.y.z`). Deterministic conflicts (version
fields and CHANGELOGs) are resolved by scripts/back-merge-resolve.mjs and
generated files/lockfile are regenerated; anything else is auto-resolved
to the dev side and the PR opens as a draft flagged for manual review.
@eduardoformiga eduardoformiga requested a review from a team as a code owner July 2, 2026 21:51
@eduardoformiga eduardoformiga requested review from hellofanny and renatamottam and removed request for a team July 2, 2026 21:51
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (8)
  • .github/workflows/back-merge.yml is excluded by none and included by none
  • .github/workflows/ci.yml is excluded by none and included by none
  • .github/workflows/release.yml is excluded by none and included by none
  • package.json is excluded by none and included by none
  • scripts/back-merge-resolve.mjs is excluded by none and included by none
  • scripts/check-provenance.mjs is excluded by none and included by none
  • scripts/diagnose-changed.mjs is excluded by none and included by none
  • scripts/verify-publish-manifests.mjs is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: edd8de52-fe3b-45aa-8b8c-a3e75badd795

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/release-workflow-automation

Comment @coderabbitai help to get the list of available commands.

@codesandbox-ci

codesandbox-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@eduardoformiga eduardoformiga changed the title ci: automate release safety checks and main->dev back-merge ci: automate release safety checks and main->dev back-merge - SFS-3247 Jul 2, 2026
@sonar-workflows

Copy link
Copy Markdown

@renatomaurovtex renatomaurovtex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the full diff (release-workflow automation, SFS-3247). Clean hygiene overall: no runtime deps added (pure node builtins + git/npm/gh CLIs), no lockfile or generated files in the diff, and both new CI checks are non-blocking by design. All checks green (SonarQube, codesandbox, node-ci-v2). Notes below.


🟠 [governance] CI/CD + release-versioning change — needs release-owner sign-off

This touches the release/CD pipeline (release.yml, back-merge.yml) and versioning semantics (package.json scripts), which is a maintainer-domain change. Flagging for an explicit release-owner review (@lemagnetic) before merge — not a code defect, just the approval gate for this class of change.

🟠 [bug] release:v3 now force-publishes every package

release gaining --force-conventional-graduate is well-justified (plain --force-publish is ignored next to --conventional-graduate, and release:dev already force-publishes), so fixed-mode graduation is consistent. But release:v3 previously versioned only changed packages; adding --force-publish makes it bump/publish all 8 on every v3 release even when untouched.

-    "release:v3": "lerna version --conventional-commits --yes && pnpm -r publish --access public --tag v3-latest --no-git-checks",
+    "release:v3": "lerna version --conventional-commits --force-publish --yes && pnpm -r publish --access public --tag v3-latest --no-git-checks",

Is the fixed-mode "everything moves together" behavior intended for the v3 line too, or only for main? If v3 should keep versioning real changes, drop --force-publish here. Worth a one-line note in the PR body either way.

🟡 [ci] back-merge.yml regresses the action pins #3391 just bumped

Base dev is on @v6 for all three actions (checkout / pnpm-action-setup / setup-node) after #3391, and this PR's own new provenance job in ci.yml correctly uses @v6. The new back-merge.yml, though, pins pnpm/action-setup@v4 and actions/setup-node@v4 — inconsistent within the same PR and a regression of the node-deprecation cleanup.

       - name: Setup pnpm
-        uses: pnpm/action-setup@v4
+        uses: pnpm/action-setup@v6
         with:
           version: 10.28.0

       - name: Setup Node.js environment
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@v6
         with:
           node-version: 24.13.0
           cache: "pnpm"

💬 [behavior] Non-deterministic conflicts auto-resolved to the dev side

The resolve step does git checkout --ours on every leftover conflict (incl. source files), so a main hotfix landing in a file the resolver doesn't understand is silently dropped to the dev version. The draft + flagged-file list mitigates this, but the safety net relies entirely on a human actually inspecting the flagged files before merging the draft. Given that's the exact failure mode this RFC is trying to prevent, consider making the flagged case louder (e.g. request-review / assignee) rather than just a draft. Working as designed — just confirming the intent.

💬 [edge] CHANGELOG union dedupes by trimmed line content

unionResolveContent skips any theirs line whose trimmed text already appears on the ours side. For version-scoped CHANGELOG entries this is safe, but a legitimately repeated line (identical bullet text across two entries) would be dropped from the main side. Low risk; noting for completeness.

💬 [ci] provenance heuristic depends on dist.attestations being in the packument

check-provenance.mjs infers provenance from npm view <pkg>@<v> dist.attestations. Please confirm the registry actually surfaces attestations under dist for your published packages — if not, this will false-positive "NO prov" for everything. It's continue-on-error/exit-0 so it can't break CI, but a permanently-noisy warning loses its value.

Nice touches: the verify-publish-manifests repository.url/directory guard reads EXPECTED_REPO_URL from the root manifest and no-ops when absent, so it stays fork/mirror-safe; and the back-merge workflow_run trigger correctly sidesteps the [no ci] release-commit skip.


Verdict: Approved with comments

Blocking (🟠):

  • Release-owner sign-off for the CI/CD + versioning change (governance gate).
  • Confirm release:v3 --force-publish is intended (v3 previously versioned only changed packages).

Non-blocking (🟡/💬):

  • Align back-merge.yml to pnpm/action-setup@v6 + actions/setup-node@v6 (matches dev + this PR's own ci.yml).
  • Make the flagged-conflict draft louder than a passive draft.
  • CHANGELOG union dedupe edge case; provenance dist.attestations assumption.

Checks to confirm before merge: pnpm lint · build · pnpm release:verify (new repository.url guard) · dry-run the back-merge resolver on a simulated version+CHANGELOG conflict. No pnpm size needed (no runtime/bundle surface).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants