Skip to content

fix(ci): set versions from one script in both publish paths - #9

Merged
qwlong merged 2 commits into
mainfrom
fix/share-version-bump
Aug 18, 2026
Merged

qwlong merged 2 commits into
mainfrom
fix/share-version-bump

Conversation

@qwlong

@qwlong qwlong commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Update: this also unbreaks main

main is currently red on every job. The v0.10.7 manual publish ran npm version at the repo root, which generated a package-lock.json, and the git add . in the next step swept it into main along with a rewritten yarn.lock:

81661cd chore(release): manual release v0.10.7
 package-lock.json  | 10131 +++++++++++++++++
 yarn.lock          |   677 +--

turbo then refuses to start, so the build step fails everywhere:

x could not resolve workspaces: We detected multiple package managers in
| your repository: npm, yarn. Please remove one of them.

The second commit removes the lockfile, restores yarn.lock to its state before that publish, ignores package-lock.json, and narrows the commit step to stage only the files the version step touches rather than the whole tree.

That closes both halves of the failure: scripts/version.js writes nothing but package.json files, so no lockfile is generated in the first place, and the commit step would not pick one up even if something else created it.

Verified locally: yarn install --frozen-lockfile and yarn build both succeed, 450 tests pass, and both workflow files still parse.


Problem

Version bumping was implemented twice, once per publish path, and the two had drifted.

The manual workflow never re-pointed the internal dependency. It ran npm version per package and stopped there, while .releaserc.json additionally rewrote the @dorval/core range. The v0.10.7 release went out through the manual workflow, so:

$ npm view dorval@0.10.7 dependencies.@dorval/core
^0.10.6

Harmless this time — ^0.10.6 still satisfies 0.10.7 — but a manual release crossing a minor boundary would ship a CLI resolving to an older core.

npm version refuses to set the version it already has. Recovering a half-published release means re-running with the same version, which is precisely what the manual workflow cannot do:

$ npm version 0.10.6 --no-git-tag-version
npm ERR! Version not changed

That is why v0.10.6 could not be finished through the manual workflow after the CLI failed to publish; the run would have died before reaching the publish step.

The sed only ever covered one file. It rewrote packages/dorval/package.json, so the @dorval/core range in dio and custom was never touched — both still declare "*" today, on every published version:

$ npm view @dorval/dio@0.10.7 dependencies.@dorval/core
*

A wildcard on your own core package means npm i @dorval/dio resolves whatever is newest, including a future incompatible major.

Change

scripts/version.js already did all of this — set every package's version, root included, and re-point internal @dorval/* dependencies. It was dead code: it used require() under "type": "module", so it threw ReferenceError: require is not defined on every run, which also means the yarn version:update script pointing at it has never worked.

Ported it to ESM, changed it to re-point internal dependencies in every package rather than one file via sed, and pointed both publish paths at it:

- "prepareCmd": "for pkg in packages/*; do ... npm version ... done && sed -i.bak 's/...' packages/dorval/package.json && ..."
+ "prepareCmd": "node scripts/version.js ${nextRelease.version} && yarn install --mode=update-lockfile"
- run: |
-     npm version ${{ inputs.version }} --no-git-tag-version
-     for pkg in packages/*; do ... done
+ run: node scripts/version.js ${{ inputs.version }}

The range stays a caret, matching what published packages already carry. dio and custom move from "*" to ^<version> on the next release — called out because it changes their published metadata, and is the point of the fix rather than a side effect.

This is the same consolidation #8 did for publishing: one implementation, both callers.

Verification

$ node scripts/version.js 0.10.8
✅ .: 0.10.7 → 0.10.8
✅ packages/core: 0.10.7 → 0.10.8
✅ packages/dorval: 0.10.7 → 0.10.8 (@dorval/core → ^0.10.8)
✅ packages/dio: 0.10.7 → 0.10.8 (@dorval/core → ^0.10.8)
✅ packages/custom: 0.10.7 → 0.10.8 (@dorval/core → ^0.10.8)
  • Setting the same version twice in a row exits 0 both times, where npm version fails the second time. This is what makes recovery re-runs work.
  • The diff it produces touches only version and @dorval/* dependency lines — no reformatting, package.json files are already 2-space.
  • Both workflow files parse, and the rewritten step resolves to {"name": "Update versions in all packages", "run": "node scripts/version.js ${{ inputs.version }}"}.
  • .releaserc.json is still valid JSON and the surrounding formatting is untouched (one line changed).

Not in this PR

scripts/sync-versions.js is a third partial implementation — it syncs packages from the root version but does not re-point dependencies, and yarn version:sync still points at it. It works, so nothing is broken today, but it is the same drift risk this PR removes elsewhere. Worth deleting separately once no one relies on it.

qwlong added 2 commits August 18, 2026 16:12
The semantic-release path and the manual workflow each carried their own
version-bump logic, and they had drifted apart:

- the manual path never re-pointed the internal @dorval/core dependency,
  so a manually published CLI kept whatever range it had before;
- `npm version <same version>` fails with "Version not changed", which is
  exactly what the manual path needs to do when recovering a release that
  published some packages and not others;
- the semantic-release sed only rewrote packages/dorval, leaving the
  @dorval/core range in dio and custom untouched - both still declare "*".

scripts/version.js already did all of this, but it was dead code: it used
require() under "type": "module", so it threw on every run, and the
`yarn version:update` script pointing at it was broken too. Ported it to
ESM, made it re-point every internal dependency rather than one file, and
pointed both publish paths at it.

Setting a version that is already set is now a no-op rather than an error,
so re-publishing to finish a half-done release works.
…ed files

The v0.10.7 manual publish ran `npm version` at the repo root, which
generated a package-lock.json, and the following `git add .` swept it into
main. turbo then refuses to start:

  x could not resolve workspaces: We detected multiple package managers in
  | your repository: npm, yarn. Please remove one of them.

which fails every CI job at the build step. The same commit also rewrote
yarn.lock, dropping ~470 entries.

Removes the lockfile, restores yarn.lock to its state before that publish,
and ignores package-lock.json so a stray one cannot come back.

The commit step now stages only the files the version step touches instead
of everything in the tree. Combined with replacing `npm version` with
scripts/version.js, which writes nothing but package.json files, neither
half of the original failure can recur.
@qwlong
qwlong merged commit 66bd827 into main Aug 18, 2026
3 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.10.8

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant