Skip to content

fix(cicd): sync .versions.json + harden release pipeline against silent failures#154

Merged
programad merged 1 commit into
developfrom
fix/cicd-versions-json-and-silent-failures
May 8, 2026
Merged

fix(cicd): sync .versions.json + harden release pipeline against silent failures#154
programad merged 1 commit into
developfrom
fix/cicd-versions-json-and-silent-failures

Conversation

@programad
Copy link
Copy Markdown
Contributor

Summary

Third (and hopefully final) fix to unblock the v0.5.0 release pipeline. After getting past the Node 18→22 issue, the next run still failed — but now in a deeper way that exposed both a stale state file and a long-standing class of silent-failure CI bugs.

What broke

Tests passed on Node 22 ✓, but the release pipeline failed at the artifact upload step with the cryptic Input required and not supplied: path. Tracing back:

TypeError: Cannot destructure property 'groups' of 'VERSION_MATCHER.exec(...)' as it is null.
    at bumpVersion (utils.js:46)
    at releaser.js:64

bumpVersion(versions[pkgName], type, true) was being called with versions[pkgName] === undefined. Reason: .versions.json was missing utils, cli, and native-test — workspaces added since the last release that nobody synced into the state file.

The crash happened before the -release marker / icons-tarball-pack logic. So the releaser exited mid-flight, no .tgz was produced, no tag name was emitted, and the workflow merrily marched into upload steps with empty inputs.

Why we didn't notice the crash

This step:

- name: Prepare tag or release
  run: |
    echo "TAG_NAME=$(npm run release | grep v)" >> $GITHUB_OUTPUT

When npm run release crashed and grep v matched nothing, the inner pipeline failed but the outer echo succeeded, so the step exited 0 with TAG_NAME="". The release process then ran along a happy path that didn't exist. This is the "make CI step succeed even when it shouldn't" anti-pattern, and the workflow had it in two places.

Fix (two parts in one PR)

1. Sync .versions.json

Added the missing workspace entries:

  • utils: "0.2.7"
  • cli: "0.2.5"
  • native-test: "0.1.0"
  • Also corrected tailwind: "0.2.5""0.2.6" (was stale by one patch)

All 8 current workspaces now covered.

2. Harden prepare-release.yml against silent failures

  • New pre-flight step Validate .versions.json is in sync with workspaces. Runs before the releaser, walks package.json#workspaces, fails fast with a clear ::error:: message listing missing entries. Future workspace additions that forget .versions.json get caught immediately with a one-line actionable error instead of a TypeError 60 seconds in.

  • Rewrote Prepare tag or release with set -euo pipefail, captures releaser output to release-output.log, extracts the tag with a strict regex (^v[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)* rather than grep v), and explicitly fails with a useful annotation if no tag was produced.

  • Same hardening on Get generated package name — empty *.tgz directory now produces a clear error instead of Input required and not supplied: path two steps later.

  • Fixed the long-standing typo genereatedgenerated.

Verification

$ node -e "..."
.versions.json covers all 8 workspaces.

YAML still parses with 2 jobs. Workflow committed via the husky commit hook (lint-staged formatted both files).

After merge

PR #151 (develop → main) auto-resyncs and prepare-release runs again. With Node 22 + a complete .versions.json + hardened error-surfacing, the releaser should:

  • Walk all 71 commits since v0.4.1-release
  • Bump versions across all affected packages (now including utils, cli, native-test)
  • Pack packages/icons into rocketicons-0.x.0.tgz
  • Append -release to the tag name (the icons package has substantive changes)
  • Auto-push the ci(releaser): bump packages versions... commit onto develop
  • Upload the deployable artifacts for the eventual npm publish on merge to main

…nt failures

Two issues bundled because they were exposed by the same release attempt:

1. `.versions.json` was missing entries for `utils`, `cli`, and
   `native-test` (added to the workspace after the last release).
   `tailwind` was also stale (0.2.5 vs current 0.2.6). When the releaser
   walks commits since the last tag and accumulates per-package bump
   types, it then calls `bumpVersion(versions[pkgName], type, true)` —
   for missing entries that's `bumpVersion(undefined, ...)`, which
   crashes inside `VERSION_MATCHER.exec(undefined)` with a confusing
   TypeError. The crash happened before the `-release` marker logic, so
   the resulting workflow path was wrong, no .tgz was produced, and the
   artifact upload failed with "Input required and not supplied: path".

2. The workflow's bash glue masked the crash. The previous step was:

       echo "TAG_NAME=$(npm run release | grep v)" >> $GITHUB_OUTPUT

   When `npm run release` crashed and `grep v` matched nothing, the
   pipeline failed but the outer `echo` succeeded, so the step exited 0
   with an empty TAG_NAME. Subsequent steps silently produced broken
   artifacts. This is exactly the "happy-path-only" CI bug class that
   makes release pipelines untrustworthy.

Changes:

- `.versions.json`: add `utils`, `cli`, `native-test` entries with
  their current package.json versions; correct `tailwind` to 0.2.6.

- `prepare-release.yml`:
  * New "Validate .versions.json is in sync with workspaces" step
    runs before the releaser and fails fast with a clear actionable
    message if any workspace is missing from .versions.json.
  * Rewrote "Prepare tag or release" to use `set -euo pipefail`,
    capture releaser output to a file, extract the tag with a strict
    regex (`^v[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)*`), and explicitly
    fail the step if no tag was produced. Also annotates a clear
    `::error::` message instead of swallowing the crash.
  * Same hardening on "Get generated package name" so an empty
    *.tgz directory produces a clear error instead of the cryptic
    "Input required and not supplied: path" from upload-artifact.
  * Fixed long-standing typo "genereated" -> "generated".

After this lands, a future workspace addition that forgets
.versions.json will fail in the validation step with a one-line
actionable message, and any future releaser crash will surface
immediately at its origin instead of corrupting downstream artifacts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@programad programad merged commit 2de3a82 into develop May 8, 2026
1 check passed
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.

1 participant