mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
e8a9abdd8d
Registry scanners diff the repository's tool surface per version string, so a
released number left on main while main keeps changing is indistinguishable
from a republished ("rug-pull") version — two scans of the same version see
two different tool sets (AS-012).
- release:publish now runs release:mark-dev after npm publish, moving
package.json and the synchronized server.json to the next patch with a
-dev prerelease marker.
- release:prepare refuses to publish while the -dev marker is in place, so
a forgotten version bump cannot ship a prerelease as latest.
- Mark the current tree 0.20.11-dev: main had been sitting on the published
0.20.10 while the tool surface kept changing, which is the live finding.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wb8EuoySL26UsdtCtRj5X8
68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
import { spawnSync } from 'node:child_process';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import process from 'node:process';
|
|
|
|
// The version on main must never equal a published version: registry scanners
|
|
// diff the repository's tool surface per version string, so a released number
|
|
// left in place while main keeps moving reads as a rug-pull republish
|
|
// (AS-012). `release:publish` runs this right after `npm publish` to move
|
|
// main to the next patch with a `-dev` prerelease marker; `--check-release-version`
|
|
// is the inverse guard in `release:prepare`, refusing to publish a `-dev`
|
|
// version because the maintainer has not set the release version yet.
|
|
const root = process.cwd();
|
|
const checkReleaseVersion = process.argv.includes('--check-release-version');
|
|
const packagePath = path.join(root, 'package.json');
|
|
|
|
const raw = fs.readFileSync(packagePath, 'utf8');
|
|
const pkg = JSON.parse(raw);
|
|
const version = pkg.version;
|
|
|
|
if (typeof version !== 'string' || version.length === 0) {
|
|
fail('package.json must define version.');
|
|
}
|
|
|
|
if (checkReleaseVersion) {
|
|
if (version.includes('-')) {
|
|
fail(
|
|
`package.json version ${version} is a prerelease marker. Set the release version first ` +
|
|
'(e.g. `npm version patch`), commit, then publish.',
|
|
);
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
if (version.includes('-')) {
|
|
process.stdout.write(`Version ${version} already carries a prerelease marker; nothing to do.\n`);
|
|
process.exit(0);
|
|
}
|
|
|
|
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
if (!match) {
|
|
fail(`Unsupported version format: ${version}`);
|
|
}
|
|
const nextVersion = `${match[1]}.${match[2]}.${Number(match[3]) + 1}-dev`;
|
|
|
|
const versionField = `"version": "${version}"`;
|
|
if (raw.split(versionField).length !== 2) {
|
|
fail(`Expected exactly one ${versionField} in package.json.`);
|
|
}
|
|
fs.writeFileSync(packagePath, raw.replace(versionField, `"version": "${nextVersion}"`));
|
|
|
|
const sync = spawnSync(process.execPath, [path.join(root, 'scripts', 'sync-mcp-metadata.mjs')], {
|
|
stdio: 'inherit',
|
|
});
|
|
if (sync.status !== 0) {
|
|
fail('sync-mcp-metadata failed after the version bump.');
|
|
}
|
|
|
|
process.stdout.write(
|
|
`Marked main as unreleased: ${version} -> ${nextVersion} (package.json + server.json).\n` +
|
|
`Commit and push this so the version on main never equals the published ${version}.\n`,
|
|
);
|
|
|
|
function fail(message) {
|
|
process.stderr.write(`${message}\n`);
|
|
process.exit(1);
|
|
}
|