105 lines
2.7 KiB
JavaScript
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();
|
|
}
|