Files
git.stella-ops.org/scripts/api-compat-changelog.mjs
master 10212d67c0
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized function calls.
2025-11-20 07:50:52 +02:00

105 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
/**
* Generate a Markdown changelog from two OpenAPI specs using the api-compat-diff tool.
*
* Usage:
* node scripts/api-compat-changelog.mjs <oldSpec> <newSpec> [--title "Release X"] [--fail-on-breaking]
*
* Output is written to stdout.
*/
import { execFileSync } from 'child_process';
import process from 'process';
import path from 'path';
function panic(message) {
console.error(`[api-compat-changelog] ${message}`);
process.exit(1);
}
function parseArgs(argv) {
const args = argv.slice(2);
if (args.length < 2) {
panic('Usage: node scripts/api-compat-changelog.mjs <oldSpec> <newSpec> [--title "Release X"] [--fail-on-breaking]');
}
const opts = {
oldSpec: args[0],
newSpec: args[1],
title: 'API Compatibility Report',
failOnBreaking: false,
};
for (let i = 2; i < args.length; i += 1) {
const arg = args[i];
if (arg === '--title' && args[i + 1]) {
opts.title = args[i + 1];
i += 1;
} else if (arg === '--fail-on-breaking') {
opts.failOnBreaking = true;
}
}
return opts;
}
function runCompatDiff(oldSpec, newSpec) {
const output = execFileSync(
'node',
['scripts/api-compat-diff.mjs', oldSpec, newSpec, '--output', 'json'],
{ encoding: 'utf8' }
);
return JSON.parse(output);
}
function formatList(items, symbol) {
if (!items || items.length === 0) {
return `${symbol} None`;
}
return items.map((item) => `${symbol} ${item}`).join('\n');
}
function renderMarkdown(title, diff, oldSpec, newSpec) {
return [
`# ${title}`,
'',
`- Old spec: \`${path.relative(process.cwd(), oldSpec)}\``,
`- New spec: \`${path.relative(process.cwd(), newSpec)}\``,
'',
'## Summary',
`- Additive operations: ${diff.additive.operations.length}`,
`- Breaking operations: ${diff.breaking.operations.length}`,
`- Additive responses: ${diff.additive.responses.length}`,
`- Breaking responses: ${diff.breaking.responses.length}`,
'',
'## Additive',
'### Operations',
formatList(diff.additive.operations, '-'),
'',
'### Responses',
formatList(diff.additive.responses, '-'),
'',
'## Breaking',
'### Operations',
formatList(diff.breaking.operations, '-'),
'',
'### Responses',
formatList(diff.breaking.responses, '-'),
'',
].join('\n');
}
function main() {
const opts = parseArgs(process.argv);
const diff = runCompatDiff(opts.oldSpec, opts.newSpec);
const markdown = renderMarkdown(opts.title, diff, opts.oldSpec, opts.newSpec);
console.log(markdown);
if (opts.failOnBreaking && (diff.breaking.operations.length > 0 || diff.breaking.responses.length > 0)) {
process.exit(2);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}