import fs from 'node:fs/promises'; import path from 'node:path'; const REPOSITORY_CHECK_IDS = new Set(['REL-01', 'REL-02', 'REL-04']); export function commandFilesForSuite(suite) { return (suite.command ?? []) .slice(1) .filter((arg) => typeof arg === 'string' && !arg.startsWith('-')) .map((arg) => arg.replaceAll('\\', '/')); } export function suiteInvalidatedByChanges(suite, changedPaths) { const normalized = new Set((changedPaths ?? []).map((item) => String(item).replaceAll('\\', '/'))); if (normalized.has('release-gate/coverage.mjs')) return true; return commandFilesForSuite(suite).some((filePath) => normalized.has(filePath)); } export function previousScenarioMap(report) { return new Map((report?.scenarios ?? []).map((scenario) => [scenario.id, scenario])); } export function shouldRerunImpactSuite({ suite, selectedIds, previousReport, artifactSha256, commitSha, changedPathsSincePrevious = [], }) { const selectedInSuite = suite.scenarios.filter((scenarioId) => selectedIds.has(scenarioId)); if (selectedInSuite.length === 0) return false; if (!previousReport || previousReport.artifact_sha256 !== artifactSha256) return true; if (suiteInvalidatedByChanges(suite, changedPathsSincePrevious)) return true; if (suite.mode === 'scenarios' && previousReport.commit_sha !== commitSha) return true; const previous = previousScenarioMap(previousReport); return selectedInSuite.some((scenarioId) => previous.get(scenarioId)?.status !== 'passed'); } export function carryForwardScenario(previousScenario) { return { ...previousScenario, evidence: [ ...(previousScenario.evidence ?? []), 'carried_forward=true', ], }; } export async function findImpactResumeReport({ reportRoot, artifactSha256, commitSha, }) { let entries = []; try { entries = await fs.readdir(reportRoot, { withFileTypes: true }); } catch (error) { if (error.code === 'ENOENT') return null; throw error; } const candidates = []; for (const entry of entries) { if (!entry.isDirectory() || entry.name === 'local') continue; const reportPath = path.join(reportRoot, entry.name, 'report.json'); try { const report = JSON.parse(await fs.readFile(reportPath, 'utf8')); if (report?.mode !== 'impact') continue; if (report.artifact_sha256 !== artifactSha256) continue; if (!Array.isArray(report.scenarios)) continue; candidates.push({ report, reportPath, commitSha: report.commit_sha }); } catch { // ignore unreadable reports } } if (candidates.length === 0) return null; const sameCommit = candidates.find((candidate) => candidate.commitSha === commitSha); if (sameCommit) return sameCommit; candidates.sort((left, right) => ( Date.parse(right.report.completed_at ?? 0) - Date.parse(left.report.completed_at ?? 0) )); return candidates[0]; } export { REPOSITORY_CHECK_IDS };