Skip to content

fix(tools): add preflight checks and rollback to release script#5235

Merged
marcoscaceres merged 6 commits intomainfrom
fix/release-script-preflight
May 8, 2026
Merged

fix(tools): add preflight checks and rollback to release script#5235
marcoscaceres merged 6 commits intomainfrom
fix/release-script-preflight

Conversation

@marcoscaceres
Copy link
Copy Markdown
Contributor

Closes #5234

The release script could fail mid-release (after committing the version bump and tag) due to missing external dependencies, leaving the repo in a state requiring manual cleanup.

Adds three improvements:

Preflight checks run before any mutations — verifying Java (for vnu), Puppeteer Chrome (for respec2html), and that gh-pages resolves unambiguously. Fails fast with actionable fix instructions.

Rollback on failure — saves the pre-release HEAD sha and restores it if anything fails before the push. Deletes the local tag, resets main and gh-pages to their pre-release state. After push (point of no return), if only npm publish fails, it tells you to run npm publish manually instead of rolling back git.

Interactive npm publish — switches from exec() to spawn() with inherited stdio so the npm OTP browser auth flow works.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the tools/release.cjs release workflow by adding upfront dependency checks, adding a local rollback path on failures before pushing, and making npm publish interactive to support OTP/browser auth.

Changes:

  • Add preflight checks for Java (vnu), Puppeteer-managed Chrome (respec2html), and gh-pages branch resolution.
  • Add rollback logic to restore pre-release main/gh-pages state and delete the local tag when failures occur before pushing.
  • Switch npm publish execution from exec() to spawn() with inherited stdio for interactive auth.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/release.cjs
Comment thread tools/release.cjs
Comment thread tools/release.cjs Outdated
Comment thread tools/release.cjs
@marcoscaceres
Copy link
Copy Markdown
Contributor Author

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 30, 2026

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

All four items from the automated review were addressed in commit 6c29f2f:

  1. origin/gh-pages existence — preflight now explicitly checks remotes.some(r => r.trim() === "origin/gh-pages") and fails with a git fetch origin gh-pages hint if missing.
  2. origin-specific check — covered by the same fix above.
  3. remote update before preflight()git remote update (with its loading indicator) now runs before preflight() so the gh-pages ref check sees fresh data.
  4. pushed = true after first push — moved to immediately after git push origin main so partial push failures don't trigger an incorrect local rollback.

Nothing left to address.

@marcoscaceres
Copy link
Copy Markdown
Contributor Author

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

Copy link
Copy Markdown
Contributor

Copilot AI commented May 4, 2026

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

All original review feedback is addressed in the current code:

  1. origin/gh-pages existence — preflight explicitly checks remotes.some(r => r.trim() === "origin/gh-pages") (line 386) and errors with a git fetch origin gh-pages hint if missing.
  2. origin-specific check — covered by the same fix.
  3. git remote update before preflight() — remote update runs at lines 502–504, before preflight() at line 506.
  4. pushed = true placement — it's set at line 574, immediately after git push origin main (the first push), not after all three. This is the correct point-of-no-return: if gh-pages or tags push fails after main is already pushed, the catch block skips local rollback and shows the manual-fix message instead.

Nothing further needs to be changed.

- Check origin/gh-pages exists specifically, not just count remotes
- Move remote update before preflight so refs are current
- Set pushed=true after first push (point of no return)
The W3C CDN syncs from GitHub Releases, not tags. Without this
step, new versions don't reach specs until someone manually creates
a release. Adds gh CLI to preflight checks.
Previously pushed=true was set after only "git push origin main".
If "git push origin gh-pages" or "git push --tags" failed, the
error handler would incorrectly claim "Git push succeeded."

Also fix prefer-template lint error.
@marcoscaceres marcoscaceres force-pushed the fix/release-script-preflight branch from 727e871 to 29b0746 Compare May 5, 2026 10:01
@marcoscaceres marcoscaceres requested a review from sidvishnoi May 8, 2026 08:20
Copy link
Copy Markdown
Member

@sidvishnoi sidvishnoi left a comment

Choose a reason for hiding this comment

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

Mostly recommending to use git switch instead of checkout.

Comment thread tools/release.cjs Outdated
try {
const currentBranch = await getCurrentBranch();
if (currentBranch !== "main") {
await git("checkout main");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
await git("checkout main");
await git("switch main");

Comment thread tools/release.cjs Outdated
}
if (ghPagesHead) {
try {
await git("checkout gh-pages");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
await git("checkout gh-pages");
await git("switch gh-pages");

Comment thread tools/release.cjs Outdated
console.log(
colors.yellow(` Reset gh-pages to ${ghPagesHead.slice(0, 8)}`)
);
await git("checkout main");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
await git("checkout main");
await git("switch main");

Comment thread tools/release.cjs Outdated
console.log(
colors.yellow(` Reset gh-pages to ${ghPagesHead.slice(0, 8)}`)
);
await git("checkout main");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should probably do this in finally?

Comment thread tools/release.cjs Outdated
try {
const currentBranch = await getCurrentBranch();
if (initialBranch !== currentBranch) {
await git(`checkout ${initialBranch}`);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
await git(`checkout ${initialBranch}`);
await git(`switch ${initialBranch}`);

@marcoscaceres
Copy link
Copy Markdown
Contributor Author

@copilot can you evaluate and merge in @sidvishnoi's suggested changes?

Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

@copilot can you evaluate and merge in @sidvishnoi's suggested changes?

Done in commit 1c16849. Applied all four of @sidvishnoi's suggestions: replaced git checkout with git switch at the four locations in the rollback function (lines 456, 477, 482, 490), and moved the switch main after the gh-pages reset into a finally block so it always runs even if the reset fails.

@marcoscaceres marcoscaceres merged commit 593d96e into main May 8, 2026
9 checks passed
@marcoscaceres marcoscaceres deleted the fix/release-script-preflight branch May 8, 2026 10:39
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.

Release script needs preflight checks and rollback on failure

4 participants