From 02e8d9b45148ff34123df8ad16c245fa9b1aa7cd Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sun, 30 Aug 2026 12:13:40 +0000 Subject: [PATCH] fix(release): the version bump skipped a package, and would again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `packages/fleet-core` was added and never listed in MANIFESTS, so the next release would have bumped seven manifests and left it on 0.2.7 — quietly, because the drift check that exists to catch exactly this only looks at what is already listed. It cannot report a package it was never told about. So: list it, and stop the list from being the weak point. The release now discovers every workspace package under apps/ and packages/ and refuses to run when one is missing, alongside the other guards that all fire before anything is written. these workspace packages are not listed in MANIFESTS in scripts/release.mjs: packages/fleet-core/package.json Add them, or the release leaves them behind at an old version. Verified both directions: the guard is silent on the tree as it stands, and refuses when fleet-core is removed from the list again. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01UeSWg1Czsb2Lwxj8vHUnA4 --- scripts/release.mjs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/scripts/release.mjs b/scripts/release.mjs index 5885c15..fdc94c8 100755 --- a/scripts/release.mjs +++ b/scripts/release.mjs @@ -13,7 +13,7 @@ * tree rather than a half-bumped one you have to unpick. */ import { execFileSync } from 'node:child_process' -import { readFileSync, writeFileSync } from 'node:fs' +import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs' import { join, resolve } from 'node:path' const root = resolve(import.meta.dirname, '..') @@ -27,6 +27,7 @@ const MANIFESTS = [ 'packages/schemas/package.json', 'packages/rsync-core/package.json', 'packages/ssh-core/package.json', + 'packages/fleet-core/package.json', 'packages/database/package.json', ] const TAG_SOURCE = 'apps/cli/package.json' @@ -108,6 +109,35 @@ if (newest && compare(next, newest) <= 0) { process.exit(1) } +/** + * Every workspace package has to be listed in MANIFESTS above. + * + * A list kept in step by hand drifts the first time someone adds a package, + * and silently: `packages/fleet-core` was added and missed, and would have + * sat at an old version release after release with nothing failing, because + * the drift check below only looks at what is already listed. Discovering the + * real set and comparing is what turns that into a refusal. + */ +function workspaceManifests() { + const found = [] + for (const group of ['apps', 'packages']) { + for (const entry of readdirSync(join(root, group), { withFileTypes: true })) { + if (!entry.isDirectory()) continue + const relative = `${group}/${entry.name}/package.json` + if (existsSync(join(root, relative))) found.push(relative) + } + } + return found +} + +const unlisted = workspaceManifests().filter((relative) => !MANIFESTS.includes(relative)) +if (unlisted.length > 0) { + console.error('these workspace packages are not listed in MANIFESTS in scripts/release.mjs:') + for (const relative of unlisted) console.error(` ${relative}`) + console.error('\nAdd them, or the release leaves them behind at an old version.') + process.exit(1) +} + // Versions must agree across manifests, because artifact filenames come from // them: a desktop manifest left behind ships DiskPush-0.1.0.AppImage under // tag v0.2.0, and nobody can tell which build they have.