mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-22 08:38:08 +02:00
refactor(release): drop release-policy.json runtime dep and next branch
Strips the release-policy.json fallback from release-version.ts so the CLI
reads its version straight from packages/cli/package.json. dev → 0.0.0-private,
installed @kaelio/ktx → the real semver baked into the published package.json.
KtxCliPackageInfo collapses to { name, version, contextPackageName }; /health
no longer depends on version files surviving past a CI run.
Replaces the dual-branch (main + next) semantic-release model with a single-
branch model on main. rcs and stables interleave on the same branch via
{ name: 'main', prerelease: 'rc', channel: 'next' } / ['main']. Drops
@semantic-release/git and @semantic-release/changelog (nothing is committed
back to the repo on any channel) and the workflow's "Prepare next prerelease
branch" step plus the KTX_PRERELEASE_BRANCH plumbing. The git tag plus the
published npm artifact carry the version forward.
Updates docs/release.md, removes the two now-unused devDeps, regenerates
pnpm-lock.yaml. 611/611 @ktx/cli tests, 173/173 script tests, type-check,
biome, knip all clean.
This commit is contained in:
parent
a0d3ddbbc2
commit
66b674f73a
13 changed files with 83 additions and 320 deletions
|
|
@ -137,7 +137,7 @@ describe('admin reindex Commander routing', () => {
|
|||
force: true,
|
||||
json: true,
|
||||
output: 'plain',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
},
|
||||
io.io,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ function stubPackageInfo(): KtxCliPackageInfo {
|
|||
return {
|
||||
name: '@ktx/cli',
|
||||
version: '0.0.0-test',
|
||||
packageVersion: '0.0.0-private',
|
||||
runtimeVersion: '0.0.0-test',
|
||||
contextPackageName: '@ktx/context',
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import type { KtxSlArgs } from './sl.js';
|
|||
import type { KtxSqlArgs } from './sql.js';
|
||||
import { profileMark, profileSpan } from './startup-profile.js';
|
||||
import type { KtxTextIngestArgs } from './text-ingest.js';
|
||||
import { resolveKtxRuntimeVersion } from './release-version.js';
|
||||
import { assertCliVersion } from './release-version.js';
|
||||
|
||||
profileMark('module:cli-runtime');
|
||||
|
||||
|
|
@ -20,8 +20,6 @@ const requirePackageJson = createRequire(import.meta.url);
|
|||
export interface KtxCliPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
packageVersion: string;
|
||||
runtimeVersion: string;
|
||||
contextPackageName: '@ktx/context';
|
||||
}
|
||||
|
||||
|
|
@ -66,16 +64,9 @@ export function packageInfoFromJson(packageJson: unknown): KtxCliPackageInfo {
|
|||
throw new Error('Invalid KTX CLI package metadata');
|
||||
}
|
||||
|
||||
const runtimeVersion = resolveKtxRuntimeVersion({
|
||||
packageName: packageJson.name,
|
||||
packageVersion: packageJson.version,
|
||||
});
|
||||
|
||||
return {
|
||||
name: packageJson.name,
|
||||
version: runtimeVersion,
|
||||
packageVersion: packageJson.version,
|
||||
runtimeVersion,
|
||||
version: assertCliVersion(packageJson.version, `${packageJson.name}/package.json`),
|
||||
contextPackageName: '@ktx/context',
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@ describe('getKtxCliPackageInfo', () => {
|
|||
it('identifies the CLI package and its context dependency', () => {
|
||||
expect(getKtxCliPackageInfo()).toEqual({
|
||||
name: '@ktx/cli',
|
||||
version: '0.1.0-rc.1',
|
||||
packageVersion: '0.0.0-private',
|
||||
runtimeVersion: '0.1.0-rc.1',
|
||||
version: '0.0.0-private',
|
||||
contextPackageName: '@ktx/context',
|
||||
});
|
||||
});
|
||||
|
|
@ -70,8 +68,6 @@ describe('getKtxCliPackageInfo', () => {
|
|||
).toEqual({
|
||||
name: '@kaelio/ktx',
|
||||
version: '0.1.0',
|
||||
packageVersion: '0.1.0',
|
||||
runtimeVersion: '0.1.0',
|
||||
contextPackageName: '@ktx/context',
|
||||
});
|
||||
});
|
||||
|
|
@ -118,7 +114,7 @@ describe('runKtxCli', () => {
|
|||
|
||||
await expect(runKtxCli(['--version'], testIo.io)).resolves.toBe(0);
|
||||
|
||||
expect(testIo.stdout()).toBe('@ktx/cli 0.1.0-rc.1\n');
|
||||
expect(testIo.stdout()).toBe('@ktx/cli 0.0.0-private\n');
|
||||
expect(testIo.stderr()).toBe('');
|
||||
});
|
||||
|
||||
|
|
@ -282,7 +278,7 @@ describe('runKtxCli', () => {
|
|||
expect(unknownIo.stderr()).toContain("unknown option '--query'");
|
||||
});
|
||||
|
||||
it('routes runtime management commands with the release runtime version', async () => {
|
||||
it('routes runtime management commands with the CLI package version', async () => {
|
||||
const runtime = vi.fn(async () => 0);
|
||||
const installIo = makeIo();
|
||||
const startIo = makeIo();
|
||||
|
|
@ -308,7 +304,7 @@ describe('runKtxCli', () => {
|
|||
1,
|
||||
{
|
||||
command: 'install',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
feature: 'local-embeddings',
|
||||
force: true,
|
||||
},
|
||||
|
|
@ -318,7 +314,7 @@ describe('runKtxCli', () => {
|
|||
2,
|
||||
{
|
||||
command: 'start',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
projectDir: expect.any(String),
|
||||
feature: 'local-embeddings',
|
||||
force: true,
|
||||
|
|
@ -329,7 +325,7 @@ describe('runKtxCli', () => {
|
|||
3,
|
||||
{
|
||||
command: 'stop',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
projectDir: expect.any(String),
|
||||
all: false,
|
||||
},
|
||||
|
|
@ -339,7 +335,7 @@ describe('runKtxCli', () => {
|
|||
4,
|
||||
{
|
||||
command: 'stop',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
projectDir: expect.any(String),
|
||||
all: true,
|
||||
},
|
||||
|
|
@ -349,7 +345,7 @@ describe('runKtxCli', () => {
|
|||
5,
|
||||
{
|
||||
command: 'status',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
json: true,
|
||||
},
|
||||
statusIo.io,
|
||||
|
|
@ -422,7 +418,7 @@ describe('runKtxCli', () => {
|
|||
expect.objectContaining({
|
||||
command: 'query',
|
||||
projectDir: tempDir,
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'prompt',
|
||||
query: expect.objectContaining({ measures: ['orders.order_count'], dimensions: [] }),
|
||||
}),
|
||||
|
|
@ -437,7 +433,7 @@ describe('runKtxCli', () => {
|
|||
).resolves.toBe(0);
|
||||
expect(sl).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'auto',
|
||||
}),
|
||||
autoIo.io,
|
||||
|
|
@ -453,7 +449,7 @@ describe('runKtxCli', () => {
|
|||
).resolves.toBe(0);
|
||||
expect(sl).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'never',
|
||||
}),
|
||||
noInputIo.io,
|
||||
|
|
@ -589,7 +585,7 @@ describe('runKtxCli', () => {
|
|||
skipAgents: false,
|
||||
inputMode: 'auto',
|
||||
yes: false,
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
skipLlm: false,
|
||||
skipEmbeddings: false,
|
||||
databaseSchemas: [],
|
||||
|
|
@ -719,7 +715,7 @@ describe('runKtxCli', () => {
|
|||
inputMode: 'disabled',
|
||||
depth: 'fast',
|
||||
queryHistory: 'default',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'never',
|
||||
},
|
||||
testIo.io,
|
||||
|
|
@ -746,7 +742,7 @@ describe('runKtxCli', () => {
|
|||
inputMode: 'auto',
|
||||
depth: 'deep',
|
||||
queryHistory: 'default',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'prompt',
|
||||
},
|
||||
testIo.io,
|
||||
|
|
@ -823,7 +819,7 @@ describe('runKtxCli', () => {
|
|||
json: false,
|
||||
inputMode: 'disabled',
|
||||
queryHistory: 'default',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'never',
|
||||
},
|
||||
testIo.io,
|
||||
|
|
@ -1128,7 +1124,7 @@ describe('runKtxCli', () => {
|
|||
command: 'run',
|
||||
projectDir: tempDir,
|
||||
inputMode: 'disabled',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
||||
llmModel: 'claude-sonnet-4-6',
|
||||
skipLlm: false,
|
||||
|
|
@ -1167,7 +1163,7 @@ describe('runKtxCli', () => {
|
|||
command: 'run',
|
||||
projectDir: tempDir,
|
||||
inputMode: 'disabled',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
llmBackend: 'vertex',
|
||||
vertexProject: 'local-gcp-project',
|
||||
vertexLocation: 'us-east5',
|
||||
|
|
@ -1204,7 +1200,7 @@ describe('runKtxCli', () => {
|
|||
command: 'run',
|
||||
projectDir: tempDir,
|
||||
inputMode: 'disabled',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
llmBackend: 'claude-code',
|
||||
llmModel: 'opus',
|
||||
skipLlm: false,
|
||||
|
|
@ -1312,7 +1308,7 @@ describe('runKtxCli', () => {
|
|||
projectDir: '/tmp/project',
|
||||
inputMode: 'disabled',
|
||||
yes: true,
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
skipLlm: true,
|
||||
skipEmbeddings: true,
|
||||
databaseDrivers: ['postgres'],
|
||||
|
|
@ -1653,7 +1649,7 @@ describe('runKtxCli', () => {
|
|||
queryFile: '/tmp/query.json',
|
||||
execute: false,
|
||||
format: 'json',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'auto',
|
||||
},
|
||||
autoIo.io,
|
||||
|
|
@ -1667,7 +1663,7 @@ describe('runKtxCli', () => {
|
|||
queryFile: '/tmp/query.json',
|
||||
execute: false,
|
||||
format: 'json',
|
||||
cliVersion: '0.1.0-rc.1',
|
||||
cliVersion: '0.0.0-private',
|
||||
runtimeInstallPolicy: 'never',
|
||||
},
|
||||
neverIo.io,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ function stubPackageInfo(): KtxCliPackageInfo {
|
|||
return {
|
||||
name: '@ktx/cli',
|
||||
version: '0.0.0-docs',
|
||||
packageVersion: '0.0.0-private',
|
||||
runtimeVersion: '0.0.0-docs',
|
||||
contextPackageName: '@ktx/context',
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,55 +1,9 @@
|
|||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import { dirname, join, parse } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const semverPattern =
|
||||
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
||||
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function assertReleaseVersion(value: unknown, source: string): string {
|
||||
export function assertCliVersion(value: unknown, source: string): string {
|
||||
if (typeof value !== 'string' || !semverPattern.test(value)) {
|
||||
throw new Error(`Invalid KTX release version in ${source}`);
|
||||
throw new Error(`Invalid KTX CLI version in ${source}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function findReleasePolicyPath(startDir: string): string | undefined {
|
||||
let current = startDir;
|
||||
const root = parse(current).root;
|
||||
while (true) {
|
||||
const candidate = join(current, 'release-policy.json');
|
||||
if (existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
if (current === root) {
|
||||
return undefined;
|
||||
}
|
||||
current = dirname(current);
|
||||
}
|
||||
}
|
||||
|
||||
function readSourceReleaseVersion(startDir = dirname(fileURLToPath(import.meta.url))): string | undefined {
|
||||
const policyPath = findReleasePolicyPath(startDir);
|
||||
if (!policyPath) {
|
||||
return undefined;
|
||||
}
|
||||
const policy = JSON.parse(readFileSync(policyPath, 'utf8')) as unknown;
|
||||
if (!isPlainObject(policy)) {
|
||||
throw new Error(`Invalid KTX release policy: ${policyPath}`);
|
||||
}
|
||||
return assertReleaseVersion(policy.publicNpmPackageVersion, policyPath);
|
||||
}
|
||||
|
||||
export function resolveKtxRuntimeVersion(input: {
|
||||
packageName: string;
|
||||
packageVersion: string;
|
||||
startDir?: string;
|
||||
}): string {
|
||||
if (input.packageName === '@kaelio/ktx') {
|
||||
return assertReleaseVersion(input.packageVersion, `${input.packageName}/package.json`);
|
||||
}
|
||||
return readSourceReleaseVersion(input.startDir) ?? input.packageVersion;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue