mirror of
https://github.com/appium/appium.git
synced 2026-10-17 04:41:24 +08:00
298b09cdbf
* chore: fix some correctness issues * chore: fix more correctness issues * chore: more correctness fixes * chore: remove unnecessary eslint-disable directives * chore: more correctness fixes * chore: apply remaining fixes * chore: minor tuning * chore: explicitly disable rule * chore: handle TS error * chore: tune * chore: tune more * chore: address comments * chore: address some comments * chore: address remaining comments * chore: address previously missed copilot commens
144 lines
5.6 KiB
JavaScript
144 lines
5.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/* eslint-disable no-console */
|
|
// Regression guard: lerna, its conventional-changelog dependency, and the changelog preset
|
|
// package can drift out of sync (e.g. a preset transform that mutates commits, fed to a writer
|
|
// that freezes them) and only fail during an actual release. This replays lerna's own preset
|
|
// resolution + legacy-config normalization (parserOpts/writerOpts -> parser/writer, replicated
|
|
// below since lerna doesn't expose it publicly) and a real changelog write, failing if it throws.
|
|
//
|
|
// If lerna changes its preset normalization, re-sync from its bundle ("normalizePresetConfig").
|
|
|
|
import {readFile} from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
|
|
import {ConventionalChangelog} from 'conventional-changelog';
|
|
import {loadPreset} from 'conventional-changelog-preset-loader';
|
|
|
|
// Ported from lerna, which hardcodes Handlebars for legacy string templates - not an assumption
|
|
// this script adds on top. Not a devDependency of its own: lerna depends on it directly, so it's
|
|
// always present alongside lerna itself; `main()` fails loudly if that ever stops being true.
|
|
function normalizeLegacyWriterOptions(writer, Handlebars) {
|
|
if (!writer || typeof writer !== 'object') {
|
|
return writer;
|
|
}
|
|
const normalized = {...writer};
|
|
const legacyMainTemplate =
|
|
typeof writer.mainTemplate === 'string' ? Handlebars.compile(writer.mainTemplate) : undefined;
|
|
const legacyHeaderPartial =
|
|
typeof writer.headerPartial === 'string' ? Handlebars.compile(writer.headerPartial) : undefined;
|
|
const legacyCommitPartial =
|
|
typeof writer.commitPartial === 'string' ? Handlebars.compile(writer.commitPartial) : undefined;
|
|
const legacyFooterPartial =
|
|
typeof writer.footerPartial === 'string' ? Handlebars.compile(writer.footerPartial) : undefined;
|
|
if (legacyMainTemplate) {
|
|
normalized.template = (context) =>
|
|
legacyMainTemplate(context, {
|
|
data: {root: context},
|
|
partials: {
|
|
header:
|
|
legacyHeaderPartial ||
|
|
((partialContext) => (writer.headerPartial || context.headerPartial)(partialContext)),
|
|
commit:
|
|
legacyCommitPartial ||
|
|
((commit, options) => (writer.commitPartial || context.commitPartial)(options.data.root, commit)),
|
|
footer:
|
|
legacyFooterPartial ||
|
|
((partialContext) => (writer.footerPartial || context.footerPartial)(partialContext)),
|
|
},
|
|
});
|
|
delete normalized.mainTemplate;
|
|
delete normalized.headerPartial;
|
|
delete normalized.commitPartial;
|
|
delete normalized.footerPartial;
|
|
} else {
|
|
if (legacyHeaderPartial) {
|
|
normalized.headerPartial = (context) => legacyHeaderPartial(context);
|
|
}
|
|
if (legacyCommitPartial) {
|
|
normalized.commitPartial = (context, commit) => legacyCommitPartial(commit, {data: {root: context}});
|
|
}
|
|
if (legacyFooterPartial) {
|
|
normalized.footerPartial = (context) => legacyFooterPartial(context);
|
|
}
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
function normalizePresetConfig(config, Handlebars) {
|
|
if (
|
|
config &&
|
|
(config.parser || config.writer || config.whatBump) &&
|
|
!config.parserOpts &&
|
|
!config.writerOpts &&
|
|
!config.conventionalChangelog
|
|
) {
|
|
return {...config, writer: normalizeLegacyWriterOptions(config.writer, Handlebars)};
|
|
}
|
|
if (
|
|
config &&
|
|
(config.parserOpts ||
|
|
config.writerOpts ||
|
|
config.conventionalChangelog ||
|
|
config.recommendedBumpOpts ||
|
|
config.gitRawCommitsOpts)
|
|
) {
|
|
const normalized = {...config};
|
|
const cc = config.conventionalChangelog || config;
|
|
normalized.parser ||= cc.parserOpts || config.parserOpts;
|
|
normalized.writer ||= cc.writerOpts || config.writerOpts;
|
|
normalized.writer = normalizeLegacyWriterOptions(normalized.writer, Handlebars);
|
|
normalized.commits ||= cc.gitRawCommitsOpts || config.gitRawCommitsOpts;
|
|
normalized.whatBump ||= config.recommendedBumpOpts?.whatBump || config.whatBump;
|
|
return normalized;
|
|
}
|
|
return config;
|
|
}
|
|
|
|
async function main() {
|
|
let Handlebars;
|
|
try {
|
|
({default: Handlebars} = await import('handlebars'));
|
|
} catch (err) {
|
|
console.error(
|
|
'Could not resolve "handlebars". This script relies on it being installed alongside ' +
|
|
'lerna (which depends on it directly) rather than declaring its own dependency - if ' +
|
|
'lerna stopped depending on it, add "handlebars" back as a devDependency here.',
|
|
);
|
|
console.error(err);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
const rootDir = path.resolve(import.meta.dirname, '..');
|
|
const lernaConfig = JSON.parse(await readFile(path.join(rootDir, 'lerna.json'), 'utf8'));
|
|
const preset = lernaConfig.changelogPreset ?? 'conventional-changelog-angular';
|
|
|
|
const config = normalizePresetConfig(await loadPreset(preset), Handlebars);
|
|
const generator = new ConventionalChangelog(rootDir);
|
|
generator.config(config);
|
|
generator.context({version: '0.0.0-verify'});
|
|
|
|
try {
|
|
// draining the stream is enough to exercise commit parsing and template rendering
|
|
for await (const chunk of generator.writeStream()) {
|
|
void chunk;
|
|
}
|
|
} catch (err) {
|
|
console.error(`Changelog generation with preset "${preset}" (as configured in lerna.json) threw an error:\n`);
|
|
console.error(err);
|
|
console.error(
|
|
'\nThis usually means the installed versions of "lerna", its "conventional-changelog" ' +
|
|
'dependency, and the changelog preset package are incompatible with each other.',
|
|
);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
console.log(`OK: changelog generation with preset "${preset}" completed without error.`);
|
|
}
|
|
|
|
// Check if this module is being run directly
|
|
if (import.meta.main) {
|
|
void main();
|
|
}
|