Files
deepseek-harness/native/landlock-run/scripts/bump-release.mjs
kingwl 0a486f09c9 chore: adopt node-addon-landlock-run source as native/ subtree
Bring the node-addon-landlock-run tree (tag v0.0.1, commit 614f7fd) into
native/landlock-run as its source of record: launcher development happens
here, next to the harness consumers, and the standalone repository becomes
the release mirror the tree is exported to for packing and publishing
(procedure in native/README.md). The subtree keeps its own pnpm workspace
and lockfile and is NOT added to the harness workspace: harness installs,
gates, and CI never touch it. The mirror's .github/ stays out of the
subtree; a separate manually-dispatched workflow
(.github/workflows/landlock-run.yml) runs the subtree's CI legs — the
per-architecture native builds, real-kernel launcher proofs, and pack
rehearsal — adapted with working-directory/cache paths.

eslint ignores the subtree like vendor/; AGENTS.md gains the native/
layout line (+5 words on its budget ceiling).
2026-07-14 23:39:58 +08:00

91 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
/**
* Bump every package (workspace root + packages/*) to one version, refresh
* the lockfile, and verify. Usage: `pnpm release:bump <major|minor|patch|x.y.z>`.
*/
import fs from 'node:fs';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { packageDirs, readJson, root } from './repo.mjs';
const bump = process.argv[2];
const releaseTypes = new Set(['major', 'minor', 'patch']);
function writeJson(file, value) {
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
}
function run(command, args) {
const result = spawnSync(command, args, {
cwd: root,
stdio: 'inherit',
env: { ...process.env, CI: 'true' },
});
if (result.error) throw result.error;
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}
function packageFiles() {
return ['package.json', ...packageDirs().map((dir) => path.join(dir, 'package.json'))];
}
function parseVersion(version) {
const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version);
if (!match) {
throw new Error(`increment types need a plain x.y.z current version (current: ${version}) — pass an explicit target version instead`);
}
return match.slice(1).map((part) => Number(part));
}
/** Explicit target versions accept full semver, prereleases included (test publishes). */
const EXPLICIT_VERSION = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/;
function nextVersion(current, release) {
if (EXPLICIT_VERSION.test(release)) return release;
if (!releaseTypes.has(release)) {
throw new Error('Usage: pnpm release:bump <major|minor|patch|x.y.z>');
}
const [major, minor, patch] = parseVersion(current);
if (release === 'major') return `${major + 1}.0.0`;
if (release === 'minor') return `${major}.${minor + 1}.0`;
return `${major}.${minor}.${patch + 1}`;
}
function currentPublishedVersion(files) {
const versions = new Set(
files
.filter((file) => file.startsWith('packages/'))
.map((file) => readJson(path.join(root, file)).version),
);
if (versions.size !== 1) {
throw new Error(`published package versions differ: ${[...versions].join(', ')}`);
}
return [...versions][0];
}
if (!bump) {
console.error('Usage: pnpm release:bump <major|minor|patch|x.y.z>');
process.exit(1);
}
const files = packageFiles();
const targetVersion = nextVersion(currentPublishedVersion(files), bump);
for (const file of files) {
const fullPath = path.join(root, file);
const json = readJson(fullPath);
json.version = targetVersion;
writeJson(fullPath, json);
console.log(`${file}: ${targetVersion}`);
}
run('pnpm', ['install', '--ignore-scripts', '--lockfile-only']);
run('node', ['./scripts/verify-release.mjs']);
console.log(`Release version bumped to ${targetVersion}`);