Skip to content

Commit 79bedda

Browse files
authored
Merge pull request #308 from metaobjectsdev/fm/mo-docs-site-pub-j8
fix: derive npm publish set instead of hardcoding package list
2 parents 7920a69 + e8849c5 commit 79bedda

9 files changed

Lines changed: 952 additions & 612 deletions

File tree

.github/workflows/publish-npm.yml

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ name: publish-npm
44
# in tier order (a dependency never lands after its dependent). Mirrors
55
# publish-csharp.yml / publish-python.yml: tag-triggered or manual.
66
#
7+
# WHICH packages, and in WHAT ORDER, is NOT decided here — `scripts/publish-set.mjs`
8+
# is the single source of truth, shared with the local `bun run release` path. This
9+
# workflow used to carry its own hardcoded list of 13 directories, which drifted from
10+
# that derivation: @metaobjectsdev/docs-site is a runtime dependency of
11+
# @metaobjectsdev/cli but was never in the list, so a release cut through here would
12+
# have shipped a cli pinning a docs-site version nobody published — an uninstallable
13+
# tarball, discoverable only by an external `npm install`. A list that is derived
14+
# cannot drift from the derivation.
15+
#
716
# This publishes the versions ALREADY COMMITTED in each package.json at the tagged
817
# commit — bump + commit them first (locally: `bun run release <ver>` does the
918
# bump/build/verify/publish in one shot WITH a confirm gate; this workflow is the
@@ -38,6 +47,9 @@ jobs:
3847
bun install --frozen-lockfile
3948
bun run build
4049
50+
- name: Derive + verify the publish set
51+
run: node scripts/publish-set.mjs --check
52+
4153
- name: Pack-verify the cli tarball pins siblings (no workspace:*)
4254
run: |
4355
set -euo pipefail
@@ -60,15 +72,15 @@ jobs:
6072
run: |
6173
set -euo pipefail
6274
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
75+
trap 'rm -f ~/.npmrc' EXIT
6376
pub() { ( cd "$1" && bun publish --access public ) && echo " ✓ $1"; }
64-
# tier 0 → 4 (deps before dependents)
65-
for d in server/typescript/packages/metadata server/typescript/packages/render \
66-
server/typescript/packages/codegen-ts server/typescript/packages/runtime-ts \
67-
server/typescript/packages/migrate-ts server/typescript/packages/sdk \
68-
client/web/packages/runtime-web \
69-
server/typescript/packages/codegen-ts-react server/typescript/packages/codegen-ts-tanstack \
70-
client/web/packages/react client/web/packages/tanstack \
71-
server/typescript/packages/cli server/typescript/packages/ai-runtime ; do
77+
# The set and its tier order (deps before dependents) come from the shared
78+
# derivation, never from a list maintained here. Written to a file first so a
79+
# non-zero exit fails the step instead of yielding a silently short list.
80+
node scripts/publish-set.mjs > "${RUNNER_TEMP}/publish-set.txt"
81+
mapfile -t DIRS < "${RUNNER_TEMP}/publish-set.txt"
82+
[ "${#DIRS[@]}" -gt 0 ] || { echo "::error::derived publish set is empty"; exit 1; }
83+
echo "publishing ${#DIRS[@]} packages in tier order"
84+
for d in "${DIRS[@]}"; do
7285
pub "$d"
7386
done
74-
rm -f ~/.npmrc

AGENTS.md

Lines changed: 592 additions & 0 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,33 @@ anything depends on the version, and deprecation does not free the number. The p
6464
checks every package in the set (in parallel, so it stays fast), and `bun run prerelease`
6565
skips numbers already burned on public npm when choosing an iteration.
6666

67+
### Fixed — `publish-npm.yml` would have published an uninstallable `@metaobjectsdev/cli`
68+
69+
The workflow carried its **own hardcoded list of 13 package directories**;
70+
`scripts/release.mjs` **derived** the same set (every non-private package at the CLI's
71+
version). Two answers to one question, and they had drifted:
72+
`@metaobjectsdev/docs-site` is a runtime `dependencies` entry of `@metaobjectsdev/cli`
73+
(`workspace:*`, rewritten to the concrete version at pack time) and was not in the
74+
workflow's list. A release cut through the workflow would therefore have published a
75+
`cli` pinning `@metaobjectsdev/docs-site@<version>` that nobody published — `npm i
76+
@metaobjectsdev/cli``ETARGET`, discoverable only by an external install. It stayed
77+
latent because the local `bun run release` path publishes all 14, so `docs-site@0.23.2`
78+
is on npm today; **nothing had ever compared the two answers.**
79+
80+
`scripts/publish-set.mjs` is now the single source of truth for which packages ship and
81+
in what order, and both paths read it — the workflow's list is gone, so it cannot drift
82+
from a derivation it no longer has. The derivation also fails loudly rather than
83+
returning a wrong set: a member with no declared tier, a set not closed over its own
84+
sibling runtime deps, or a tier order that would publish a dependency after its
85+
dependent. Wired into the `gates` lane (`publish-set parity`) beside
86+
`check-publish-intent.sh`, which enforces the same rule from the other side.
87+
88+
`TIER_ORDER` omitted `docs-site` too, and that was **not** the harmless oversight it
89+
looked like: `indexOf()` returns `-1`, which does not sort last — it sorts **first**, so
90+
the local release path published `docs-site` ahead of `metadata` and `render`, the two
91+
packages it depends on. The tier is declared now, and an undeclared one is an error
92+
instead of an accidental position.
93+
6794

6895
## [0.23.2] — npm `0.23.2` · PyPI `0.23.2` · NuGet `0.23.2` · Maven `7.23.2`
6996

0 commit comments

Comments
 (0)