release candidates: every push to main runs the full CI, the acceptance matrix and the Linux / Windows installer builds in parallel (ci.yml) and records the green result per commit as the draft rc-<sha> (green.json last); a version-only bump commit (proven file by file with the version writers) reuses its parent's CI and matrix and rebuilds only the installers; a v* tag only promotes the candidate (release.yml), fails fast on a red or missing commit; acceptance runs carry a CLI key; tools/release.ts does the whole release on the Mac (bump, CHANGELOG cut, fast gate, push, tag, Mac build + notarize in parallel with Forgejo, cached macOS acceptance, add, verify, publish with one upload of the Mac files, /Applications update, npm commands) and --rehearsal; DMG notarization runs while the app and updater bundle are checked; rehearsal channel on the VDS; docs
This commit is contained in:
parent
89d94d6993
commit
c3b1e8c370
14 changed files with 1438 additions and 526 deletions
|
|
@ -21,6 +21,7 @@ import { FakeAsc, FakePlay } from '../tests/helpers/fake-stores';
|
|||
import { makeAab } from '../tests/build-fixtures';
|
||||
import { ALPHA3 } from '../cli/lib/money';
|
||||
import { CURRENCY } from '../cli/lib/ppp';
|
||||
import { cliKey } from './cli-key';
|
||||
|
||||
const ROOT = resolve(import.meta.dir, '..');
|
||||
const PKG = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')) as { version: string };
|
||||
|
|
@ -492,7 +493,7 @@ async function run(argv: string[]): Promise<void> {
|
|||
const failed = results.filter(r => !r.ok);
|
||||
const out = resolve(arg('--out') ?? join(ROOT, `acceptance-${platform}-${rt.name.replace(/\s+/g, '')}.json`));
|
||||
mkdirSync(dirname(out), { recursive: true });
|
||||
writeFileSync(out, JSON.stringify({ platform, runtime: rt.name, label: rt.label, version: PKG.version, quick, at: new Date().toISOString(), results }, null, 2));
|
||||
writeFileSync(out, JSON.stringify({ platform, runtime: rt.name, label: rt.label, version: PKG.version, cliKey: cliKey(ROOT), quick, at: new Date().toISOString(), results }, null, 2));
|
||||
console.log(`acceptance: ${results.length - failed.length}/${results.length} cells passed in ${Math.round((Date.now() - t0) / 1000)} s -> ${out}`);
|
||||
if (failed.length) {
|
||||
console.log(`acceptance: failed cells keep their folder and output.txt under ${work}`);
|
||||
|
|
@ -504,7 +505,17 @@ async function run(argv: string[]): Promise<void> {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------- report
|
||||
|
||||
interface RunFile { platform: string; runtime: string; label: string; version: string; quick: boolean; at: string; results: Result[] }
|
||||
interface RunFile { platform: string; runtime: string; label: string; version: string; cliKey?: string; quick: boolean; at: string; results: Result[] }
|
||||
|
||||
/** Why a run does not count for this checkout (pure): a quick run, or another version whose CLI code differs. A run
|
||||
* of another version counts when its CLI key (tools/cli-key.ts) is this checkout's: the commits differ only in
|
||||
* version copies and prose (a release's version bump), so the CLI under test is the same code. */
|
||||
export function staleReason(r: Pick<RunFile, 'version' | 'quick' | 'cliKey'>, version: string, key: string): string | null {
|
||||
if (r.quick) return 'a quick run';
|
||||
if (r.version === version) return null;
|
||||
if (r.cliKey && r.cliKey === key) return null;
|
||||
return `version ${r.version}, not ${version}${r.cliKey ? ' (other CLI code)' : ''}`;
|
||||
}
|
||||
|
||||
export function renderReport(runs: RunFile[]): string {
|
||||
const cols = runs.map(r => `${r.platform} · ${r.runtime}`);
|
||||
|
|
@ -548,9 +559,11 @@ function report(argv: string[]): void {
|
|||
runs.sort((a, b) => rank(a) - rank(b));
|
||||
writeFileSync(md, renderReport(runs));
|
||||
const bad = runs.flatMap(r => r.results.filter(x => !x.ok));
|
||||
const stale = runs.filter(r => r.version !== PKG.version || r.quick);
|
||||
const key = cliKey(ROOT);
|
||||
const stale = runs.map(r => ({ r, why: staleReason(r, PKG.version, key) })).filter(x => x.why);
|
||||
console.log(`acceptance report: ${runs.length} runs, ${bad.length} red cells -> ${md}`);
|
||||
for (const r of stale) console.log(` ${r.platform} · ${r.runtime}: ${r.quick ? 'a quick run' : `version ${r.version}, not ${PKG.version}`}`);
|
||||
for (const { r, why } of stale) console.log(` ${r.platform} · ${r.runtime}: ${why}`);
|
||||
for (const r of runs) if (r.version !== PKG.version && !staleReason(r, PKG.version, key)) console.log(` ${r.platform} · ${r.runtime}: run on ${r.version}, same CLI code (key ${key.slice(0, 12)}): counts for ${PKG.version}`);
|
||||
const missing = expect && runs.length < expect ? `${expect - runs.length} of ${expect} runs missing` : '';
|
||||
if (missing) console.log(` ${missing}`);
|
||||
if (argv.includes('--strict') && (bad.length || stale.length || missing)) process.exit(1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue