Skip to content

fix: build package manifests at pack time so releases actually publish - #35

Merged
pyramation merged 3 commits into
mainfrom
fix/publishing-setup
Aug 24, 2026
Merged

fix: build package manifests at pack time so releases actually publish#35
pyramation merged 3 commits into
mainfrom
fix/publishing-setup

Conversation

@pyramation

Copy link
Copy Markdown
Collaborator

Summary

Releases silently no-op'd: lerna publish reported Package is already published: latex2js@4.2.0 for every package, yet npm is still serving latex2js@4.0.8, @latex2js/utils@4.0.4, etc. Only @mathapedia/css went out.

Cause: every TS package publishes from dist/ (publishConfig.directory), so dist/package.json is the published manifest — but it was only rewritten by an explicitly-invoked tools/write-dist-manifest.mjs. After lerna version bumped the package-root versions, the dist/ manifests still held the previous version, so lerna packed and pushed tarballs for versions that already existed on npm, and npm's 403 surfaced as the misleading "already published" warning. @mathapedia/css was immune precisely because it's the one package that publishes from its root.

Fix: adopt the constructive/dev-utils convention — the manifest is produced by the build, and the build runs at pack time, so it can never be stale:

-"build": "rimraf dist && tsc && copyfiles ... && node ../../tools/write-dist-manifest.mjs"
+"clean":      "makage clean",
+"build":      "makage clean && makage build-ts && makage assets",
+"build:dev":  "makage clean && makage build-ts --dev && makage assets",
+"prepack":    "pnpm run build && makage check-publish"

Notes on the two non-obvious pieces:

  • makage build is deliberately not used. It is clean + build-ts + assets + check-publish, and that last step rejects any workspace: spec in dist/package.json — which is the correct state after an ordinary local build, since lerna rewrites workspace:^ into concrete ranges in the package-root manifest only immediately before packing. Composing the sub-commands keeps pnpm build green, and prepack puts check-publish where the specs are resolved, turning it into a real guard that a tarball can never ship an unresolvable workspace:^ dependency.
  • prepack runs makage clean, which deletes dist/. Safe because lerna 8's publish packs via topoMapPackagesrunProjectsTopologically: a dependent is never packed until its local dependencies finish, so nothing reads a sibling's dist/ while it's being rebuilt.

Package-specific build steps are preserved (latex2js grammar + css copies + bundle css, html5's build-bundle.mjs --dist, vue's component copies). packages/css keeps publishing from its root and loses its prepack, since its build writes into ../latex2js — a side effect that has no business firing during a pack.

Also: tools/check-dist-manifests.mjs asserts, for every directory: "dist" package, that dist/package.json exists, its version matches the package root, and main/module/types resolve inside dist — wired into CI right after pnpm build so this class of bug fails a PR instead of a release. lerna.json gains the registry, package globs, syncWorkspaceLock, allowBranch: main and conventional commits; lerna 8.2.38.2.4; root workspaces now matches pnpm-workspace.yaml (the old website/*, examples/* entries don't exist); PUBLISHING.md rewritten to drop the now-unnecessary manual build step.

The pnpm-lock.yaml diff is large mostly because pnpm 11.15.1 (the declared packageManager) reserializes the file — quote style and blank lines. The semantic changes are lerna 8.2.4, makage@0.6.0 added, copyfiles/rimraf dropped.

Verification

pnpm install, pnpm build (12 targets), pnpm test (36 suites / 589 tests), the manifest guard, and grammar/bundle no-drift checks all pass on Node 22 + pnpm 11.15.1. A lerna publish rehearsal against a dead registry ran every package's prepack — each reported check-publish: dist/package.json OK — no workspace: protocols found — and failed only at the intended ECONNREFUSED. Planting a stale version and a workspace:^ spec in a dist manifest was confirmed to be corrected and rejected respectively.

No versions or tags are touched here. Note for the next release: npm won't allow reusing the already-tagged 4.2.0/4.3.0/4.1.0 versions, so lerna version will need to bump past them.

Link to Devin session: https://app.devin.ai/sessions/e51e8ecb94d241bd8d89e65e642c3e43
Requested by: @pyramation

@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation
pyramation merged commit 061abd6 into main Aug 24, 2026
4 checks 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