test(release): cover final review blockers

This commit is contained in:
haelyra
2026-08-24 21:14:29 -04:00
parent 75b632c42d
commit 01779a4a2b
6 changed files with 126 additions and 4 deletions
@@ -86,6 +86,15 @@ for (const workflowPath of workflowPaths) {
);
});
test(`${workflowPath} disables generated additions to reviewed release notes`, () => {
const publish = jobBlock(source, 'publish');
assert.match(
publish,
/body_path:\s*release_body\.md[\s\S]{0,160}generate_release_notes:\s*false/
);
assert.doesNotMatch(publish, /generate_release_notes:\s*(?:true|\$\{\{)/);
});
test(`${workflowPath} uploads the one packed tgz as the release artifact`, () => {
const verify = jobBlock(source, 'verify', 'lifecycle');
const packIndex = verify.indexOf('name: Pack npm artifact');
+5
View File
@@ -83,6 +83,11 @@ function runTests() {
assert.deepStrictEqual(kimi.scopes, [
{ id: 'project', targetId: 'kimi', root: './.kimi-code' },
]);
const opencode = getHarnessCapability('opencode');
assert.match(opencode.destinationResolution, /OPENCODE_CONFIG_DIR/);
assert.match(opencode.destinationResolution, /XDG_CONFIG_HOME/);
assert.match(opencode.destinationResolution, /~\/\.config\/opencode/);
})) passed++; else failed++;
if (test('keeps every advanced target attached to its registered root and scope', () => {
@@ -68,6 +68,7 @@ try {
const first = makePlan(root, 'first-module', 'FIRST.md');
const second = makePlan(root, 'second-module', 'SECOND.md');
applyInstallPlan(first);
fs.writeFileSync(first.operations[0].destinationPath, 'user-modified\n');
applyInstallPlan(second);
const state = readInstallState(first.installStatePath);
@@ -79,9 +80,13 @@ try {
const result = uninstallInstalledStates({ projectRoot: root, targets: ['cursor'] });
assert.strictEqual(result.summary.errorCount, 0);
assert.ok(!fs.existsSync(first.operations[0].destinationPath));
assert.strictEqual(
fs.readFileSync(first.operations[0].destinationPath, 'utf8'),
'user-modified\n',
'selective reinstall must not claim modified retained content'
);
assert.ok(!fs.existsSync(second.operations[0].destinationPath));
console.log(' ✓ selective reinstall preserves cumulative ownership and uninstall removes it');
console.log(' ✓ selective reinstall preserves cumulative ownership without claiming user changes');
passed += 1;
} catch (error) {
console.log(` ✗ ${error.message}`);
@@ -90,5 +95,38 @@ try {
fs.rmSync(root, { recursive: true, force: true });
}
const partialRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-partial-non-claude-'));
try {
const copied = makePlan(partialRoot, 'copied-module', 'COPIED.md');
const missing = makePlan(partialRoot, 'missing-module', 'MISSING.md');
fs.rmSync(missing.operations[0].sourcePath);
const partialPlan = {
...copied,
operations: [copied.operations[0], missing.operations[0]],
statePreview: {
...copied.statePreview,
operations: [copied.operations[0], missing.operations[0]],
},
};
assert.throws(() => applyInstallPlan(partialPlan), /ENOENT/);
assert.ok(fs.existsSync(copied.operations[0].destinationPath));
const checkpoint = readInstallState(copied.installStatePath);
assert.ok(checkpoint.operations.some(operation => (
operation.destinationPath === copied.operations[0].destinationPath
)));
const result = uninstallInstalledStates({ projectRoot: partialRoot, targets: ['cursor'] });
assert.strictEqual(result.summary.errorCount, 0);
assert.ok(!fs.existsSync(copied.operations[0].destinationPath));
console.log(' ✓ failed non-Claude install checkpoints managed files for uninstall');
passed += 1;
} catch (error) {
console.log(` ✗ ${error.message}`);
failed += 1;
} finally {
fs.rmSync(partialRoot, { recursive: true, force: true });
}
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);
+31 -2
View File
@@ -629,8 +629,8 @@ function runTests() {
if (test('resolves qwen adapter root and install-state path from home dir', () => {
const adapter = getInstallTargetAdapter('qwen');
const homeDir = '/Users/example';
const root = adapter.resolveRoot({ homeDir });
const statePath = adapter.getInstallStatePath({ homeDir });
const root = adapter.resolveRoot({ homeDir, env: {} });
const statePath = adapter.getInstallStatePath({ homeDir, env: {} });
assert.strictEqual(adapter.id, 'qwen-home');
assert.strictEqual(adapter.target, 'qwen');
@@ -639,6 +639,35 @@ function runTests() {
assert.strictEqual(statePath, path.join(homeDir, '.qwen', 'ecc-install-state.json'));
})) passed++; else failed++;
if (test('opencode adapter honors config overrides in priority order', () => {
const adapter = getInstallTargetAdapter('opencode');
const homeDir = '/Users/example';
const xdgRoot = path.join(homeDir, 'xdg');
const explicitRoot = path.join(homeDir, 'custom-opencode');
assert.strictEqual(
adapter.resolveRoot({
homeDir,
env: {
XDG_CONFIG_HOME: xdgRoot,
OPENCODE_CONFIG_DIR: explicitRoot,
},
}),
explicitRoot
);
assert.strictEqual(
adapter.resolveRoot({ homeDir, env: { XDG_CONFIG_HOME: xdgRoot } }),
path.join(xdgRoot, 'opencode')
);
assert.strictEqual(
adapter.getInstallStatePath({
homeDir,
env: { OPENCODE_CONFIG_DIR: explicitRoot },
}),
path.join(explicitRoot, 'ecc-install-state.json')
);
})) passed++; else failed++;
if (test('qwen adapter supports lookup by target and adapter id', () => {
const byTarget = getInstallTargetAdapter('qwen');
const byId = getInstallTargetAdapter('qwen-home');
+32
View File
@@ -184,6 +184,38 @@ test('opencode reader splits command array and reads environment', () => {
assert.strictEqual(records.find(r => r.name === 'disabledtool').enabled, false);
});
test('opencode reader honors OPENCODE_CONFIG_DIR before XDG_CONFIG_HOME', () => {
const home = tmpHome();
const explicitRoot = path.join(home, 'explicit-opencode');
const xdgRoot = path.join(home, 'xdg');
for (const root of [explicitRoot, path.join(xdgRoot, 'opencode')]) {
fs.mkdirSync(root, { recursive: true });
fs.writeFileSync(path.join(root, 'opencode.json'), JSON.stringify({
mcp: {
[root === explicitRoot ? 'explicit' : 'xdg']: {
type: 'local',
command: ['node'],
},
},
}), 'utf8');
}
const explicit = readOpencodeMcp({
homeDir: home,
env: {
OPENCODE_CONFIG_DIR: explicitRoot,
XDG_CONFIG_HOME: xdgRoot,
},
});
assert.deepStrictEqual(explicit.map(record => record.name), ['explicit']);
const xdg = readOpencodeMcp({
homeDir: home,
env: { XDG_CONFIG_HOME: xdgRoot },
});
assert.deepStrictEqual(xdg.map(record => record.name), ['xdg']);
});
test('collectMcpInventory merges harnesses, detects fragmentation + drift, redacts secrets', () => {
const home = tmpHome();
// claude + opencode agree on github (consistent); codex github uses a
+9
View File
@@ -66,6 +66,11 @@ for (const workflow of [
assert.match(content, /docs\/releases\/\$\{RELEASE_VERSION\}\/release-notes\.md/);
});
test(`${workflow} publishes only the reviewed release notes`, () => {
assert.match(content, /body_path:\s*release_body\.md[\s\S]{0,160}generate_release_notes:\s*false/);
assert.doesNotMatch(content, /generate_release_notes:\s*(?:true|\$\{\{)/);
});
test(`${workflow} publishes new tag versions to npm`, () => {
assert.match(content, /ECC_RELEASE_PACKAGE:\s*\$\{\{ needs\.verify\.outputs\.package_file \}\}/);
assert.match(content, /npm publish "\.\/\$\{ECC_RELEASE_PACKAGE\}" --access public --provenance/);
@@ -85,6 +90,10 @@ for (const workflow of [
});
}
test('reusable release workflow has no generated-notes input', () => {
assert.doesNotMatch(load('.github/workflows/reusable-release.yml'), /generate-notes:/);
});
if (failed > 0) {
console.log(`\nFailed: ${failed}`);
process.exit(1);