Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/cli/scripts/generate-release.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
import { basename, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { assertReleaseMetadata, REPOSITORY, TARGETS } from './release-metadata.js';
import { versionsAligned } from '../../../scripts/workspace-versions.mjs';

const root = fileURLToPath(new URL('../../../', import.meta.url));
const SHA256 = /^[a-f0-9]{64}$/;
Expand Down Expand Up @@ -59,7 +60,7 @@ async function main() {
if (!directory || process.argv.length > 4) throw new Error('Usage: node packages/cli/scripts/generate-release.js <artifact-dir> [output-file]');
const app = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
const cli = JSON.parse(await readFile(join(root, 'packages/cli/package.json'), 'utf8'));
if (app.version !== cli.version || app.dependencies?.[cli.name] !== cli.version) throw new Error('Application and CLI versions must match.');
if (!versionsAligned(app, cli)) throw new Error('Application and CLI versions must match.');
const revision = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim();
const release = await generateRelease({ artifactDir: resolve(directory), version: cli.version, revision });
await writeFile(resolve(output), `${JSON.stringify(release, null, 2)}\n`);
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/scripts/prepack.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { execFileSync } from 'node:child_process';
import { copyFileSync, readFileSync, writeFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { assertReleaseMetadata } from './release-metadata.js';
import { dependencyMatchesVersion } from '../../../scripts/workspace-versions.mjs';
const root = fileURLToPath(new URL('../../../', import.meta.url));
const git = (...args) => execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
if (git('status', '--porcelain', '--untracked-files=normal')) throw new Error('Release packaging requires a clean, committed checkout.');
const app = JSON.parse(readFileSync(new URL('../../../package.json', import.meta.url), 'utf8'));
const cli = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
if (app.dependencies['@earendil-works/pi-coding-agent'] !== cli.dependencies['@earendil-works/pi-coding-agent'] || app.dependencies[cli.name] !== cli.version) {
if (app.dependencies['@earendil-works/pi-coding-agent'] !== cli.dependencies['@earendil-works/pi-coding-agent'] || !dependencyMatchesVersion(app.dependencies[cli.name], cli.version)) {
throw new Error('Align the CLI version and agent SDK versions in both workspace manifests before packing.');
}
if (app.version !== cli.version) throw new Error('Align the application and CLI versions before packing.');
Expand Down
8 changes: 2 additions & 6 deletions scripts/package-standalone.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { tmpdir } from 'node:os';
import { basename, dirname, join, relative, resolve, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import * as tar from 'tar';
import { dependencyMatchesVersion } from './workspace-versions.mjs';

const root = fileURLToPath(new URL('../', import.meta.url));
const output = resolve(root, process.env.TRACESIFT_ARTIFACT_OUTPUT_DIR || 'dist');
Expand Down Expand Up @@ -53,12 +54,7 @@ async function main() {
assert(['darwin', 'linux'].includes(platform) && ['arm64', 'x64'].includes(arch), `Unsupported artifact target: ${platform}-${arch}`);
const app = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
const cli = JSON.parse(await readFile(join(root, 'packages/cli/package.json'), 'utf8'));
const dependency = app.dependencies?.[cli.name];
assert(dependency, `The app must depend on ${cli.name} before packaging.`);
assert(
dependency === cli.version || /^workspace:(\*|\^|~)$/.test(dependency),
'The app and CLI versions must match before packaging.',
);
assert(dependencyMatchesVersion(app.dependencies?.[cli.name], cli.version), 'The app and CLI versions must match before packaging.');
assert(app.version === cli.version, 'The application and CLI package versions must match before packaging.');
assert(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(app.version), 'Invalid application version.');
const revision = process.env.TRACESIFT_RELEASE_REVISION || execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim();
Expand Down
12 changes: 12 additions & 0 deletions scripts/workspace-versions.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* The app depends on the CLI through the workspace protocol, so the manifest
* records `workspace:*` rather than a literal version. npm resolves that to the
* CLI's own version at install time, which `app.version === cli.version` pins.
*/
export function dependencyMatchesVersion(dependency, version) {
return dependency === version || /^workspace:(\*|\^|~)$/.test(dependency);
}

export function versionsAligned(app, cli) {
return app.version === cli.version && dependencyMatchesVersion(app.dependencies?.[cli.name], cli.version);
}
Loading