test: harden updater 3.4 parallel workflow regressions
This commit is contained in:
@@ -30,18 +30,35 @@ for (const file of [
|
||||
'docs/PRODUCTION_UPDATER_3_4.md',
|
||||
]) assert(existsSync(join(root, file)), `Pflichtdatei fehlt: ${file}`);
|
||||
|
||||
const lifecycle = read('tools/updater-lifecycle-3.4.mjs');
|
||||
for (const marker of ['main-and-production-at-target', 'main-at-target-production-behind', 'matching-open-pr', 'matching-pr-already-merged']) {
|
||||
assert(lifecycle.includes(marker), `Lifecycle-Entscheidung fehlt: ${marker}`);
|
||||
}
|
||||
|
||||
if (existsSync(join(root, 'scripts/updater/Vendoo.Updater.Worker34.ps1'))) {
|
||||
const worker = read('scripts/updater/Vendoo.Updater.Worker34.ps1');
|
||||
for (const marker of [
|
||||
"'3.4.0'", 'production-update-v4', 'payloadHash', 'baseCommit', 'sourceCommit',
|
||||
'Get-ReleaseObservation', 'Wait-RequiredGitHubChecks', 'headRefOid', 'workflow_runs',
|
||||
'force-with-lease', 'main-and-production-at-target', 'completedAt', 'finalPrHeadSha',
|
||||
'force-with-lease', 'completedAt', 'finalPrHeadSha',
|
||||
'check-release-payload-3.4.mjs', '--match-head-commit',
|
||||
]) assert(worker.includes(marker), `Worker-3.4-Vertrag fehlt: ${marker}`);
|
||||
assert(!worker.includes("@('pr','checks'"), 'Updater 3.4 darf gh pr checks --watch nicht mehr verwenden.');
|
||||
assert(!worker.includes("@('push','--force'"), 'Updater 3.4 darf keinen unbedingten Force-Push verwenden.');
|
||||
}
|
||||
|
||||
if (existsSync(join(root, 'scripts/updater/Vendoo.Updater.UI.ps1'))) {
|
||||
const ui = read('scripts/updater/Vendoo.Updater.UI.ps1');
|
||||
assert(ui.includes("$UpdaterVersion = '3.4.0'"), 'Updater-UI meldet nicht Version 3.4.0.');
|
||||
assert(ui.includes("Vendoo.Updater.Worker34.ps1"), 'Updater-UI startet nicht den Worker 3.4.');
|
||||
}
|
||||
if (existsSync(join(root, 'scripts/updater/Vendoo.Updater.Host.ps1'))) {
|
||||
assert(read('scripts/updater/Vendoo.Updater.Host.ps1').includes("$UpdaterVersion = '3.4.0'"), 'Updater-Host meldet nicht Version 3.4.0.');
|
||||
}
|
||||
const manifestSync = read('.github/workflows/sync-release-manifest.yml');
|
||||
assert(manifestSync.includes("'release/*-production-update-v*'"), 'Manifest-Sync ist nicht auf versionsneutrale Releasebranches generalisiert.');
|
||||
assert(!manifestSync.includes('release/1.43.0-production-update-v3'), 'Manifest-Sync enthält weiterhin den alten festen 3.3-Branch.');
|
||||
|
||||
const packageJson = JSON.parse(read('package.json'));
|
||||
for (const name of ['verify:one-click-update', 'verify:updater-ui', 'verify:updater-hotfix']) {
|
||||
assert(packageJson.scripts?.[name] === 'node tools/verify-production-updater-3.4.mjs', `${name} verweist nicht auf Updater 3.4.`);
|
||||
@@ -70,11 +87,43 @@ for (const status of ['QUEUED', 'PENDING', 'IN_PROGRESS']) {
|
||||
assert(['pending', 'waiting-missing'].includes(result.state), `${status} wurde nicht als laufend behandelt.`);
|
||||
}
|
||||
result = classifyChecks({ checks: [...successChecks, { ...successChecks[0], completedAt: '2026-07-10T11:00:00Z', conclusion: 'CANCELLED' }], workflowRuns: successRuns, elapsedSeconds: 120 });
|
||||
assert(result.state === 'success', 'Paralleler älterer abgebrochener Lauf darf neueren Erfolg nicht überstimmen.');
|
||||
assert(result.state === 'success', 'Paralleler älterer abgebrochener Check darf neueren Erfolg nicht überstimmen.');
|
||||
result = classifyChecks({ checks: successChecks.map((x, i) => i ? x : ({ ...x, conclusion: 'FAILURE' })), workflowRuns: successRuns, elapsedSeconds: 120 });
|
||||
assert(result.state === 'failed', 'Fehlgeschlagener Pflichtcheck wurde nicht terminal erkannt.');
|
||||
assert(formatStatusMatrix(result.rows).includes(REQUIRED_CHECKS[0]), 'Timeout-/Fehlermatrix enthält Checknamen nicht.');
|
||||
|
||||
const runBase = successRuns.filter(run => run.name !== REQUIRED_WORKFLOWS[0]);
|
||||
result = classifyChecks({
|
||||
checks: successChecks,
|
||||
workflowRuns: [
|
||||
...runBase,
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'completed', conclusion: 'success', updated_at: '2026-07-10T11:00:00Z' },
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'completed', conclusion: 'failure', updated_at: '2026-07-10T12:00:00Z' },
|
||||
],
|
||||
elapsedSeconds: 120,
|
||||
});
|
||||
assert(result.state === 'failed', 'Ein älterer erfolgreicher Workflow-Run darf einen neueren Fehler nicht verdecken.');
|
||||
result = classifyChecks({
|
||||
checks: successChecks,
|
||||
workflowRuns: [
|
||||
...runBase,
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'completed', conclusion: 'failure', updated_at: '2026-07-10T11:00:00Z' },
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'in_progress', conclusion: null, updated_at: '2026-07-10T12:00:00Z' },
|
||||
],
|
||||
elapsedSeconds: 120,
|
||||
});
|
||||
assert(result.state === 'pending', 'Ein neuer laufender Workflow-Run muss einen älteren Fehler ablösen.');
|
||||
result = classifyChecks({
|
||||
checks: successChecks,
|
||||
workflowRuns: [
|
||||
...runBase,
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'completed', conclusion: 'cancelled', updated_at: '2026-07-10T11:00:00Z' },
|
||||
{ name: REQUIRED_WORKFLOWS[0], status: 'completed', conclusion: 'success', updated_at: '2026-07-10T12:00:00Z' },
|
||||
],
|
||||
elapsedSeconds: 120,
|
||||
});
|
||||
assert(result.state === 'success', 'Ein neuer erfolgreicher Workflow-Run muss einen älteren Abbruch ablösen.');
|
||||
|
||||
let decision = decideReleasePath({ targetVersion: '1.43.0', mainVersion: '1.43.0', productionReady: true, productionVersion: '1.43.0' });
|
||||
assert(decision.action === 'complete', 'Bereits deployte Zielversion muss sofort erfolgreich enden.');
|
||||
decision = decideReleasePath({ targetVersion: '1.43.0', mainVersion: '1.43.0', productionReady: true, productionVersion: '1.42.0' });
|
||||
|
||||
Reference in New Issue
Block a user