chore(release): unblock 5.3.0 — version lockstep sync + npm-publish chaining - #804
Conversation
…haining
Every semantic-release run was blocked at the prepublishOnly safety gate:
validate-publish.js (Check 5) requires .aiox-core/package.json to match the
root version, but semantic-release only bumps the root manifest. Fixes:
- scripts/sync-version-lockstep.js: syncs .aiox-core/package.json and
compat/aiox-core/package.json (version + @aiox-squads/core dependency pin)
to the target version. Idempotent, standalone-usable.
- .releaserc.json: @semantic-release/exec prepare step runs the sync with
${nextRelease.version} — the gate now passes inside the release run.
- semantic-release.yml: after a non-dry-run release, explicitly dispatch
npm-publish.yml (stable, all) via gh workflow run — the GITHUB_TOKEN tag/
release events do not chain workflows (anti-recursion); workflow_dispatch
is the documented exception (same pattern as release.yml
trigger-npm-publish). Requires the new actions:write permission.
- Version bump 5.2.9 -> 5.3.0 committed across the three manifests (repo
convention: chore(release) bump PRs), so the chained npm-publish.yml can
publish the legacy aiox-core wrapper at 5.3.0 from the committed tree.
Context: docs/handoffs (aiox-cockpit) 2026-07-11-env-normalization-
consolidation.md, Fase 4. The orphan v5.3.0 tag from the failed attempt was
deleted; baseline tag for semantic-release remains v5.2.8 (next: 5.3.0,
minor, driven by the feat commits in #800/#801).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughVersion metadata is aligned to 5.3.0, semantic-release now synchronizes related manifests during preparation, and successful non-dry-run releases dispatch the stable npm publishing workflow for all packages. ChangesRelease version synchronization and publishing
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant SemanticRelease
participant SyncVersionLockstep
participant PackageManifests
participant NpmPublishWorkflow
SemanticRelease->>SyncVersionLockstep: prepare with nextRelease.version
SyncVersionLockstep->>PackageManifests: synchronize package versions
SemanticRelease->>NpmPublishWorkflow: dispatch stable publish for all packages
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Coverage ReportCoverage report not available
Generated by PR Automation (Story 6.1) |
|
🎉 This PR is included in version 5.3.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
scripts/sync-version-lockstep.js (1)
32-38: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winWrap
main()in try/catch for the documented IO-error exit path.The header promises
1 = invalid input / IO error(Line 21), but only the semver-validation branch emits a cleanFAIL:message before exiting — a missing/corrupt.aiox-core/package.jsonorcompat/aiox-core/package.jsonwill instead throw an uncaught exception. The exit code (1) is still correct by Node's default behavior, but the error output is an unstructured stack trace rather than the intendedFAIL:message.🐛 Proposed fix
-function main() { +function main() { + try { const rootPkg = readJson(path.join(ROOT, 'package.json')); ... console.log(`PASS: version lockstep at ${version}`); + } catch (err) { + console.error(`FAIL: ${err.message}`); + process.exit(1); + } }Note: static analysis flagged
fs.readFileSync/writeFileSync(Lines 32, 36) for path traversal — these are false positives sincefilePathis always built from the hardcodedROOTconstant, never from external input.Also applies to: 40-82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/sync-version-lockstep.js` around lines 32 - 38, Wrap the top-level main() execution in a try/catch so IO or JSON parsing failures from readJson and writeJson produce the documented FAIL: message and exit with status 1 instead of an uncaught stack trace. Preserve the existing semver-validation failure behavior and successful main() flow.Sources: Path instructions, Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/semantic-release.yml:
- Around line 176-190: Before the npm-publish dispatch in the semantic-release
workflow, persist the version changes produced by
scripts/sync-version-lockstep.js by committing and pushing the updated
.aiox-core/package.json and compat/aiox-core/package.json to main. Ensure the
push completes before gh workflow run npm-publish.yml executes, while preserving
the existing dry-run guard and dispatch behavior.
---
Nitpick comments:
In `@scripts/sync-version-lockstep.js`:
- Around line 32-38: Wrap the top-level main() execution in a try/catch so IO or
JSON parsing failures from readJson and writeJson produce the documented FAIL:
message and exit with status 1 instead of an uncaught stack trace. Preserve the
existing semver-validation failure behavior and successful main() flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: eb217907-59fd-45ab-bfd6-314898200894
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
.aiox-core/install-manifest.yaml.aiox-core/package.json.github/workflows/semantic-release.yml.releaserc.jsoncompat/aiox-core/package.jsonpackage.jsonscripts/sync-version-lockstep.js
| - name: Chain npm-publish (legacy wrapper + workspace packages) | ||
| if: inputs.dry_run != true | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # The tag/release created by semantic-release uses GITHUB_TOKEN, which does | ||
| # NOT trigger npm-publish.yml's push/release triggers (GitHub Actions | ||
| # anti-recursion). workflow_dispatch via API is the documented exception — | ||
| # same pattern release.yml relies on in its trigger-npm-publish job. | ||
| # npm-publish.yml is idempotent (should_publish skips versions already in | ||
| # the registry), so dispatching after a no-release run is a safe no-op. | ||
| gh workflow run npm-publish.yml --ref main -f publish_mode=stable -f packages=all | ||
| echo "✅ npm-publish.yml dispatched (stable, all packages)" | ||
| echo "### 🔗 Chained npm-publish.yml (stable, all)" >> $GITHUB_STEP_SUMMARY | ||
|
|
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect npm-publish.yml for how it resolves package versions to publish,
# and check for any commit/push step in this workflow that might persist
# the lockstep-synced manifests.
fd -H npm-publish.yml .github
cat .github/workflows/npm-publish.yml 2>/dev/null | rg -n -B2 -A5 'version|package\.json|ref'
rg -n 'git (add|commit|push)|`@semantic-release/git`' .github/workflows/semantic-release.yml .releaserc.jsonRepository: SynkraAI/aiox-core
Length of output: 13729
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== semantic-release workflow around the chained dispatch =="
sed -n '1,260p' .github/workflows/semantic-release.yml | cat -n | sed -n '1,240p'
echo
echo "== releaserc =="
sed -n '1,220p' .releaserc.json | cat -n | sed -n '1,220p'
echo
echo "== lockstep sync script =="
sed -n '1,240p' scripts/sync-version-lockstep.js | cat -n | sed -n '1,240p'Repository: SynkraAI/aiox-core
Length of output: 14867
Persist the lockstep manifests before dispatching npm-publish.yml
.github/workflows/semantic-release.yml:176-187 dispatches npm-publish.yml --ref main, but scripts/sync-version-lockstep.js only updates .aiox-core/package.json and compat/aiox-core/package.json in the semantic-release job’s working tree. The chained workflow checks out committed main and reads those package manifests directly, so future releases will publish against stale legacy versions unless the synced files are committed/pushed first or the publish workflow re-runs the sync itself.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/semantic-release.yml around lines 176 - 190, Before the
npm-publish dispatch in the semantic-release workflow, persist the version
changes produced by scripts/sync-version-lockstep.js by committing and pushing
the updated .aiox-core/package.json and compat/aiox-core/package.json to main.
Ensure the push completes before gh workflow run npm-publish.yml executes, while
preserving the existing dry-run guard and dispatch behavior.
Why
The 5.3.0 release attempt failed at the prepublishOnly publish safety gate:
validate-publish.js(Check 5 /validate-aiox-core-namespace.js) requires.aiox-core/package.jsonto be in version lockstep with the rootpackage.json, but semantic-release (.releaserc.json, no@semantic-release/git) only bumps the root manifest in the release working tree. Nothing bumps the internal manifest → every release is blocked. The failed run also pushed an orphanv5.3.0tag (already deleted).What
scripts/sync-version-lockstep.js— syncs.aiox-core/package.json+compat/aiox-core/package.json(version and the exact@aiox-squads/coredependency pin) to the target version. Idempotent; usable standalone in release-bump PRs..releaserc.json—@semantic-release/execprepare step runs the sync with${nextRelease.version}, so the safety gate passes inside the release run.semantic-release.yml— after a non-dry-run release, explicitly dispatchesnpm-publish.yml(stable,all) viagh workflow run. The tag/release created withGITHUB_TOKENnever chainsnpm-publish.yml(Actions anti-recursion);workflow_dispatchvia API is the documented exception — the same patternrelease.ymluses intrigger-npm-publish. Addsactions: write.npm-publish.ymlis idempotent (skips versions already in the registry).npm-publish.ymlpublishes the legacyaiox-corewrapper at 5.3.0 from the committed tree.Validation (local)
node bin/utils/validate-publish.js→ PUBLISH SAFETY GATE: PASS (2088 files)node scripts/validate-aiox-core-namespace.js→ PASS (5.3.0 lockstep)v5.2.8(5.2.9 was published untagged) → semantic-release computes 5.3.0 (minor, from thefeat:in feat: optimized AIOX agents and skills for Grok Build #800/feat: CORE-SUPER-UPDATE — OSS harvest (Waves 0–F required scope) #801) — matches the dry-run from the release attemptRelease plan after merge
semantic-release.ymldispatch withdry_run=true→ confirm "next release 5.3.0"@aiox-squads/core@5.3.0, tagsv5.3.0, GitHub release, chainsnpm-publish.yml→ legacyaiox-core@5.3.0wrapper + workspace packagesnpm view @aiox-squads/core versionandnpm view aiox-core version= 5.3.0Context: aiox-cockpit
docs/handoffs/2026-07-11-env-normalization-consolidation.md(Fase 4). Follow-up from the #802 review remains open (shell-level guard inpm.sh spawn_terminal()).🤖 Generated with Claude Code
Summary by CodeRabbit