@ttt-productions/repo-guards 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/backend/functions-build.d.ts +1 -0
- package/dist/modules/backend/functions-build.d.ts.map +1 -1
- package/dist/modules/backend/functions-build.js +24 -0
- package/dist/modules/backend/functions-build.js.map +1 -1
- package/dist/node/tooling/cloud-checks.d.ts +9 -0
- package/dist/node/tooling/cloud-checks.d.ts.map +1 -1
- package/dist/node/tooling/cloud-checks.js +45 -8
- package/dist/node/tooling/cloud-checks.js.map +1 -1
- package/dist/node/tooling/functions-deploy-passes.d.ts +26 -0
- package/dist/node/tooling/functions-deploy-passes.d.ts.map +1 -0
- package/dist/node/tooling/functions-deploy-passes.js +96 -0
- package/dist/node/tooling/functions-deploy-passes.js.map +1 -0
- package/dist/node/tooling/index.d.ts +3 -2
- package/dist/node/tooling/index.d.ts.map +1 -1
- package/dist/node/tooling/index.js +3 -2
- package/dist/node/tooling/index.js.map +1 -1
- package/dist/node/tooling/quiet-gate.d.ts +4 -1
- package/dist/node/tooling/quiet-gate.d.ts.map +1 -1
- package/dist/node/tooling/quiet-gate.js +28 -2
- package/dist/node/tooling/quiet-gate.js.map +1 -1
- package/package.json +1 -1
|
@@ -65,6 +65,7 @@ export declare function exportsOf(file: FileView): {
|
|
|
65
65
|
unreadable: ts.Node[];
|
|
66
66
|
};
|
|
67
67
|
export declare const lightFunctionGuard: GenericGuardDefinition<LightFunctionFacts>;
|
|
68
|
+
export declare const MAX_FUNCTIONS_PER_CODEBASE = 55;
|
|
68
69
|
export interface CodebaseManifestFacts {
|
|
69
70
|
manifest: string;
|
|
70
71
|
entryIndex: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions-build.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"functions-build.d.ts","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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"}
|
|
@@ -527,6 +527,9 @@ export const lightFunctionGuard = {
|
|
|
527
527
|
];
|
|
528
528
|
},
|
|
529
529
|
};
|
|
530
|
+
// Google allows 60 Cloud Functions mutations per minute per project and region, and a deploy
|
|
531
|
+
// changes every function of the codebase it targets; 55 leaves room for that pass's deletions.
|
|
532
|
+
export const MAX_FUNCTIONS_PER_CODEBASE = 55;
|
|
530
533
|
function readJson(context, path, findings) {
|
|
531
534
|
if (!context.reader.exists(path)) {
|
|
532
535
|
findings.push({ file: path, detail: 'the file no longer exists' });
|
|
@@ -659,6 +662,27 @@ export const codebaseManifestGuard = {
|
|
|
659
662
|
return findings;
|
|
660
663
|
},
|
|
661
664
|
},
|
|
665
|
+
{
|
|
666
|
+
title: `no Functions codebase holds more than ${MAX_FUNCTIONS_PER_CODEBASE} functions`,
|
|
667
|
+
description: `Each codebase in ${facts.manifest} deploys as one pass that changes every function it holds, ` +
|
|
668
|
+
`so a codebase over ${MAX_FUNCTIONS_PER_CODEBASE} functions outruns the platform's per-minute ` +
|
|
669
|
+
'mutation budget and its creates are dropped. A codebase that grows past the cap is split.',
|
|
670
|
+
run(context) {
|
|
671
|
+
const findings = [];
|
|
672
|
+
const manifest = readJson(context, facts.manifest, findings);
|
|
673
|
+
if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases)
|
|
674
|
+
return findings;
|
|
675
|
+
for (const [codebase, list] of Object.entries(manifest.codebases)) {
|
|
676
|
+
if (!isList(list) || list.length <= MAX_FUNCTIONS_PER_CODEBASE)
|
|
677
|
+
continue;
|
|
678
|
+
findings.push({
|
|
679
|
+
file: facts.manifest,
|
|
680
|
+
detail: `codebase ${codebase} holds ${list.length} functions; split it so each codebase holds at most ${MAX_FUNCTIONS_PER_CODEBASE}`,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
return findings;
|
|
684
|
+
},
|
|
685
|
+
},
|
|
662
686
|
];
|
|
663
687
|
},
|
|
664
688
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions-build.js","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from 'node:path';\nimport ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { Finding, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../node/reader.js';\nimport type { FileView } from '../../reader/view.js';\nimport { ROOT_ROLES, type Reviewed, type RootRole } from '../../node/layout.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport { namesProblem, reviewedProblems, textProblem, isList } from '../../support/facts.js';\nimport { moduleImports, namesModule } from '../../support/imports.js';\nimport { resolveRelative } from '../../support/paths.js';\nimport { calleePath } from './shared.js';\nimport { REPOSITORY_GUARD_TIMEOUT_MS } from '../../support/timeouts.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nconst CODE_EXTENSION = /\\.(?:[cm]?[jt]sx?)$/;\n\nfunction functionsRoot(context: GuardContext): string {\n const root = context.reader.layout.roots.functions;\n if (!root)\n throw new Error(\n 'repo-guards: a Functions guard runs and the layout declares no functions root',\n );\n return root.path;\n}\n\nconst moduleIdOf = (root: string, file: string) =>\n posix.relative(root, file).replace(CODE_EXTENSION, '');\n\nexport interface RateLimitFacts {\n owner: string;\n presetMap: string;\n surfaceMap: string;\n sharedPresets: string;\n chargeCall: string;\n prefixField: string;\n}\n\nconst isMapAccess = (node: ts.Node, map: string): node is ts.PropertyAccessExpression =>\n ts.isPropertyAccessExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === map;\n\nexport function inlineLimiterConfigs(\n file: FileView,\n facts: Pick<RateLimitFacts, 'presetMap' | 'chargeCall'>,\n): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n forEachNode(sf, (node) => {\n if (ts.isSpreadAssignment(node) && isMapAccess(node.expression, facts.presetMap)) {\n out.push({ node, detail: `spreads ${node.expression.getText(sf)} into a new config` });\n }\n if (\n ts.isCallExpression(node) &&\n calleeName(node) === facts.chargeCall &&\n node.arguments.some((a) => ts.isObjectLiteralExpression(a))\n ) {\n out.push({ node, detail: `passes an inline config to ${facts.chargeCall}` });\n }\n });\n return out;\n}\n\nexport function presetsNamed(file: FileView, presetMap: string): string[] {\n const out = new Set<string>();\n forEachNode(file.sourceFile, (node) => {\n if (isMapAccess(node, presetMap)) out.add(node.name.text);\n });\n return [...out];\n}\n\nexport function limiterDeclarations(owner: FileView, facts: RateLimitFacts) {\n const prefixes: string[] = [];\n const surfaces = new Map<string, string[]>();\n const shared = new Set<string>();\n let presetMapFound = false;\n let surfaceMapFound = false;\n let sharedFound = false;\n const strings = (node: ts.Expression): string[] =>\n ts.isArrayLiteralExpression(node)\n ? node.elements.filter(ts.isStringLiteralLike).map((e) => e.text)\n : [];\n const bare = (e: ts.Expression) => {\n let out = e;\n while (ts.isAsExpression(out) || ts.isSatisfiesExpression(out)) out = out.expression;\n return out;\n };\n forEachNode(owner.sourceFile, (node) => {\n if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name) || !node.initializer) return;\n const init = bare(node.initializer);\n if (node.name.text === facts.presetMap) {\n presetMapFound = true;\n forEachNode(init, (inner) => {\n if (\n ts.isPropertyAssignment(inner) &&\n inner.name.getText() === facts.prefixField &&\n ts.isStringLiteralLike(inner.initializer)\n ) {\n prefixes.push(inner.initializer.text);\n }\n });\n }\n if (node.name.text === facts.sharedPresets) {\n sharedFound = true;\n strings(init).forEach((name) => shared.add(name));\n }\n if (node.name.text === facts.surfaceMap && ts.isObjectLiteralExpression(init)) {\n surfaceMapFound = true;\n for (const p of init.properties) {\n if (\n ts.isPropertyAssignment(p) &&\n (ts.isIdentifier(p.name) || ts.isStringLiteralLike(p.name))\n )\n surfaces.set(p.name.text, strings(bare(p.initializer)));\n }\n }\n });\n return { prefixes, surfaces, shared, presetMapFound, surfaceMapFound, sharedFound };\n}\n\nexport function offendingCharges(\n charges: ReadonlyArray<{ module: string; presets: readonly string[] }>,\n surfaces: ReadonlyMap<string, readonly string[]>,\n shared: ReadonlySet<string>,\n): string[] {\n const listed = new Set([...surfaces.values()].flat());\n const out: string[] = [];\n for (const { module, presets } of charges) {\n for (const preset of presets) {\n const owners = surfaces.get(preset);\n const allowed = owners ? owners.includes(module) : shared.has(preset) && !listed.has(module);\n if (!allowed) out.push(`${module} charges ${preset}`);\n }\n }\n return out;\n}\n\nexport const rateLimitGuard: GenericGuardDefinition<RateLimitFacts> = {\n id: 'rateLimitSurfaces',\n absentWhen: 'the app runs no rate limiter',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of [\n 'owner',\n 'presetMap',\n 'surfaceMap',\n 'sharedPresets',\n 'chargeCall',\n 'prefixField',\n ] as const)\n textProblem(facts?.[key], key, problems);\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'every rate-limit charge names its own preset',\n description:\n `Every limiter charge passes a named ${facts.presetMap} preset — never an inline config to ${facts.chargeCall}, and ` +\n `never a preset spread into a new one — and every preset owns a distinct ${facts.prefixField}. A dedicated preset ` +\n `is charged only by the modules ${facts.surfaceMap} lists for it, and a listed module charges only its own presets; ` +\n `any other module charges only the ${facts.sharedPresets}. Otherwise two surfaces share one sliding window sized ` +\n `for neither. Every module the map lists must exist and charge its preset. Declare a new preset in ${facts.owner}.`,\n run(context) {\n const root = functionsRoot(context);\n const findings: Finding[] = [];\n const charges: Array<{ module: string; presets: string[] }> = [];\n let ownerFile: FileView | undefined;\n for (const file of context.files(FUNCTIONS_CODE)) {\n if (file.path === facts.owner) {\n ownerFile = file;\n continue;\n }\n for (const { node, detail } of inlineLimiterConfigs(file, facts))\n findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n const presets = presetsNamed(file, facts.presetMap);\n if (presets.length) charges.push({ module: moduleIdOf(root, file.path), presets });\n }\n if (!ownerFile)\n return [\n ...findings,\n {\n file: facts.owner,\n detail: 'the limiter owner is gone or outside the Functions tree',\n },\n ];\n const declared = limiterDeclarations(ownerFile, facts);\n if (!declared.presetMapFound || !declared.prefixes.length)\n findings.push({\n file: facts.owner,\n detail: `no ${facts.presetMap} with a ${facts.prefixField} found`,\n });\n if (!declared.surfaceMapFound)\n findings.push({ file: facts.owner, detail: `no ${facts.surfaceMap} object found` });\n if (!declared.sharedFound)\n findings.push({ file: facts.owner, detail: `no ${facts.sharedPresets} list found` });\n const dup = declared.prefixes.filter((p, i) => declared.prefixes.indexOf(p) !== i);\n for (const p of new Set(dup))\n findings.push({\n file: facts.owner,\n detail: `two presets share the ${facts.prefixField} ${p}`,\n });\n for (const offense of offendingCharges(charges, declared.surfaces, declared.shared))\n findings.push({ file: facts.owner, detail: offense });\n const charged = new Map(charges.map((c) => [c.module, c.presets]));\n for (const [preset, modules] of declared.surfaces) {\n for (const module of modules)\n if (!charged.get(module)?.includes(preset))\n findings.push({\n file: facts.owner,\n detail: `${preset} lists ${module}, which does not charge it`,\n });\n }\n return findings;\n },\n },\n ];\n },\n};\n\nexport interface LazyLoaderFacts {\n loader: string;\n roots?: readonly RootRole[];\n otherLoaders?: ReadonlyArray<{ name: string; why: string }>;\n testRunnerConfigs: readonly string[];\n testExceptions: readonly Reviewed[];\n}\n\nconst isDynamicImport = (node: ts.Node): node is ts.CallExpression =>\n ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword;\n\nexport function strayDynamicImports(\n file: FileView,\n names: string | readonly string[],\n): { loaders: number; used: Set<string>; stray: ts.Node[] } {\n const accepted = typeof names === 'string' ? [names] : names;\n const sf = file.sourceFile;\n const stray: ts.Node[] = [];\n const used = new Set<string>();\n let loaders = 0;\n forEachNode(sf, (node) => {\n if (!isDynamicImport(node)) return;\n const name = moduleLevelLoaderName(node, accepted);\n if (name !== null) {\n used.add(name);\n if (name === accepted[0]) loaders += 1;\n } else stray.push(node);\n });\n return { loaders, used, stray };\n}\n\nfunction moduleLevelLoaderName(\n node: ts.CallExpression,\n accepted: readonly string[],\n): string | null {\n if (node.arguments.length !== 1 || !ts.isStringLiteralLike(node.arguments[0]!)) return null;\n let body: ts.Node = node;\n const access = node.parent;\n const projected =\n !!access &&\n ts.isPropertyAccessExpression(access) &&\n access.expression === node &&\n access.name.text === 'then' &&\n ts.isCallExpression(access.parent) &&\n access.parent.expression === access &&\n access.parent.arguments.length === 1;\n if (projected) body = access.parent;\n const arrow = body.parent;\n if (!arrow || !ts.isArrowFunction(arrow) || arrow.body !== body || arrow.parameters.length !== 0)\n return null;\n const call = arrow.parent;\n if (\n !call ||\n !ts.isCallExpression(call) ||\n !ts.isIdentifier(call.expression) ||\n call.arguments[0] !== arrow\n )\n return null;\n const name = call.expression.text;\n if (!accepted.includes(name)) return null;\n const isMain = name === accepted[0];\n if (isMain && (projected || call.arguments.length !== 1)) return null;\n const declaration = call.parent;\n if (!declaration || !ts.isVariableDeclaration(declaration) || declaration.initializer !== call)\n return null;\n if ((declaration.parent.flags & ts.NodeFlags.Const) === 0) return null;\n const statement = declaration.parent.parent;\n if (!statement || !ts.isVariableStatement(statement) || statement.parent !== node.getSourceFile())\n return null;\n return name;\n}\n\nconst COMBINATORS = new Set(['Promise.all', 'Promise.allSettled', 'Promise.race', 'Promise.any']);\n\nexport function overlappingTestImports(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n const visit = (node: ts.Node, inCombinator: boolean) => {\n let combinator = inCombinator;\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'concurrent')\n out.push({ node, detail: `${node.getText(sf)} runs tests concurrently` });\n if (\n ts.isPropertyAssignment(node) &&\n ts.isIdentifier(node.name) &&\n node.name.text === 'concurrent'\n )\n out.push({ node, detail: 'a concurrent test option' });\n if (ts.isCallExpression(node) && COMBINATORS.has(calleePath(node) ?? '')) combinator = true;\n if (inCombinator && isDynamicImport(node))\n out.push({\n node,\n detail: `${node.getText(sf)} overlaps the other imports of a Promise combinator`,\n });\n ts.forEachChild(node, (child) => visit(child, combinator));\n };\n visit(sf, false);\n return out;\n}\n\nexport const lazyLoaderGuard: GenericGuardDefinition<LazyLoaderFacts> = {\n id: 'lazyLoader',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.loader, 'loader', problems);\n if (facts?.roots !== undefined) {\n namesProblem(facts.roots, 'roots', problems);\n if (isList(facts.roots)) {\n for (const root of facts.roots)\n if (!ROOT_ROLES.includes(root))\n problems.push(`roots names ${String(root)}, which is not a root role`);\n }\n }\n if (facts?.otherLoaders !== undefined)\n reviewedProblems(facts.otherLoaders, 'otherLoaders', problems, { key: 'name' });\n namesProblem(facts?.testRunnerConfigs, 'testRunnerConfigs', problems);\n reviewedProblems(facts?.testExceptions, 'testExceptions', problems);\n return problems;\n },\n build(facts) {\n const roots = facts.roots ?? ['functions'];\n const others = (facts.otherLoaders ?? []).map((other) => other.name);\n return [\n {\n title: 'no code can overlap two dynamic imports of one module',\n description:\n `Every dynamic import in production code is a module-level \\`const load… = ${facts.loader}(() => import('…'))\\` ` +\n '(or a static import when laziness buys nothing): its first call starts the one import and every concurrent call ' +\n 'awaits it. A bare `import()` lets two concurrent calls overlap, and the test runner hands the second the REAL ' +\n 'module for a mocked one. Tests never overlap their own imports — no concurrent tests, no concurrent runner ' +\n 'config, no `import()` inside a Promise combinator; a test that does so on purpose is a reviewed exception with ' +\n 'its why, stale once it no longer does.',\n run(context) {\n const findings: Finding[] = [];\n let loaders = 0;\n const used = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: false })) {\n const result = strayDynamicImports(file, [facts.loader, ...others]);\n loaders += result.loaders;\n for (const name of result.used) used.add(name);\n for (const node of result.stray) {\n findings.push({\n file: file.path,\n line: lineOfNode(file, node),\n detail: `${node.getText(file.sourceFile).slice(0, 80)} is not a module-level ${facts.loader} loader`,\n });\n }\n }\n if (!loaders)\n findings.push({\n file: `(${roots.join(', ')})`,\n detail: `no ${facts.loader} loader found, so the guard checks nothing`,\n });\n for (const name of others)\n if (!used.has(name))\n findings.push({\n file: '(otherLoaders)',\n detail: `stale other loader: ${name} wraps no import`,\n });\n const exceptions = new Set(facts.testExceptions.map((e) => e.path));\n const overlapping = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: 'only' })) {\n const hits = overlappingTestImports(file);\n if (hits.length) overlapping.add(file.path);\n if (exceptions.has(file.path)) continue;\n for (const { node, detail } of hits)\n findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n }\n for (const path of exceptions)\n if (!overlapping.has(path))\n findings.push({\n file: path,\n detail: 'stale test exception: the file overlaps no import',\n });\n for (const config of facts.testRunnerConfigs) {\n if (!context.reader.exists(config))\n findings.push({ file: config, detail: 'the test runner config no longer exists' });\n else {\n const view = context.file(config);\n const m = /\\bconcurrent\\s*:/.exec(view.code);\n if (m)\n findings.push({\n file: config,\n line: view.lineOf(m.index),\n detail: 'the runner config makes tests concurrent',\n });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n\nexport interface LightFunctionFacts {\n entryIndex: string;\n lightFunctions: readonly string[];\n heavyPackages: ReadonlyArray<{\n specifier: string;\n lightSubpaths: readonly string[];\n why: string;\n }>;\n heavyFiles: readonly Reviewed[];\n}\n\nexport function staticEdges(file: FileView): string[] {\n return moduleImports(file.sourceFile, ['import', 'export'])\n .filter((site) => site.topLevel && !site.typeOnly)\n .map((site) => site.spec);\n}\n\nexport function resolveModule(\n fromPath: string,\n spec: string,\n known: ReadonlySet<string>,\n): string | null {\n const base = resolveRelative(fromPath, spec)?.path;\n if (base === undefined) return null;\n const stem = base.replace(/\\.[cm]?jsx?$/, '');\n const candidates = [\n base,\n `${stem}.ts`,\n `${stem}.tsx`,\n `${stem}.mts`,\n `${stem}.cts`,\n `${base}.ts`,\n `${base}.tsx`,\n `${base}/index.ts`,\n `${base}/index.tsx`,\n ];\n return candidates.find((c) => known.has(c)) ?? null;\n}\n\nexport function exportsOf(file: FileView): {\n names: Map<string, string | null>;\n unreadable: ts.Node[];\n} {\n const names = new Map<string, string | null>();\n const unreadable: ts.Node[] = [];\n const exported = (node: ts.Node) =>\n ts.canHaveModifiers(node) &&\n !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n for (const stmt of file.sourceFile.statements) {\n if (ts.isExportDeclaration(stmt)) {\n const from =\n stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)\n ? stmt.moduleSpecifier.text\n : null;\n if (stmt.exportClause && ts.isNamedExports(stmt.exportClause))\n for (const e of stmt.exportClause.elements) names.set(e.name.text, from);\n else unreadable.push(stmt);\n } else if (ts.isVariableStatement(stmt) && exported(stmt)) {\n for (const d of stmt.declarationList.declarations)\n if (ts.isIdentifier(d.name)) names.set(d.name.text, null);\n } else if (\n (ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) &&\n exported(stmt) &&\n stmt.name\n ) {\n names.set(stmt.name.text, null);\n }\n }\n return { names, unreadable };\n}\n\nexport const lightFunctionGuard: GenericGuardDefinition<LightFunctionFacts> = {\n id: 'lightFunctions',\n absentWhen: 'the app designates no light functions',\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.entryIndex, 'entryIndex', problems);\n namesProblem(facts?.lightFunctions, 'lightFunctions', problems);\n reviewedProblems(facts?.heavyPackages, 'heavyPackages', problems, { key: 'specifier' });\n for (const p of facts?.heavyPackages ?? [])\n if (!isList(p?.lightSubpaths))\n problems.push(\n `heavy package ${String(p?.specifier)} needs lightSubpaths (declare [] when none)`,\n );\n reviewedProblems(facts?.heavyFiles, 'heavyFiles', problems);\n if (!facts?.heavyPackages?.length && !facts?.heavyFiles?.length)\n problems.push(\n 'neither heavyPackages nor heavyFiles names anything, so the guard checks nothing',\n );\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'light functions never statically reach a heavy module',\n description:\n `The light functions (${facts.lightFunctions.join(', ')}) are hot interactive paths whose static import closure ` +\n \"is small by design: walking the static import graph from each one's module (dynamic `import()` and type-only \" +\n 'imports are not edges) never reaches a heavy package or a heavy Functions module, which would load on every ' +\n 'cold start. Cut the edge — load the heavy module through the module-level lazy loader at its true usage site — ' +\n 'instead of relaxing the list. Every relative import must resolve, every light function must be exported by ' +\n 'the entry module, and every heavy file must exist.',\n timeoutMs: REPOSITORY_GUARD_TIMEOUT_MS,\n run(context) {\n const findings: Finding[] = [];\n const files = context.files(FUNCTIONS_CODE);\n const known = new Set(files.map((f) => f.path));\n const graph = new Map<string, { internal: string[]; external: string[] }>();\n for (const file of files) {\n const internal: string[] = [];\n const external: string[] = [];\n for (const spec of staticEdges(file)) {\n if (!spec.startsWith('.')) external.push(spec);\n else {\n const target = resolveModule(file.path, spec, known);\n if (target) internal.push(target);\n else\n findings.push({\n file: file.path,\n detail: `cannot resolve ${spec}, so the closure through it is unread`,\n });\n }\n }\n graph.set(file.path, { internal, external });\n }\n for (const { path } of facts.heavyFiles)\n if (!known.has(path))\n findings.push({\n file: path,\n detail: 'stale heavy file: it is not a Functions module',\n });\n if (!known.has(facts.entryIndex))\n return [\n ...findings,\n {\n file: facts.entryIndex,\n detail: 'the entry module is gone or outside the Functions tree',\n },\n ];\n const { names } = exportsOf(files.find((f) => f.path === facts.entryIndex)!);\n for (const fn of facts.lightFunctions) {\n const from = names.get(fn);\n const start = from ? resolveModule(facts.entryIndex, from, known) : null;\n if (!start) {\n findings.push({\n file: facts.entryIndex,\n detail: `light function ${fn} is not re-exported from a Functions module`,\n });\n continue;\n }\n const seen = new Set([start]);\n const externals = new Set<string>();\n const stack = [start];\n while (stack.length) {\n const node = graph.get(stack.pop()!);\n if (!node) continue;\n node.external.forEach((e) => externals.add(e));\n for (const next of node.internal) {\n if (seen.has(next)) continue;\n seen.add(next);\n stack.push(next);\n }\n }\n for (const spec of externals) {\n const heavy = facts.heavyPackages.find(\n (p) => namesModule(spec, p.specifier) && !p.lightSubpaths.includes(spec),\n );\n if (heavy)\n findings.push({\n file: start,\n detail: `light function ${fn} statically reaches ${spec}`,\n });\n }\n for (const { path } of facts.heavyFiles)\n if (seen.has(path))\n findings.push({\n file: start,\n detail: `light function ${fn} statically reaches ${path}`,\n });\n }\n return findings;\n },\n },\n ];\n },\n};\n\nexport interface CodebaseManifestFacts {\n manifest: string;\n entryIndex: string;\n deployConfig: string;\n sourceTemplate: string;\n predeployTemplate: readonly string[];\n}\n\nfunction readJson(context: GuardContext, path: string, findings: Finding[]): unknown {\n if (!context.reader.exists(path)) {\n findings.push({ file: path, detail: 'the file no longer exists' });\n return undefined;\n }\n try {\n return JSON.parse(context.file(path).text);\n } catch (err) {\n findings.push({ file: path, detail: `cannot be read as JSON (${(err as Error).message})` });\n return undefined;\n }\n}\n\nexport const codebaseManifestGuard: GenericGuardDefinition<CodebaseManifestFacts> = {\n id: 'codebaseManifest',\n absentWhen: 'the app deploys its Functions as one codebase',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['manifest', 'entryIndex', 'deployConfig', 'sourceTemplate'] as const)\n textProblem(facts?.[key], key, problems);\n if (typeof facts?.sourceTemplate === 'string' && !facts.sourceTemplate.includes('{codebase}'))\n problems.push('sourceTemplate names no {codebase}');\n namesProblem(facts?.predeployTemplate, 'predeployTemplate', problems, { nonEmpty: false });\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'the codebase manifest deploys every function exactly once',\n description:\n `${facts.manifest} maps every export of ${facts.entryIndex} to exactly one Functions codebase — none missing, none ` +\n `stale, none in two — and ${facts.deployConfig} declares exactly the manifest's codebases, each from its source ` +\n 'folder with its predeploy build. A function in no codebase never deploys; one in two deploys twice; a codebase ' +\n 'the deploy config does not declare is never built. The entry module re-exports by name, never `export *`.',\n run(context) {\n const findings: Finding[] = [];\n const manifest = readJson(context, facts.manifest, findings) as\n { codebases?: Record<string, unknown> } | undefined;\n const deploy = readJson(context, facts.deployConfig, findings) as\n { functions?: unknown } | undefined;\n if (!context.reader.exists(facts.entryIndex))\n return [\n ...findings,\n { file: facts.entryIndex, detail: 'the entry module no longer exists' },\n ];\n const index = context.file(facts.entryIndex);\n const { names, unreadable } = exportsOf(index);\n for (const node of unreadable)\n findings.push({\n file: index.path,\n line: lineOfNode(index, node),\n detail: 'export * hides which functions the module deploys',\n });\n if (!names.size)\n findings.push({\n file: index.path,\n detail: 'no export found, so the guard checks nothing',\n });\n if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases) {\n if (manifest) findings.push({ file: facts.manifest, detail: 'no codebases object' });\n return findings;\n }\n const seen = new Map<string, string>();\n for (const [codebase, list] of Object.entries(manifest.codebases)) {\n if (!isList(list)) {\n findings.push({\n file: facts.manifest,\n detail: `codebase ${codebase} is not a list of exports`,\n });\n continue;\n }\n for (const name of list as unknown[]) {\n if (typeof name !== 'string') continue;\n if (seen.has(name))\n findings.push({\n file: facts.manifest,\n detail: `${name} is in two codebases (${seen.get(name)} and ${codebase})`,\n });\n seen.set(name, codebase);\n }\n }\n for (const name of names.keys())\n if (!seen.has(name))\n findings.push({\n file: facts.manifest,\n detail: `${name} is exported but in no codebase`,\n });\n for (const name of seen.keys())\n if (!names.has(name))\n findings.push({\n file: facts.manifest,\n detail: `stale entry ${name}: the entry module does not export it`,\n });\n if (!deploy) return findings;\n const entries = isList(deploy.functions)\n ? (deploy.functions as Array<Record<string, unknown>>)\n : null;\n if (!entries)\n return [\n ...findings,\n { file: facts.deployConfig, detail: 'functions is not a list of codebase entries' },\n ];\n const declared = entries.map((e) => String(e.codebase));\n const codebases = Object.keys(manifest.codebases);\n for (const cb of codebases)\n if (!declared.includes(cb))\n findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not declared` });\n for (const cb of declared)\n if (!codebases.includes(cb))\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb} is not in the manifest`,\n });\n for (const entry of entries) {\n const cb = String(entry.codebase);\n const source = facts.sourceTemplate.split('{codebase}').join(cb);\n if (entry.source !== source)\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb} deploys from ${String(entry.source)}, not ${source}`,\n });\n const predeploy = facts.predeployTemplate.map((t) => t.split('{codebase}').join(cb));\n if (JSON.stringify(entry.predeploy ?? []) !== JSON.stringify(predeploy)) {\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb}'s predeploy is not ${JSON.stringify(predeploy)}`,\n });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"functions-build.js","sourceRoot":"","sources":["../../../src/modules/backend/functions-build.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from 'node:path';\nimport ts from 'typescript';\nimport type { GenericGuardDefinition } from '../../node/suite/config.js';\nimport type { Finding, GuardContext } from '../../guard.js';\nimport type { Scope } from '../../node/reader.js';\nimport type { FileView } from '../../reader/view.js';\nimport { ROOT_ROLES, type Reviewed, type RootRole } from '../../node/layout.js';\nimport { calleeName, forEachNode, lineOfNode } from '../../support/ast.js';\nimport { namesProblem, reviewedProblems, textProblem, isList } from '../../support/facts.js';\nimport { moduleImports, namesModule } from '../../support/imports.js';\nimport { resolveRelative } from '../../support/paths.js';\nimport { calleePath } from './shared.js';\nimport { REPOSITORY_GUARD_TIMEOUT_MS } from '../../support/timeouts.js';\n\nconst FUNCTIONS_CODE: Scope = { roots: ['functions'], kinds: ['code'], tests: false };\n\nconst CODE_EXTENSION = /\\.(?:[cm]?[jt]sx?)$/;\n\nfunction functionsRoot(context: GuardContext): string {\n const root = context.reader.layout.roots.functions;\n if (!root)\n throw new Error(\n 'repo-guards: a Functions guard runs and the layout declares no functions root',\n );\n return root.path;\n}\n\nconst moduleIdOf = (root: string, file: string) =>\n posix.relative(root, file).replace(CODE_EXTENSION, '');\n\nexport interface RateLimitFacts {\n owner: string;\n presetMap: string;\n surfaceMap: string;\n sharedPresets: string;\n chargeCall: string;\n prefixField: string;\n}\n\nconst isMapAccess = (node: ts.Node, map: string): node is ts.PropertyAccessExpression =>\n ts.isPropertyAccessExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === map;\n\nexport function inlineLimiterConfigs(\n file: FileView,\n facts: Pick<RateLimitFacts, 'presetMap' | 'chargeCall'>,\n): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n forEachNode(sf, (node) => {\n if (ts.isSpreadAssignment(node) && isMapAccess(node.expression, facts.presetMap)) {\n out.push({ node, detail: `spreads ${node.expression.getText(sf)} into a new config` });\n }\n if (\n ts.isCallExpression(node) &&\n calleeName(node) === facts.chargeCall &&\n node.arguments.some((a) => ts.isObjectLiteralExpression(a))\n ) {\n out.push({ node, detail: `passes an inline config to ${facts.chargeCall}` });\n }\n });\n return out;\n}\n\nexport function presetsNamed(file: FileView, presetMap: string): string[] {\n const out = new Set<string>();\n forEachNode(file.sourceFile, (node) => {\n if (isMapAccess(node, presetMap)) out.add(node.name.text);\n });\n return [...out];\n}\n\nexport function limiterDeclarations(owner: FileView, facts: RateLimitFacts) {\n const prefixes: string[] = [];\n const surfaces = new Map<string, string[]>();\n const shared = new Set<string>();\n let presetMapFound = false;\n let surfaceMapFound = false;\n let sharedFound = false;\n const strings = (node: ts.Expression): string[] =>\n ts.isArrayLiteralExpression(node)\n ? node.elements.filter(ts.isStringLiteralLike).map((e) => e.text)\n : [];\n const bare = (e: ts.Expression) => {\n let out = e;\n while (ts.isAsExpression(out) || ts.isSatisfiesExpression(out)) out = out.expression;\n return out;\n };\n forEachNode(owner.sourceFile, (node) => {\n if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name) || !node.initializer) return;\n const init = bare(node.initializer);\n if (node.name.text === facts.presetMap) {\n presetMapFound = true;\n forEachNode(init, (inner) => {\n if (\n ts.isPropertyAssignment(inner) &&\n inner.name.getText() === facts.prefixField &&\n ts.isStringLiteralLike(inner.initializer)\n ) {\n prefixes.push(inner.initializer.text);\n }\n });\n }\n if (node.name.text === facts.sharedPresets) {\n sharedFound = true;\n strings(init).forEach((name) => shared.add(name));\n }\n if (node.name.text === facts.surfaceMap && ts.isObjectLiteralExpression(init)) {\n surfaceMapFound = true;\n for (const p of init.properties) {\n if (\n ts.isPropertyAssignment(p) &&\n (ts.isIdentifier(p.name) || ts.isStringLiteralLike(p.name))\n )\n surfaces.set(p.name.text, strings(bare(p.initializer)));\n }\n }\n });\n return { prefixes, surfaces, shared, presetMapFound, surfaceMapFound, sharedFound };\n}\n\nexport function offendingCharges(\n charges: ReadonlyArray<{ module: string; presets: readonly string[] }>,\n surfaces: ReadonlyMap<string, readonly string[]>,\n shared: ReadonlySet<string>,\n): string[] {\n const listed = new Set([...surfaces.values()].flat());\n const out: string[] = [];\n for (const { module, presets } of charges) {\n for (const preset of presets) {\n const owners = surfaces.get(preset);\n const allowed = owners ? owners.includes(module) : shared.has(preset) && !listed.has(module);\n if (!allowed) out.push(`${module} charges ${preset}`);\n }\n }\n return out;\n}\n\nexport const rateLimitGuard: GenericGuardDefinition<RateLimitFacts> = {\n id: 'rateLimitSurfaces',\n absentWhen: 'the app runs no rate limiter',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of [\n 'owner',\n 'presetMap',\n 'surfaceMap',\n 'sharedPresets',\n 'chargeCall',\n 'prefixField',\n ] as const)\n textProblem(facts?.[key], key, problems);\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'every rate-limit charge names its own preset',\n description:\n `Every limiter charge passes a named ${facts.presetMap} preset — never an inline config to ${facts.chargeCall}, and ` +\n `never a preset spread into a new one — and every preset owns a distinct ${facts.prefixField}. A dedicated preset ` +\n `is charged only by the modules ${facts.surfaceMap} lists for it, and a listed module charges only its own presets; ` +\n `any other module charges only the ${facts.sharedPresets}. Otherwise two surfaces share one sliding window sized ` +\n `for neither. Every module the map lists must exist and charge its preset. Declare a new preset in ${facts.owner}.`,\n run(context) {\n const root = functionsRoot(context);\n const findings: Finding[] = [];\n const charges: Array<{ module: string; presets: string[] }> = [];\n let ownerFile: FileView | undefined;\n for (const file of context.files(FUNCTIONS_CODE)) {\n if (file.path === facts.owner) {\n ownerFile = file;\n continue;\n }\n for (const { node, detail } of inlineLimiterConfigs(file, facts))\n findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n const presets = presetsNamed(file, facts.presetMap);\n if (presets.length) charges.push({ module: moduleIdOf(root, file.path), presets });\n }\n if (!ownerFile)\n return [\n ...findings,\n {\n file: facts.owner,\n detail: 'the limiter owner is gone or outside the Functions tree',\n },\n ];\n const declared = limiterDeclarations(ownerFile, facts);\n if (!declared.presetMapFound || !declared.prefixes.length)\n findings.push({\n file: facts.owner,\n detail: `no ${facts.presetMap} with a ${facts.prefixField} found`,\n });\n if (!declared.surfaceMapFound)\n findings.push({ file: facts.owner, detail: `no ${facts.surfaceMap} object found` });\n if (!declared.sharedFound)\n findings.push({ file: facts.owner, detail: `no ${facts.sharedPresets} list found` });\n const dup = declared.prefixes.filter((p, i) => declared.prefixes.indexOf(p) !== i);\n for (const p of new Set(dup))\n findings.push({\n file: facts.owner,\n detail: `two presets share the ${facts.prefixField} ${p}`,\n });\n for (const offense of offendingCharges(charges, declared.surfaces, declared.shared))\n findings.push({ file: facts.owner, detail: offense });\n const charged = new Map(charges.map((c) => [c.module, c.presets]));\n for (const [preset, modules] of declared.surfaces) {\n for (const module of modules)\n if (!charged.get(module)?.includes(preset))\n findings.push({\n file: facts.owner,\n detail: `${preset} lists ${module}, which does not charge it`,\n });\n }\n return findings;\n },\n },\n ];\n },\n};\n\nexport interface LazyLoaderFacts {\n loader: string;\n roots?: readonly RootRole[];\n otherLoaders?: ReadonlyArray<{ name: string; why: string }>;\n testRunnerConfigs: readonly string[];\n testExceptions: readonly Reviewed[];\n}\n\nconst isDynamicImport = (node: ts.Node): node is ts.CallExpression =>\n ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword;\n\nexport function strayDynamicImports(\n file: FileView,\n names: string | readonly string[],\n): { loaders: number; used: Set<string>; stray: ts.Node[] } {\n const accepted = typeof names === 'string' ? [names] : names;\n const sf = file.sourceFile;\n const stray: ts.Node[] = [];\n const used = new Set<string>();\n let loaders = 0;\n forEachNode(sf, (node) => {\n if (!isDynamicImport(node)) return;\n const name = moduleLevelLoaderName(node, accepted);\n if (name !== null) {\n used.add(name);\n if (name === accepted[0]) loaders += 1;\n } else stray.push(node);\n });\n return { loaders, used, stray };\n}\n\nfunction moduleLevelLoaderName(\n node: ts.CallExpression,\n accepted: readonly string[],\n): string | null {\n if (node.arguments.length !== 1 || !ts.isStringLiteralLike(node.arguments[0]!)) return null;\n let body: ts.Node = node;\n const access = node.parent;\n const projected =\n !!access &&\n ts.isPropertyAccessExpression(access) &&\n access.expression === node &&\n access.name.text === 'then' &&\n ts.isCallExpression(access.parent) &&\n access.parent.expression === access &&\n access.parent.arguments.length === 1;\n if (projected) body = access.parent;\n const arrow = body.parent;\n if (!arrow || !ts.isArrowFunction(arrow) || arrow.body !== body || arrow.parameters.length !== 0)\n return null;\n const call = arrow.parent;\n if (\n !call ||\n !ts.isCallExpression(call) ||\n !ts.isIdentifier(call.expression) ||\n call.arguments[0] !== arrow\n )\n return null;\n const name = call.expression.text;\n if (!accepted.includes(name)) return null;\n const isMain = name === accepted[0];\n if (isMain && (projected || call.arguments.length !== 1)) return null;\n const declaration = call.parent;\n if (!declaration || !ts.isVariableDeclaration(declaration) || declaration.initializer !== call)\n return null;\n if ((declaration.parent.flags & ts.NodeFlags.Const) === 0) return null;\n const statement = declaration.parent.parent;\n if (!statement || !ts.isVariableStatement(statement) || statement.parent !== node.getSourceFile())\n return null;\n return name;\n}\n\nconst COMBINATORS = new Set(['Promise.all', 'Promise.allSettled', 'Promise.race', 'Promise.any']);\n\nexport function overlappingTestImports(file: FileView): Array<{ node: ts.Node; detail: string }> {\n const sf = file.sourceFile;\n const out: Array<{ node: ts.Node; detail: string }> = [];\n const visit = (node: ts.Node, inCombinator: boolean) => {\n let combinator = inCombinator;\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'concurrent')\n out.push({ node, detail: `${node.getText(sf)} runs tests concurrently` });\n if (\n ts.isPropertyAssignment(node) &&\n ts.isIdentifier(node.name) &&\n node.name.text === 'concurrent'\n )\n out.push({ node, detail: 'a concurrent test option' });\n if (ts.isCallExpression(node) && COMBINATORS.has(calleePath(node) ?? '')) combinator = true;\n if (inCombinator && isDynamicImport(node))\n out.push({\n node,\n detail: `${node.getText(sf)} overlaps the other imports of a Promise combinator`,\n });\n ts.forEachChild(node, (child) => visit(child, combinator));\n };\n visit(sf, false);\n return out;\n}\n\nexport const lazyLoaderGuard: GenericGuardDefinition<LazyLoaderFacts> = {\n id: 'lazyLoader',\n absentWhen: false,\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.loader, 'loader', problems);\n if (facts?.roots !== undefined) {\n namesProblem(facts.roots, 'roots', problems);\n if (isList(facts.roots)) {\n for (const root of facts.roots)\n if (!ROOT_ROLES.includes(root))\n problems.push(`roots names ${String(root)}, which is not a root role`);\n }\n }\n if (facts?.otherLoaders !== undefined)\n reviewedProblems(facts.otherLoaders, 'otherLoaders', problems, { key: 'name' });\n namesProblem(facts?.testRunnerConfigs, 'testRunnerConfigs', problems);\n reviewedProblems(facts?.testExceptions, 'testExceptions', problems);\n return problems;\n },\n build(facts) {\n const roots = facts.roots ?? ['functions'];\n const others = (facts.otherLoaders ?? []).map((other) => other.name);\n return [\n {\n title: 'no code can overlap two dynamic imports of one module',\n description:\n `Every dynamic import in production code is a module-level \\`const load… = ${facts.loader}(() => import('…'))\\` ` +\n '(or a static import when laziness buys nothing): its first call starts the one import and every concurrent call ' +\n 'awaits it. A bare `import()` lets two concurrent calls overlap, and the test runner hands the second the REAL ' +\n 'module for a mocked one. Tests never overlap their own imports — no concurrent tests, no concurrent runner ' +\n 'config, no `import()` inside a Promise combinator; a test that does so on purpose is a reviewed exception with ' +\n 'its why, stale once it no longer does.',\n run(context) {\n const findings: Finding[] = [];\n let loaders = 0;\n const used = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: false })) {\n const result = strayDynamicImports(file, [facts.loader, ...others]);\n loaders += result.loaders;\n for (const name of result.used) used.add(name);\n for (const node of result.stray) {\n findings.push({\n file: file.path,\n line: lineOfNode(file, node),\n detail: `${node.getText(file.sourceFile).slice(0, 80)} is not a module-level ${facts.loader} loader`,\n });\n }\n }\n if (!loaders)\n findings.push({\n file: `(${roots.join(', ')})`,\n detail: `no ${facts.loader} loader found, so the guard checks nothing`,\n });\n for (const name of others)\n if (!used.has(name))\n findings.push({\n file: '(otherLoaders)',\n detail: `stale other loader: ${name} wraps no import`,\n });\n const exceptions = new Set(facts.testExceptions.map((e) => e.path));\n const overlapping = new Set<string>();\n for (const file of context.files({ roots, kinds: ['code'], tests: 'only' })) {\n const hits = overlappingTestImports(file);\n if (hits.length) overlapping.add(file.path);\n if (exceptions.has(file.path)) continue;\n for (const { node, detail } of hits)\n findings.push({ file: file.path, line: lineOfNode(file, node), detail });\n }\n for (const path of exceptions)\n if (!overlapping.has(path))\n findings.push({\n file: path,\n detail: 'stale test exception: the file overlaps no import',\n });\n for (const config of facts.testRunnerConfigs) {\n if (!context.reader.exists(config))\n findings.push({ file: config, detail: 'the test runner config no longer exists' });\n else {\n const view = context.file(config);\n const m = /\\bconcurrent\\s*:/.exec(view.code);\n if (m)\n findings.push({\n file: config,\n line: view.lineOf(m.index),\n detail: 'the runner config makes tests concurrent',\n });\n }\n }\n return findings;\n },\n },\n ];\n },\n};\n\nexport interface LightFunctionFacts {\n entryIndex: string;\n lightFunctions: readonly string[];\n heavyPackages: ReadonlyArray<{\n specifier: string;\n lightSubpaths: readonly string[];\n why: string;\n }>;\n heavyFiles: readonly Reviewed[];\n}\n\nexport function staticEdges(file: FileView): string[] {\n return moduleImports(file.sourceFile, ['import', 'export'])\n .filter((site) => site.topLevel && !site.typeOnly)\n .map((site) => site.spec);\n}\n\nexport function resolveModule(\n fromPath: string,\n spec: string,\n known: ReadonlySet<string>,\n): string | null {\n const base = resolveRelative(fromPath, spec)?.path;\n if (base === undefined) return null;\n const stem = base.replace(/\\.[cm]?jsx?$/, '');\n const candidates = [\n base,\n `${stem}.ts`,\n `${stem}.tsx`,\n `${stem}.mts`,\n `${stem}.cts`,\n `${base}.ts`,\n `${base}.tsx`,\n `${base}/index.ts`,\n `${base}/index.tsx`,\n ];\n return candidates.find((c) => known.has(c)) ?? null;\n}\n\nexport function exportsOf(file: FileView): {\n names: Map<string, string | null>;\n unreadable: ts.Node[];\n} {\n const names = new Map<string, string | null>();\n const unreadable: ts.Node[] = [];\n const exported = (node: ts.Node) =>\n ts.canHaveModifiers(node) &&\n !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n for (const stmt of file.sourceFile.statements) {\n if (ts.isExportDeclaration(stmt)) {\n const from =\n stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)\n ? stmt.moduleSpecifier.text\n : null;\n if (stmt.exportClause && ts.isNamedExports(stmt.exportClause))\n for (const e of stmt.exportClause.elements) names.set(e.name.text, from);\n else unreadable.push(stmt);\n } else if (ts.isVariableStatement(stmt) && exported(stmt)) {\n for (const d of stmt.declarationList.declarations)\n if (ts.isIdentifier(d.name)) names.set(d.name.text, null);\n } else if (\n (ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) &&\n exported(stmt) &&\n stmt.name\n ) {\n names.set(stmt.name.text, null);\n }\n }\n return { names, unreadable };\n}\n\nexport const lightFunctionGuard: GenericGuardDefinition<LightFunctionFacts> = {\n id: 'lightFunctions',\n absentWhen: 'the app designates no light functions',\n factProblems(facts) {\n const problems: string[] = [];\n textProblem(facts?.entryIndex, 'entryIndex', problems);\n namesProblem(facts?.lightFunctions, 'lightFunctions', problems);\n reviewedProblems(facts?.heavyPackages, 'heavyPackages', problems, { key: 'specifier' });\n for (const p of facts?.heavyPackages ?? [])\n if (!isList(p?.lightSubpaths))\n problems.push(\n `heavy package ${String(p?.specifier)} needs lightSubpaths (declare [] when none)`,\n );\n reviewedProblems(facts?.heavyFiles, 'heavyFiles', problems);\n if (!facts?.heavyPackages?.length && !facts?.heavyFiles?.length)\n problems.push(\n 'neither heavyPackages nor heavyFiles names anything, so the guard checks nothing',\n );\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'light functions never statically reach a heavy module',\n description:\n `The light functions (${facts.lightFunctions.join(', ')}) are hot interactive paths whose static import closure ` +\n \"is small by design: walking the static import graph from each one's module (dynamic `import()` and type-only \" +\n 'imports are not edges) never reaches a heavy package or a heavy Functions module, which would load on every ' +\n 'cold start. Cut the edge — load the heavy module through the module-level lazy loader at its true usage site — ' +\n 'instead of relaxing the list. Every relative import must resolve, every light function must be exported by ' +\n 'the entry module, and every heavy file must exist.',\n timeoutMs: REPOSITORY_GUARD_TIMEOUT_MS,\n run(context) {\n const findings: Finding[] = [];\n const files = context.files(FUNCTIONS_CODE);\n const known = new Set(files.map((f) => f.path));\n const graph = new Map<string, { internal: string[]; external: string[] }>();\n for (const file of files) {\n const internal: string[] = [];\n const external: string[] = [];\n for (const spec of staticEdges(file)) {\n if (!spec.startsWith('.')) external.push(spec);\n else {\n const target = resolveModule(file.path, spec, known);\n if (target) internal.push(target);\n else\n findings.push({\n file: file.path,\n detail: `cannot resolve ${spec}, so the closure through it is unread`,\n });\n }\n }\n graph.set(file.path, { internal, external });\n }\n for (const { path } of facts.heavyFiles)\n if (!known.has(path))\n findings.push({\n file: path,\n detail: 'stale heavy file: it is not a Functions module',\n });\n if (!known.has(facts.entryIndex))\n return [\n ...findings,\n {\n file: facts.entryIndex,\n detail: 'the entry module is gone or outside the Functions tree',\n },\n ];\n const { names } = exportsOf(files.find((f) => f.path === facts.entryIndex)!);\n for (const fn of facts.lightFunctions) {\n const from = names.get(fn);\n const start = from ? resolveModule(facts.entryIndex, from, known) : null;\n if (!start) {\n findings.push({\n file: facts.entryIndex,\n detail: `light function ${fn} is not re-exported from a Functions module`,\n });\n continue;\n }\n const seen = new Set([start]);\n const externals = new Set<string>();\n const stack = [start];\n while (stack.length) {\n const node = graph.get(stack.pop()!);\n if (!node) continue;\n node.external.forEach((e) => externals.add(e));\n for (const next of node.internal) {\n if (seen.has(next)) continue;\n seen.add(next);\n stack.push(next);\n }\n }\n for (const spec of externals) {\n const heavy = facts.heavyPackages.find(\n (p) => namesModule(spec, p.specifier) && !p.lightSubpaths.includes(spec),\n );\n if (heavy)\n findings.push({\n file: start,\n detail: `light function ${fn} statically reaches ${spec}`,\n });\n }\n for (const { path } of facts.heavyFiles)\n if (seen.has(path))\n findings.push({\n file: start,\n detail: `light function ${fn} statically reaches ${path}`,\n });\n }\n return findings;\n },\n },\n ];\n },\n};\n\n// Google allows 60 Cloud Functions mutations per minute per project and region, and a deploy\n// changes every function of the codebase it targets; 55 leaves room for that pass's deletions.\nexport const MAX_FUNCTIONS_PER_CODEBASE = 55;\n\nexport interface CodebaseManifestFacts {\n manifest: string;\n entryIndex: string;\n deployConfig: string;\n sourceTemplate: string;\n predeployTemplate: readonly string[];\n}\n\nfunction readJson(context: GuardContext, path: string, findings: Finding[]): unknown {\n if (!context.reader.exists(path)) {\n findings.push({ file: path, detail: 'the file no longer exists' });\n return undefined;\n }\n try {\n return JSON.parse(context.file(path).text);\n } catch (err) {\n findings.push({ file: path, detail: `cannot be read as JSON (${(err as Error).message})` });\n return undefined;\n }\n}\n\nexport const codebaseManifestGuard: GenericGuardDefinition<CodebaseManifestFacts> = {\n id: 'codebaseManifest',\n absentWhen: 'the app deploys its Functions as one codebase',\n factProblems(facts) {\n const problems: string[] = [];\n for (const key of ['manifest', 'entryIndex', 'deployConfig', 'sourceTemplate'] as const)\n textProblem(facts?.[key], key, problems);\n if (typeof facts?.sourceTemplate === 'string' && !facts.sourceTemplate.includes('{codebase}'))\n problems.push('sourceTemplate names no {codebase}');\n namesProblem(facts?.predeployTemplate, 'predeployTemplate', problems, { nonEmpty: false });\n return problems;\n },\n build(facts) {\n return [\n {\n title: 'the codebase manifest deploys every function exactly once',\n description:\n `${facts.manifest} maps every export of ${facts.entryIndex} to exactly one Functions codebase — none missing, none ` +\n `stale, none in two — and ${facts.deployConfig} declares exactly the manifest's codebases, each from its source ` +\n 'folder with its predeploy build. A function in no codebase never deploys; one in two deploys twice; a codebase ' +\n 'the deploy config does not declare is never built. The entry module re-exports by name, never `export *`.',\n run(context) {\n const findings: Finding[] = [];\n const manifest = readJson(context, facts.manifest, findings) as\n { codebases?: Record<string, unknown> } | undefined;\n const deploy = readJson(context, facts.deployConfig, findings) as\n { functions?: unknown } | undefined;\n if (!context.reader.exists(facts.entryIndex))\n return [\n ...findings,\n { file: facts.entryIndex, detail: 'the entry module no longer exists' },\n ];\n const index = context.file(facts.entryIndex);\n const { names, unreadable } = exportsOf(index);\n for (const node of unreadable)\n findings.push({\n file: index.path,\n line: lineOfNode(index, node),\n detail: 'export * hides which functions the module deploys',\n });\n if (!names.size)\n findings.push({\n file: index.path,\n detail: 'no export found, so the guard checks nothing',\n });\n if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases) {\n if (manifest) findings.push({ file: facts.manifest, detail: 'no codebases object' });\n return findings;\n }\n const seen = new Map<string, string>();\n for (const [codebase, list] of Object.entries(manifest.codebases)) {\n if (!isList(list)) {\n findings.push({\n file: facts.manifest,\n detail: `codebase ${codebase} is not a list of exports`,\n });\n continue;\n }\n for (const name of list as unknown[]) {\n if (typeof name !== 'string') continue;\n if (seen.has(name))\n findings.push({\n file: facts.manifest,\n detail: `${name} is in two codebases (${seen.get(name)} and ${codebase})`,\n });\n seen.set(name, codebase);\n }\n }\n for (const name of names.keys())\n if (!seen.has(name))\n findings.push({\n file: facts.manifest,\n detail: `${name} is exported but in no codebase`,\n });\n for (const name of seen.keys())\n if (!names.has(name))\n findings.push({\n file: facts.manifest,\n detail: `stale entry ${name}: the entry module does not export it`,\n });\n if (!deploy) return findings;\n const entries = isList(deploy.functions)\n ? (deploy.functions as Array<Record<string, unknown>>)\n : null;\n if (!entries)\n return [\n ...findings,\n { file: facts.deployConfig, detail: 'functions is not a list of codebase entries' },\n ];\n const declared = entries.map((e) => String(e.codebase));\n const codebases = Object.keys(manifest.codebases);\n for (const cb of codebases)\n if (!declared.includes(cb))\n findings.push({ file: facts.deployConfig, detail: `codebase ${cb} is not declared` });\n for (const cb of declared)\n if (!codebases.includes(cb))\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb} is not in the manifest`,\n });\n for (const entry of entries) {\n const cb = String(entry.codebase);\n const source = facts.sourceTemplate.split('{codebase}').join(cb);\n if (entry.source !== source)\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb} deploys from ${String(entry.source)}, not ${source}`,\n });\n const predeploy = facts.predeployTemplate.map((t) => t.split('{codebase}').join(cb));\n if (JSON.stringify(entry.predeploy ?? []) !== JSON.stringify(predeploy)) {\n findings.push({\n file: facts.deployConfig,\n detail: `codebase ${cb}'s predeploy is not ${JSON.stringify(predeploy)}`,\n });\n }\n }\n return findings;\n },\n },\n {\n title: `no Functions codebase holds more than ${MAX_FUNCTIONS_PER_CODEBASE} functions`,\n description:\n `Each codebase in ${facts.manifest} deploys as one pass that changes every function it holds, ` +\n `so a codebase over ${MAX_FUNCTIONS_PER_CODEBASE} functions outruns the platform's per-minute ` +\n 'mutation budget and its creates are dropped. A codebase that grows past the cap is split.',\n run(context) {\n const findings: Finding[] = [];\n const manifest = readJson(context, facts.manifest, findings) as\n { codebases?: Record<string, unknown> } | undefined;\n if (!manifest || typeof manifest.codebases !== 'object' || !manifest.codebases)\n return findings;\n for (const [codebase, list] of Object.entries(manifest.codebases)) {\n if (!isList(list) || list.length <= MAX_FUNCTIONS_PER_CODEBASE) continue;\n findings.push({\n file: facts.manifest,\n detail: `codebase ${codebase} holds ${list.length} functions; split it so each codebase holds at most ${MAX_FUNCTIONS_PER_CODEBASE}`,\n });\n }\n return findings;\n },\n },\n ];\n },\n};\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ExpectedCodebase } from './deployed-functions.js';
|
|
2
|
+
import { type FunctionsManifest } from './functions-deploy-passes.js';
|
|
2
3
|
export declare function applyStorageCors(repoRoot: string, projectId: string): void;
|
|
3
4
|
export declare function checkCallableInvokers({ repoRoot, region, projectId: requested, extraPublicServices, }: {
|
|
4
5
|
repoRoot: string;
|
|
@@ -12,4 +13,12 @@ export declare function checkDeployedFunctions({ repoRoot, region, projectId: re
|
|
|
12
13
|
projectId: string | undefined;
|
|
13
14
|
expected: () => readonly ExpectedCodebase[];
|
|
14
15
|
}): void;
|
|
16
|
+
export declare function deployFunctionsInPasses({ repoRoot, region, projectId: requested, targets, manifest, nonFunctionTargets, }: {
|
|
17
|
+
repoRoot: string;
|
|
18
|
+
region: string;
|
|
19
|
+
projectId: string | undefined;
|
|
20
|
+
targets: string | undefined;
|
|
21
|
+
manifest: () => FunctionsManifest;
|
|
22
|
+
nonFunctionTargets: readonly string[];
|
|
23
|
+
}): void;
|
|
15
24
|
//# sourceMappingURL=cloud-checks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-checks.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/cloud-checks.ts"],"names":[],"mappings":"AASA,OAAO,
|
|
1
|
+
{"version":3,"file":"cloud-checks.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/cloud-checks.ts"],"names":[],"mappings":"AASA,OAAO,EAIL,KAAK,gBAAgB,EAEtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAsDhG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA0B1E;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,MAAM,EACN,SAAS,EAAE,SAAS,EACpB,mBAAwB,GACzB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,GAAG,IAAI,CAwEP;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,MAAM,EACN,SAAS,EAAE,SAAS,EACpB,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,MAAM,SAAS,gBAAgB,EAAE,CAAC;CAC7C,GAAG,IAAI,CAgDP;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,MAAM,EACN,SAAS,EAAE,SAAS,EACpB,OAAO,EACP,QAAQ,EACR,kBAAkB,GACnB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,iBAAiB,CAAC;IAClC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC,GAAG,IAAI,CAsCP"}
|
|
@@ -2,7 +2,8 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { CALLABLE_LABEL_FILTER, assessInvokers, lines, } from './callable-invokers.js';
|
|
5
|
-
import { compareDeployedFunctions, parseLiveFunctions, } from './deployed-functions.js';
|
|
5
|
+
import { compareDeployedFunctions, parseLiveFunctions, targetedCodebases, } from './deployed-functions.js';
|
|
6
|
+
import { runFunctionsDeployPasses } from './functions-deploy-passes.js';
|
|
6
7
|
import { assertSafeCors, defaultStorageBucket, normalizeCors, readBucketCors, } from './storage-cors.js';
|
|
7
8
|
import { readFirebaseProjects } from './firebase-projects-file.js';
|
|
8
9
|
function gcloud(args, cwd) {
|
|
@@ -13,6 +14,15 @@ function gcloud(args, cwd) {
|
|
|
13
14
|
maxBuffer: 64 * 1024 * 1024,
|
|
14
15
|
});
|
|
15
16
|
}
|
|
17
|
+
function listLiveFunctions(projectId, region) {
|
|
18
|
+
return parseLiveFunctions(JSON.parse(gcloud([
|
|
19
|
+
'functions',
|
|
20
|
+
'list',
|
|
21
|
+
`--project=${projectId}`,
|
|
22
|
+
`--regions=${region}`,
|
|
23
|
+
'--format=json',
|
|
24
|
+
]) || '[]'));
|
|
25
|
+
}
|
|
16
26
|
function firstLine(error) {
|
|
17
27
|
const e = error;
|
|
18
28
|
return String(e?.stderr || e?.message || error).split('\n')[0];
|
|
@@ -114,13 +124,7 @@ export function checkDeployedFunctions({ repoRoot, region, projectId: requested,
|
|
|
114
124
|
}
|
|
115
125
|
let live;
|
|
116
126
|
try {
|
|
117
|
-
live =
|
|
118
|
-
'functions',
|
|
119
|
-
'list',
|
|
120
|
-
`--project=${projectId}`,
|
|
121
|
-
`--regions=${region}`,
|
|
122
|
-
'--format=json',
|
|
123
|
-
]) || '[]'));
|
|
127
|
+
live = listLiveFunctions(projectId, region);
|
|
124
128
|
}
|
|
125
129
|
catch (error) {
|
|
126
130
|
console.error(`::error::[deployed-functions] Could not list the functions on ${projectId} (${firstLine(error)}). The guard fails CLOSED.`);
|
|
@@ -143,4 +147,37 @@ export function checkDeployedFunctions({ repoRoot, region, projectId: requested,
|
|
|
143
147
|
const count = groups.reduce((n, g) => n + g.names.length, 0);
|
|
144
148
|
console.log(`[deployed-functions] OK — ${count} functions on ${projectId}: every expected function is live and ACTIVE, and nothing else is.`);
|
|
145
149
|
}
|
|
150
|
+
export function deployFunctionsInPasses({ repoRoot, region, projectId: requested, targets, manifest, nonFunctionTargets, }) {
|
|
151
|
+
const projectId = knownProject(repoRoot, requested, 'deploy-functions');
|
|
152
|
+
let codebases;
|
|
153
|
+
let selected;
|
|
154
|
+
try {
|
|
155
|
+
codebases = manifest();
|
|
156
|
+
selected = targetedCodebases(targets ?? '', Object.keys(codebases));
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error(`::error::[deploy-functions] Could not read the deploy targets (${firstLine(error)}).`);
|
|
160
|
+
process.exit(2);
|
|
161
|
+
}
|
|
162
|
+
const pauseLock = new Int32Array(new SharedArrayBuffer(4));
|
|
163
|
+
const ok = runFunctionsDeployPasses({ targets: selected, manifest: codebases, nonFunctionTargets }, {
|
|
164
|
+
listLive: () => listLiveFunctions(projectId, region),
|
|
165
|
+
deploy: (only) => {
|
|
166
|
+
try {
|
|
167
|
+
execFileSync('firebase', ['deploy', '--only', only, '--project', projectId, '--non-interactive', '--force'], { cwd: repoRoot, stdio: 'inherit' });
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
pause: (ms) => {
|
|
175
|
+
Atomics.wait(pauseLock, 0, 0, ms);
|
|
176
|
+
},
|
|
177
|
+
log: (line) => console.log(line),
|
|
178
|
+
error: (line) => console.error(`::error::${line}`),
|
|
179
|
+
});
|
|
180
|
+
if (!ok)
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
146
183
|
//# sourceMappingURL=cloud-checks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-checks.js","sourceRoot":"","sources":["../../../src/node/tooling/cloud-checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport {\n CALLABLE_LABEL_FILTER,\n assessInvokers,\n lines,\n type IamPolicy,\n} from './callable-invokers.js';\nimport {\n compareDeployedFunctions,\n parseLiveFunctions,\n type ExpectedCodebase,\n} from './deployed-functions.js';\nimport {\n assertSafeCors,\n defaultStorageBucket,\n normalizeCors,\n readBucketCors,\n} from './storage-cors.js';\nimport { readFirebaseProjects } from './firebase-projects-file.js';\n\nfunction gcloud(args: readonly string[], cwd?: string): string {\n return execFileSync('gcloud', args, {\n cwd,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n maxBuffer: 64 * 1024 * 1024,\n });\n}\n\nfunction firstLine(error: unknown): string {\n const e = error as { stderr?: unknown; message?: unknown } | null;\n return String(e?.stderr || e?.message || error).split('\\n')[0]!;\n}\n\nfunction knownProject(repoRoot: string, projectId: string | undefined, tag: string): string {\n const projects = readFirebaseProjects(repoRoot);\n const known = [projects.dev, projects.prod];\n if (!projectId) {\n console.error(`usage: <script> <projectId> (one of: ${known.join(', ')})`);\n process.exit(2);\n }\n if (!known.includes(projectId)) {\n console.error(\n `::error::[${tag}] Unknown project \"${projectId}\" — expected one of: ${known.join(', ')}.`,\n );\n process.exit(2);\n }\n return projectId;\n}\n\nexport function applyStorageCors(repoRoot: string, projectId: string): void {\n const projects = readFirebaseProjects(repoRoot);\n if (projectId !== projects.dev && projectId !== projects.prod) {\n throw new Error(`unsupported project: ${projectId}`);\n }\n const expected: unknown = JSON.parse(readFileSync(path.join(repoRoot, 'cors.json'), 'utf8'));\n assertSafeCors(expected);\n const bucketUri = `gs://${defaultStorageBucket(projectId)}`;\n gcloud(\n ['storage', 'buckets', 'update', bucketUri, '--cors-file=cors.json', `--project=${projectId}`],\n repoRoot,\n );\n const actual = readBucketCors(\n JSON.parse(\n gcloud(\n ['storage', 'buckets', 'describe', bucketUri, '--format=json', `--project=${projectId}`],\n repoRoot,\n ),\n ),\n );\n if (JSON.stringify(normalizeCors(actual)) !== JSON.stringify(normalizeCors(expected))) {\n throw new Error(\n `Storage CORS verification failed for ${bucketUri}: applied ${JSON.stringify(actual)}, expected ${JSON.stringify(expected)}`,\n );\n }\n console.log(`Storage CORS applied and verified for ${bucketUri}`);\n}\n\nexport function checkCallableInvokers({\n repoRoot,\n region,\n projectId: requested,\n extraPublicServices = [],\n}: {\n repoRoot: string;\n region: string;\n projectId: string | undefined;\n extraPublicServices?: readonly string[];\n}): void {\n const projectId = knownProject(repoRoot, requested, 'invoker-guard');\n let labelled: string[];\n try {\n labelled = lines(\n gcloud([\n 'run',\n 'services',\n 'list',\n `--project=${projectId}`,\n `--region=${region}`,\n `--filter=${CALLABLE_LABEL_FILTER}`,\n '--format=value(metadata.name)',\n ]),\n );\n } catch (error) {\n console.error(\n `::error::[invoker-guard] Could not list Cloud Run services on ${projectId} (${firstLine(error)}). The guard fails CLOSED; if this is a permissions error, grant the deploy service account roles/run.viewer.`,\n );\n process.exit(1);\n }\n if (labelled.length === 0) {\n console.error(\n `::error::[invoker-guard] No callable service carries the ${CALLABLE_LABEL_FILTER} label on ${projectId} in ${region}. The guard fails CLOSED: a check that found nothing proved nothing.`,\n );\n process.exit(1);\n }\n const services = [...new Set([...labelled, ...extraPublicServices])];\n const policies = new Map<string, IamPolicy | Error>();\n for (const name of services) {\n try {\n policies.set(\n name,\n JSON.parse(\n gcloud([\n 'run',\n 'services',\n 'get-iam-policy',\n name,\n `--project=${projectId}`,\n `--region=${region}`,\n '--format=json',\n ]) || '{}',\n ) as IamPolicy,\n );\n } catch (error) {\n policies.set(\n name,\n new Error(error instanceof SyntaxError ? 'unparseable IAM policy' : firstLine(error)),\n );\n }\n }\n const { missing, unreadable } = assessInvokers(services, policies);\n for (const name of missing) {\n console.error(\n `::error::[invoker-guard] ${name} is MISSING the allUsers -> roles/run.invoker binding — clients are refused at Cloud Run before the request reaches the function. Fix: gcloud run services add-iam-policy-binding ${name} --region=${region} --project=${projectId} --member=allUsers --role=roles/run.invoker`,\n );\n }\n for (const entry of unreadable) {\n console.error(\n `::error::[invoker-guard] Could not read the IAM policy for ${entry}. The guard fails CLOSED; grant the deploy service account roles/run.viewer if this is a permissions error.`,\n );\n }\n if (missing.length || unreadable.length) {\n console.error(\n `\\n[invoker-guard] FAILED — ${missing.length} missing binding(s), ${unreadable.length} unreadable — on project ${projectId}.`,\n );\n process.exit(1);\n }\n console.log(\n `[invoker-guard] OK — ${services.length} public service(s) on ${projectId} carry the allUsers invoker binding.`,\n );\n}\n\nexport function checkDeployedFunctions({\n repoRoot,\n region,\n projectId: requested,\n expected,\n}: {\n repoRoot: string;\n region: string;\n projectId: string | undefined;\n expected: () => readonly ExpectedCodebase[];\n}): void {\n const projectId = knownProject(repoRoot, requested, 'deployed-functions');\n let groups: readonly ExpectedCodebase[];\n try {\n groups = expected();\n } catch (error) {\n console.error(\n `::error::[deployed-functions] Could not read the expected functions (${firstLine(error)}). The guard fails CLOSED.`,\n );\n process.exit(2);\n }\n if (groups.length === 0) {\n console.log('[deployed-functions] OK — this deploy targeted no functions.');\n return;\n }\n let live;\n try {\n live = parseLiveFunctions(\n JSON.parse(\n gcloud([\n 'functions',\n 'list',\n `--project=${projectId}`,\n `--regions=${region}`,\n '--format=json',\n ]) || '[]',\n // gcloud's JSON listing of functions is an array of these rows.\n ) as Parameters<typeof parseLiveFunctions>[0],\n );\n } catch (error) {\n console.error(\n `::error::[deployed-functions] Could not list the functions on ${projectId} (${firstLine(error)}). The guard fails CLOSED.`,\n );\n process.exit(1);\n }\n const { missing, leftover, notActive } = compareDeployedFunctions(groups, live);\n for (const fn of missing) {\n console.error(\n `::error::[deployed-functions] ${fn} is expected but NOT deployed — its create was dropped or failed.`,\n );\n }\n for (const fn of leftover) {\n console.error(\n `::error::[deployed-functions] ${fn} is still deployed but no longer expected — its deletion did not happen.`,\n );\n }\n for (const fn of notActive) {\n console.error(`::error::[deployed-functions] ${fn} is deployed but not ACTIVE.`);\n }\n if (missing.length || leftover.length || notActive.length) {\n console.error(\n `\\n[deployed-functions] FAILED on ${projectId} — ${missing.length} missing, ${leftover.length} leftover, ${notActive.length} not ACTIVE.`,\n );\n process.exit(1);\n }\n const count = groups.reduce((n, g) => n + g.names.length, 0);\n console.log(\n `[deployed-functions] OK — ${count} functions on ${projectId}: every expected function is live and ACTIVE, and nothing else is.`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cloud-checks.js","sourceRoot":"","sources":["../../../src/node/tooling/cloud-checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport {\n CALLABLE_LABEL_FILTER,\n assessInvokers,\n lines,\n type IamPolicy,\n} from './callable-invokers.js';\nimport {\n compareDeployedFunctions,\n parseLiveFunctions,\n targetedCodebases,\n type ExpectedCodebase,\n type LiveFunction,\n} from './deployed-functions.js';\nimport { runFunctionsDeployPasses, type FunctionsManifest } from './functions-deploy-passes.js';\nimport {\n assertSafeCors,\n defaultStorageBucket,\n normalizeCors,\n readBucketCors,\n} from './storage-cors.js';\nimport { readFirebaseProjects } from './firebase-projects-file.js';\n\nfunction gcloud(args: readonly string[], cwd?: string): string {\n return execFileSync('gcloud', args, {\n cwd,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe'],\n maxBuffer: 64 * 1024 * 1024,\n });\n}\n\nfunction listLiveFunctions(projectId: string, region: string): LiveFunction[] {\n return parseLiveFunctions(\n JSON.parse(\n gcloud([\n 'functions',\n 'list',\n `--project=${projectId}`,\n `--regions=${region}`,\n '--format=json',\n ]) || '[]',\n // gcloud's JSON listing of functions is an array of these rows.\n ) as Parameters<typeof parseLiveFunctions>[0],\n );\n}\n\nfunction firstLine(error: unknown): string {\n const e = error as { stderr?: unknown; message?: unknown } | null;\n return String(e?.stderr || e?.message || error).split('\\n')[0]!;\n}\n\nfunction knownProject(repoRoot: string, projectId: string | undefined, tag: string): string {\n const projects = readFirebaseProjects(repoRoot);\n const known = [projects.dev, projects.prod];\n if (!projectId) {\n console.error(`usage: <script> <projectId> (one of: ${known.join(', ')})`);\n process.exit(2);\n }\n if (!known.includes(projectId)) {\n console.error(\n `::error::[${tag}] Unknown project \"${projectId}\" — expected one of: ${known.join(', ')}.`,\n );\n process.exit(2);\n }\n return projectId;\n}\n\nexport function applyStorageCors(repoRoot: string, projectId: string): void {\n const projects = readFirebaseProjects(repoRoot);\n if (projectId !== projects.dev && projectId !== projects.prod) {\n throw new Error(`unsupported project: ${projectId}`);\n }\n const expected: unknown = JSON.parse(readFileSync(path.join(repoRoot, 'cors.json'), 'utf8'));\n assertSafeCors(expected);\n const bucketUri = `gs://${defaultStorageBucket(projectId)}`;\n gcloud(\n ['storage', 'buckets', 'update', bucketUri, '--cors-file=cors.json', `--project=${projectId}`],\n repoRoot,\n );\n const actual = readBucketCors(\n JSON.parse(\n gcloud(\n ['storage', 'buckets', 'describe', bucketUri, '--format=json', `--project=${projectId}`],\n repoRoot,\n ),\n ),\n );\n if (JSON.stringify(normalizeCors(actual)) !== JSON.stringify(normalizeCors(expected))) {\n throw new Error(\n `Storage CORS verification failed for ${bucketUri}: applied ${JSON.stringify(actual)}, expected ${JSON.stringify(expected)}`,\n );\n }\n console.log(`Storage CORS applied and verified for ${bucketUri}`);\n}\n\nexport function checkCallableInvokers({\n repoRoot,\n region,\n projectId: requested,\n extraPublicServices = [],\n}: {\n repoRoot: string;\n region: string;\n projectId: string | undefined;\n extraPublicServices?: readonly string[];\n}): void {\n const projectId = knownProject(repoRoot, requested, 'invoker-guard');\n let labelled: string[];\n try {\n labelled = lines(\n gcloud([\n 'run',\n 'services',\n 'list',\n `--project=${projectId}`,\n `--region=${region}`,\n `--filter=${CALLABLE_LABEL_FILTER}`,\n '--format=value(metadata.name)',\n ]),\n );\n } catch (error) {\n console.error(\n `::error::[invoker-guard] Could not list Cloud Run services on ${projectId} (${firstLine(error)}). The guard fails CLOSED; if this is a permissions error, grant the deploy service account roles/run.viewer.`,\n );\n process.exit(1);\n }\n if (labelled.length === 0) {\n console.error(\n `::error::[invoker-guard] No callable service carries the ${CALLABLE_LABEL_FILTER} label on ${projectId} in ${region}. The guard fails CLOSED: a check that found nothing proved nothing.`,\n );\n process.exit(1);\n }\n const services = [...new Set([...labelled, ...extraPublicServices])];\n const policies = new Map<string, IamPolicy | Error>();\n for (const name of services) {\n try {\n policies.set(\n name,\n JSON.parse(\n gcloud([\n 'run',\n 'services',\n 'get-iam-policy',\n name,\n `--project=${projectId}`,\n `--region=${region}`,\n '--format=json',\n ]) || '{}',\n ) as IamPolicy,\n );\n } catch (error) {\n policies.set(\n name,\n new Error(error instanceof SyntaxError ? 'unparseable IAM policy' : firstLine(error)),\n );\n }\n }\n const { missing, unreadable } = assessInvokers(services, policies);\n for (const name of missing) {\n console.error(\n `::error::[invoker-guard] ${name} is MISSING the allUsers -> roles/run.invoker binding — clients are refused at Cloud Run before the request reaches the function. Fix: gcloud run services add-iam-policy-binding ${name} --region=${region} --project=${projectId} --member=allUsers --role=roles/run.invoker`,\n );\n }\n for (const entry of unreadable) {\n console.error(\n `::error::[invoker-guard] Could not read the IAM policy for ${entry}. The guard fails CLOSED; grant the deploy service account roles/run.viewer if this is a permissions error.`,\n );\n }\n if (missing.length || unreadable.length) {\n console.error(\n `\\n[invoker-guard] FAILED — ${missing.length} missing binding(s), ${unreadable.length} unreadable — on project ${projectId}.`,\n );\n process.exit(1);\n }\n console.log(\n `[invoker-guard] OK — ${services.length} public service(s) on ${projectId} carry the allUsers invoker binding.`,\n );\n}\n\nexport function checkDeployedFunctions({\n repoRoot,\n region,\n projectId: requested,\n expected,\n}: {\n repoRoot: string;\n region: string;\n projectId: string | undefined;\n expected: () => readonly ExpectedCodebase[];\n}): void {\n const projectId = knownProject(repoRoot, requested, 'deployed-functions');\n let groups: readonly ExpectedCodebase[];\n try {\n groups = expected();\n } catch (error) {\n console.error(\n `::error::[deployed-functions] Could not read the expected functions (${firstLine(error)}). The guard fails CLOSED.`,\n );\n process.exit(2);\n }\n if (groups.length === 0) {\n console.log('[deployed-functions] OK — this deploy targeted no functions.');\n return;\n }\n let live;\n try {\n live = listLiveFunctions(projectId, region);\n } catch (error) {\n console.error(\n `::error::[deployed-functions] Could not list the functions on ${projectId} (${firstLine(error)}). The guard fails CLOSED.`,\n );\n process.exit(1);\n }\n const { missing, leftover, notActive } = compareDeployedFunctions(groups, live);\n for (const fn of missing) {\n console.error(\n `::error::[deployed-functions] ${fn} is expected but NOT deployed — its create was dropped or failed.`,\n );\n }\n for (const fn of leftover) {\n console.error(\n `::error::[deployed-functions] ${fn} is still deployed but no longer expected — its deletion did not happen.`,\n );\n }\n for (const fn of notActive) {\n console.error(`::error::[deployed-functions] ${fn} is deployed but not ACTIVE.`);\n }\n if (missing.length || leftover.length || notActive.length) {\n console.error(\n `\\n[deployed-functions] FAILED on ${projectId} — ${missing.length} missing, ${leftover.length} leftover, ${notActive.length} not ACTIVE.`,\n );\n process.exit(1);\n }\n const count = groups.reduce((n, g) => n + g.names.length, 0);\n console.log(\n `[deployed-functions] OK — ${count} functions on ${projectId}: every expected function is live and ACTIVE, and nothing else is.`,\n );\n}\n\nexport function deployFunctionsInPasses({\n repoRoot,\n region,\n projectId: requested,\n targets,\n manifest,\n nonFunctionTargets,\n}: {\n repoRoot: string;\n region: string;\n projectId: string | undefined;\n targets: string | undefined;\n manifest: () => FunctionsManifest;\n nonFunctionTargets: readonly string[];\n}): void {\n const projectId = knownProject(repoRoot, requested, 'deploy-functions');\n let codebases: FunctionsManifest;\n let selected: string[];\n try {\n codebases = manifest();\n selected = targetedCodebases(targets ?? '', Object.keys(codebases));\n } catch (error) {\n console.error(\n `::error::[deploy-functions] Could not read the deploy targets (${firstLine(error)}).`,\n );\n process.exit(2);\n }\n const pauseLock = new Int32Array(new SharedArrayBuffer(4));\n const ok = runFunctionsDeployPasses(\n { targets: selected, manifest: codebases, nonFunctionTargets },\n {\n listLive: () => listLiveFunctions(projectId, region),\n deploy: (only) => {\n try {\n execFileSync(\n 'firebase',\n ['deploy', '--only', only, '--project', projectId, '--non-interactive', '--force'],\n { cwd: repoRoot, stdio: 'inherit' },\n );\n return true;\n } catch {\n return false;\n }\n },\n pause: (ms) => {\n Atomics.wait(pauseLock, 0, 0, ms);\n },\n log: (line) => console.log(line),\n error: (line) => console.error(`::error::${line}`),\n },\n );\n if (!ok) process.exit(1);\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type LiveFunction } from './deployed-functions.js';
|
|
2
|
+
export declare const DEPLOY_PASS_ATTEMPTS = 3;
|
|
3
|
+
export declare const DEPLOY_PASS_PAUSE_MS = 60000;
|
|
4
|
+
export type FunctionsManifest = Readonly<Record<string, readonly string[]>>;
|
|
5
|
+
export interface FunctionsDeployPlan {
|
|
6
|
+
passes: string[];
|
|
7
|
+
problems: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function planFunctionsDeployPasses({ targets, manifest, live, }: {
|
|
10
|
+
targets: readonly string[];
|
|
11
|
+
manifest: FunctionsManifest;
|
|
12
|
+
live: readonly LiveFunction[];
|
|
13
|
+
}): FunctionsDeployPlan;
|
|
14
|
+
export interface DeployPassEffects {
|
|
15
|
+
listLive: () => LiveFunction[];
|
|
16
|
+
deploy: (only: string) => boolean;
|
|
17
|
+
pause: (ms: number) => void;
|
|
18
|
+
log: (line: string) => void;
|
|
19
|
+
error: (line: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function runFunctionsDeployPasses({ targets, manifest, nonFunctionTargets, }: {
|
|
22
|
+
targets: readonly string[];
|
|
23
|
+
manifest: FunctionsManifest;
|
|
24
|
+
nonFunctionTargets: readonly string[];
|
|
25
|
+
}, effects: DeployPassEffects): boolean;
|
|
26
|
+
//# sourceMappingURL=functions-deploy-passes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions-deploy-passes.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/functions-deploy-passes.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEtF,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAKD,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,QAAQ,EACR,IAAI,GACL,EAAE;IACD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,EAAE,SAAS,YAAY,EAAE,CAAC;CAC/B,GAAG,mBAAmB,CAiDtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,YAAY,EAAE,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,wBAAgB,wBAAwB,CACtC,EACE,OAAO,EACP,QAAQ,EACR,kBAAkB,GACnB,EAAE;IACD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC,EACD,OAAO,EAAE,iBAAiB,GACzB,OAAO,CA8CT"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { compareDeployedFunctions } from './deployed-functions.js';
|
|
2
|
+
export const DEPLOY_PASS_ATTEMPTS = 3;
|
|
3
|
+
export const DEPLOY_PASS_PAUSE_MS = 60_000;
|
|
4
|
+
// The deploy CLI groups a live function by name only across the codebases one deploy targets, so a
|
|
5
|
+
// function moving between codebases is updated in place only when its new codebase deploys first;
|
|
6
|
+
// deploying the old codebase first deletes it.
|
|
7
|
+
export function planFunctionsDeployPasses({ targets, manifest, live, }) {
|
|
8
|
+
const problems = [];
|
|
9
|
+
const owner = new Map();
|
|
10
|
+
for (const [codebase, names] of Object.entries(manifest))
|
|
11
|
+
for (const name of names)
|
|
12
|
+
owner.set(name, codebase);
|
|
13
|
+
const before = new Map(targets.map((cb) => [cb, new Set()]));
|
|
14
|
+
const moves = [];
|
|
15
|
+
for (const fn of live) {
|
|
16
|
+
const wanted = owner.get(fn.name);
|
|
17
|
+
if (wanted === undefined) {
|
|
18
|
+
if (fn.codebase === null || !(fn.codebase in manifest))
|
|
19
|
+
problems.push(`${fn.name} is live under ${fn.codebase ?? 'no codebase'}, which no codebase deploys, so no pass would delete it`);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (fn.codebase === null || fn.codebase === wanted)
|
|
23
|
+
continue;
|
|
24
|
+
if (!targets.includes(wanted)) {
|
|
25
|
+
problems.push(`${fn.name} moves from ${fn.codebase} to ${wanted}, but this release does not deploy ${wanted}`);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (!targets.includes(fn.codebase))
|
|
29
|
+
continue;
|
|
30
|
+
before.get(fn.codebase).add(wanted);
|
|
31
|
+
moves.push({ name: fn.name, from: fn.codebase, to: wanted });
|
|
32
|
+
}
|
|
33
|
+
const passes = [];
|
|
34
|
+
const placed = new Set();
|
|
35
|
+
while (passes.length < targets.length) {
|
|
36
|
+
const next = targets.find((cb) => !placed.has(cb) && [...before.get(cb)].every((dep) => placed.has(dep)));
|
|
37
|
+
if (next === undefined) {
|
|
38
|
+
const stuck = targets.filter((cb) => !placed.has(cb));
|
|
39
|
+
const swapped = moves
|
|
40
|
+
.filter((move) => stuck.includes(move.from) && stuck.includes(move.to))
|
|
41
|
+
.map((move) => `${move.name} ${move.from} -> ${move.to}`);
|
|
42
|
+
problems.push(`functions move both ways between ${stuck.join(', ')} (${swapped.join(', ')}); move them in two releases`);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
passes.push(next);
|
|
46
|
+
placed.add(next);
|
|
47
|
+
}
|
|
48
|
+
return { passes, problems };
|
|
49
|
+
}
|
|
50
|
+
export function runFunctionsDeployPasses({ targets, manifest, nonFunctionTargets, }, effects) {
|
|
51
|
+
const plan = planFunctionsDeployPasses({ targets, manifest, live: effects.listLive() });
|
|
52
|
+
if (plan.problems.length > 0) {
|
|
53
|
+
for (const problem of plan.problems)
|
|
54
|
+
effects.error(`[deploy-functions] ${problem}`);
|
|
55
|
+
effects.error('[deploy-functions] Nothing was deployed.');
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const attempt = (label, run) => {
|
|
59
|
+
for (let n = 1; n <= DEPLOY_PASS_ATTEMPTS; n += 1) {
|
|
60
|
+
if (run())
|
|
61
|
+
return true;
|
|
62
|
+
if (n < DEPLOY_PASS_ATTEMPTS) {
|
|
63
|
+
effects.log(`[deploy-functions] ${label}: attempt ${n} failed; retrying.`);
|
|
64
|
+
effects.pause(DEPLOY_PASS_PAUSE_MS);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
effects.error(`[deploy-functions] ${label} failed ${DEPLOY_PASS_ATTEMPTS} attempts; later passes did not run.`);
|
|
68
|
+
return false;
|
|
69
|
+
};
|
|
70
|
+
if (nonFunctionTargets.length > 0) {
|
|
71
|
+
const only = nonFunctionTargets.join(',');
|
|
72
|
+
if (!attempt(only, () => effects.deploy(only)))
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
effects.log(`[deploy-functions] passes: ${plan.passes.join(' -> ') || '(none)'}`);
|
|
76
|
+
for (const [index, codebase] of plan.passes.entries()) {
|
|
77
|
+
const ok = attempt(`functions:${codebase}`, () => {
|
|
78
|
+
if (!effects.deploy(`functions:${codebase}`))
|
|
79
|
+
return false;
|
|
80
|
+
const { missing, leftover, notActive } = compareDeployedFunctions([{ codebase, names: manifest[codebase] ?? [] }], effects.listLive());
|
|
81
|
+
for (const fn of missing)
|
|
82
|
+
effects.error(`[deploy-functions] ${fn} is expected but not deployed.`);
|
|
83
|
+
for (const fn of leftover)
|
|
84
|
+
effects.error(`[deploy-functions] ${fn} is still deployed but no longer expected.`);
|
|
85
|
+
for (const fn of notActive)
|
|
86
|
+
effects.error(`[deploy-functions] ${fn} is not ACTIVE.`);
|
|
87
|
+
return missing.length + leftover.length + notActive.length === 0;
|
|
88
|
+
});
|
|
89
|
+
if (!ok)
|
|
90
|
+
return false;
|
|
91
|
+
if (index < plan.passes.length - 1)
|
|
92
|
+
effects.pause(DEPLOY_PASS_PAUSE_MS);
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=functions-deploy-passes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions-deploy-passes.js","sourceRoot":"","sources":["../../../src/node/tooling/functions-deploy-passes.ts"],"names":[],"mappings":"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","sourcesContent":["import { compareDeployedFunctions, type LiveFunction } from './deployed-functions.js';\n\nexport const DEPLOY_PASS_ATTEMPTS = 3;\nexport const DEPLOY_PASS_PAUSE_MS = 60_000;\n\nexport type FunctionsManifest = Readonly<Record<string, readonly string[]>>;\n\nexport interface FunctionsDeployPlan {\n passes: string[];\n problems: string[];\n}\n\n// The deploy CLI groups a live function by name only across the codebases one deploy targets, so a\n// function moving between codebases is updated in place only when its new codebase deploys first;\n// deploying the old codebase first deletes it.\nexport function planFunctionsDeployPasses({\n targets,\n manifest,\n live,\n}: {\n targets: readonly string[];\n manifest: FunctionsManifest;\n live: readonly LiveFunction[];\n}): FunctionsDeployPlan {\n const problems: string[] = [];\n const owner = new Map<string, string>();\n for (const [codebase, names] of Object.entries(manifest))\n for (const name of names) owner.set(name, codebase);\n\n const before = new Map<string, Set<string>>(targets.map((cb) => [cb, new Set<string>()]));\n const moves: { name: string; from: string; to: string }[] = [];\n for (const fn of live) {\n const wanted = owner.get(fn.name);\n if (wanted === undefined) {\n if (fn.codebase === null || !(fn.codebase in manifest))\n problems.push(\n `${fn.name} is live under ${fn.codebase ?? 'no codebase'}, which no codebase deploys, so no pass would delete it`,\n );\n continue;\n }\n if (fn.codebase === null || fn.codebase === wanted) continue;\n if (!targets.includes(wanted)) {\n problems.push(\n `${fn.name} moves from ${fn.codebase} to ${wanted}, but this release does not deploy ${wanted}`,\n );\n continue;\n }\n if (!targets.includes(fn.codebase)) continue;\n before.get(fn.codebase)!.add(wanted);\n moves.push({ name: fn.name, from: fn.codebase, to: wanted });\n }\n\n const passes: string[] = [];\n const placed = new Set<string>();\n while (passes.length < targets.length) {\n const next = targets.find(\n (cb) => !placed.has(cb) && [...before.get(cb)!].every((dep) => placed.has(dep)),\n );\n if (next === undefined) {\n const stuck = targets.filter((cb) => !placed.has(cb));\n const swapped = moves\n .filter((move) => stuck.includes(move.from) && stuck.includes(move.to))\n .map((move) => `${move.name} ${move.from} -> ${move.to}`);\n problems.push(\n `functions move both ways between ${stuck.join(', ')} (${swapped.join(', ')}); move them in two releases`,\n );\n break;\n }\n passes.push(next);\n placed.add(next);\n }\n return { passes, problems };\n}\n\nexport interface DeployPassEffects {\n listLive: () => LiveFunction[];\n deploy: (only: string) => boolean;\n pause: (ms: number) => void;\n log: (line: string) => void;\n error: (line: string) => void;\n}\n\nexport function runFunctionsDeployPasses(\n {\n targets,\n manifest,\n nonFunctionTargets,\n }: {\n targets: readonly string[];\n manifest: FunctionsManifest;\n nonFunctionTargets: readonly string[];\n },\n effects: DeployPassEffects,\n): boolean {\n const plan = planFunctionsDeployPasses({ targets, manifest, live: effects.listLive() });\n if (plan.problems.length > 0) {\n for (const problem of plan.problems) effects.error(`[deploy-functions] ${problem}`);\n effects.error('[deploy-functions] Nothing was deployed.');\n return false;\n }\n\n const attempt = (label: string, run: () => boolean): boolean => {\n for (let n = 1; n <= DEPLOY_PASS_ATTEMPTS; n += 1) {\n if (run()) return true;\n if (n < DEPLOY_PASS_ATTEMPTS) {\n effects.log(`[deploy-functions] ${label}: attempt ${n} failed; retrying.`);\n effects.pause(DEPLOY_PASS_PAUSE_MS);\n }\n }\n effects.error(\n `[deploy-functions] ${label} failed ${DEPLOY_PASS_ATTEMPTS} attempts; later passes did not run.`,\n );\n return false;\n };\n\n if (nonFunctionTargets.length > 0) {\n const only = nonFunctionTargets.join(',');\n if (!attempt(only, () => effects.deploy(only))) return false;\n }\n\n effects.log(`[deploy-functions] passes: ${plan.passes.join(' -> ') || '(none)'}`);\n for (const [index, codebase] of plan.passes.entries()) {\n const ok = attempt(`functions:${codebase}`, () => {\n if (!effects.deploy(`functions:${codebase}`)) return false;\n const { missing, leftover, notActive } = compareDeployedFunctions(\n [{ codebase, names: manifest[codebase] ?? [] }],\n effects.listLive(),\n );\n for (const fn of missing)\n effects.error(`[deploy-functions] ${fn} is expected but not deployed.`);\n for (const fn of leftover)\n effects.error(`[deploy-functions] ${fn} is still deployed but no longer expected.`);\n for (const fn of notActive) effects.error(`[deploy-functions] ${fn} is not ACTIVE.`);\n return missing.length + leftover.length + notActive.length === 0;\n });\n if (!ok) return false;\n if (index < plan.passes.length - 1) effects.pause(DEPLOY_PASS_PAUSE_MS);\n }\n return true;\n}\n"]}
|
|
@@ -2,8 +2,9 @@ export { AppHostingConfigError, BASE_CONFIG, PRODUCTION_CONFIG, buildEnvFromConf
|
|
|
2
2
|
export { runAppHostingBuild } from './apphosting-build.js';
|
|
3
3
|
export { CALLABLE_LABEL_FILTER, assessInvokers, hasAllUsersInvoker, lines, type IamPolicy, } from './callable-invokers.js';
|
|
4
4
|
export { runCleanup } from './cleanup.js';
|
|
5
|
-
export { applyStorageCors, checkCallableInvokers, checkDeployedFunctions } from './cloud-checks.js';
|
|
5
|
+
export { applyStorageCors, checkCallableInvokers, checkDeployedFunctions, deployFunctionsInPasses, } from './cloud-checks.js';
|
|
6
6
|
export { CODEBASE_LABEL, compareDeployedFunctions, parseLiveFunctions, targetedCodebases, type ExpectedCodebase, type LiveFunction, } from './deployed-functions.js';
|
|
7
|
+
export { DEPLOY_PASS_ATTEMPTS, DEPLOY_PASS_PAUSE_MS, planFunctionsDeployPasses, runFunctionsDeployPasses, type DeployPassEffects, type FunctionsDeployPlan, type FunctionsManifest, } from './functions-deploy-passes.js';
|
|
7
8
|
export { adcCandidatePaths, devLoginPlan, runDevLogin, runDevLoginCli, type DevLoginPlan, type LoginStep, } from './dev-login.js';
|
|
8
9
|
export { isStackProcess, killDevStack, listeningOn, type DevStackConfig } from './dev-stack.js';
|
|
9
10
|
export { runEmulatorSeed } from './emulator-seed.js';
|
|
@@ -12,7 +13,7 @@ export { readFirebaseProjects } from './firebase-projects-file.js';
|
|
|
12
13
|
export { isDevProject, parseFirebaseProjects, resolveProject, type FirebaseProjects, } from './firebase-projects.js';
|
|
13
14
|
export { checkPlaybookRefs, runPlaybookRefsCli, type PlaybookMiss, type PlaybookRefsConfig, } from './playbook-refs.js';
|
|
14
15
|
export { collectPlaywrightFailures, FLAKY_LOG_HEADER, flakyLogRows, type FlakyTest, type PlaywrightJsonReport, type PlaywrightTotals, } from './playwright-report.js';
|
|
15
|
-
export { runQuietGate, selectStages, type GateSelection, type GateStage, type GateStep, type LiveService, type QuietGateConfig, } from './quiet-gate.js';
|
|
16
|
+
export { GATE_PHASES, runQuietGate, selectStages, type GatePhase, type GateSelection, type GateStage, type GateStep, type LiveService, type QuietGateConfig, } from './quiet-gate.js';
|
|
16
17
|
export { DispatchInputError, RELEASE_REASONS, RELEASE_REASON_CODES, classifyPaths, formatOutputs, lastGreenRunsUrl, outputKeys, parseCodebasesInput, pickNewestGreenSha, resolveReleaseScope, type ReleaseApi, type ReleaseComponent, type ReleaseDispatch, type ReleaseGit, type ReleaseReason, type ReleaseScopeConfig, type ResolvedScope, } from './release-scope.js';
|
|
17
18
|
export { assertReleaseVerdict, assertVerificationGate, renderSummary, type Blocker, type ReleaseEnv, type ReleaseVerdictConfig, type VerdictComponent, } from './release-verdict.js';
|
|
18
19
|
export { githubReleaseApi, repoGit, runReleaseScopeCli, runReleaseVerdictCli } from './release.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,KAAK,EACL,KAAK,SAAS,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,9 @@ export { AppHostingConfigError, BASE_CONFIG, PRODUCTION_CONFIG, buildEnvFromConf
|
|
|
2
2
|
export { runAppHostingBuild } from './apphosting-build.js';
|
|
3
3
|
export { CALLABLE_LABEL_FILTER, assessInvokers, hasAllUsersInvoker, lines, } from './callable-invokers.js';
|
|
4
4
|
export { runCleanup } from './cleanup.js';
|
|
5
|
-
export { applyStorageCors, checkCallableInvokers, checkDeployedFunctions } from './cloud-checks.js';
|
|
5
|
+
export { applyStorageCors, checkCallableInvokers, checkDeployedFunctions, deployFunctionsInPasses, } from './cloud-checks.js';
|
|
6
6
|
export { CODEBASE_LABEL, compareDeployedFunctions, parseLiveFunctions, targetedCodebases, } from './deployed-functions.js';
|
|
7
|
+
export { DEPLOY_PASS_ATTEMPTS, DEPLOY_PASS_PAUSE_MS, planFunctionsDeployPasses, runFunctionsDeployPasses, } from './functions-deploy-passes.js';
|
|
7
8
|
export { adcCandidatePaths, devLoginPlan, runDevLogin, runDevLoginCli, } from './dev-login.js';
|
|
8
9
|
export { isStackProcess, killDevStack, listeningOn } from './dev-stack.js';
|
|
9
10
|
export { runEmulatorSeed } from './emulator-seed.js';
|
|
@@ -12,7 +13,7 @@ export { readFirebaseProjects } from './firebase-projects-file.js';
|
|
|
12
13
|
export { isDevProject, parseFirebaseProjects, resolveProject, } from './firebase-projects.js';
|
|
13
14
|
export { checkPlaybookRefs, runPlaybookRefsCli, } from './playbook-refs.js';
|
|
14
15
|
export { collectPlaywrightFailures, FLAKY_LOG_HEADER, flakyLogRows, } from './playwright-report.js';
|
|
15
|
-
export { runQuietGate, selectStages, } from './quiet-gate.js';
|
|
16
|
+
export { GATE_PHASES, runQuietGate, selectStages, } from './quiet-gate.js';
|
|
16
17
|
export { DispatchInputError, RELEASE_REASONS, RELEASE_REASON_CODES, classifyPaths, formatOutputs, lastGreenRunsUrl, outputKeys, parseCodebasesInput, pickNewestGreenSha, resolveReleaseScope, } from './release-scope.js';
|
|
17
18
|
export { assertReleaseVerdict, assertVerificationGate, renderSummary, } from './release-verdict.js';
|
|
18
19
|
export { githubReleaseApi, repoGit, runReleaseScopeCli, runReleaseVerdictCli } from './release.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/node/tooling/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,WAAW,GAGZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,KAAK,GAEN,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/node/tooling/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,WAAW,GAGZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,KAAK,GAEN,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,GAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,GAIzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,cAAc,GAGf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAuB,MAAM,gBAAgB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,YAAY,GAIb,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,GAOb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GAQpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,GAKd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,YAAY,GAEb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,cAAc,GAEf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,GAMnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC","sourcesContent":["export {\n AppHostingConfigError,\n BASE_CONFIG,\n PRODUCTION_CONFIG,\n buildEnvFromConfigs,\n configFilesFor,\n isBuildAvailable,\n mergeEnv,\n parseConfig,\n type AppHostingEnvEntry,\n type BuildSecretSkip,\n} from './apphosting-env.js';\nexport { runAppHostingBuild } from './apphosting-build.js';\nexport {\n CALLABLE_LABEL_FILTER,\n assessInvokers,\n hasAllUsersInvoker,\n lines,\n type IamPolicy,\n} from './callable-invokers.js';\nexport { runCleanup } from './cleanup.js';\nexport {\n applyStorageCors,\n checkCallableInvokers,\n checkDeployedFunctions,\n deployFunctionsInPasses,\n} from './cloud-checks.js';\nexport {\n CODEBASE_LABEL,\n compareDeployedFunctions,\n parseLiveFunctions,\n targetedCodebases,\n type ExpectedCodebase,\n type LiveFunction,\n} from './deployed-functions.js';\nexport {\n DEPLOY_PASS_ATTEMPTS,\n DEPLOY_PASS_PAUSE_MS,\n planFunctionsDeployPasses,\n runFunctionsDeployPasses,\n type DeployPassEffects,\n type FunctionsDeployPlan,\n type FunctionsManifest,\n} from './functions-deploy-passes.js';\nexport {\n adcCandidatePaths,\n devLoginPlan,\n runDevLogin,\n runDevLoginCli,\n type DevLoginPlan,\n type LoginStep,\n} from './dev-login.js';\nexport { isStackProcess, killDevStack, listeningOn, type DevStackConfig } from './dev-stack.js';\nexport { runEmulatorSeed } from './emulator-seed.js';\nexport {\n analyzeFieldLineage,\n runFieldLineageCli,\n type FieldLineageConfig,\n} from './field-lineage.js';\nexport { readFirebaseProjects } from './firebase-projects-file.js';\nexport {\n isDevProject,\n parseFirebaseProjects,\n resolveProject,\n type FirebaseProjects,\n} from './firebase-projects.js';\nexport {\n checkPlaybookRefs,\n runPlaybookRefsCli,\n type PlaybookMiss,\n type PlaybookRefsConfig,\n} from './playbook-refs.js';\nexport {\n collectPlaywrightFailures,\n FLAKY_LOG_HEADER,\n flakyLogRows,\n type FlakyTest,\n type PlaywrightJsonReport,\n type PlaywrightTotals,\n} from './playwright-report.js';\nexport {\n GATE_PHASES,\n runQuietGate,\n selectStages,\n type GatePhase,\n type GateSelection,\n type GateStage,\n type GateStep,\n type LiveService,\n type QuietGateConfig,\n} from './quiet-gate.js';\nexport {\n DispatchInputError,\n RELEASE_REASONS,\n RELEASE_REASON_CODES,\n classifyPaths,\n formatOutputs,\n lastGreenRunsUrl,\n outputKeys,\n parseCodebasesInput,\n pickNewestGreenSha,\n resolveReleaseScope,\n type ReleaseApi,\n type ReleaseComponent,\n type ReleaseDispatch,\n type ReleaseGit,\n type ReleaseReason,\n type ReleaseScopeConfig,\n type ResolvedScope,\n} from './release-scope.js';\nexport {\n assertReleaseVerdict,\n assertVerificationGate,\n renderSummary,\n type Blocker,\n type ReleaseEnv,\n type ReleaseVerdictConfig,\n type VerdictComponent,\n} from './release-verdict.js';\nexport { githubReleaseApi, repoGit, runReleaseScopeCli, runReleaseVerdictCli } from './release.js';\nexport {\n SHELL_SAFE_TOKEN,\n isMainModule,\n runCommand,\n runNpmScript,\n type CommandResult,\n} from './shell.js';\nexport {\n assertSafeCors,\n defaultStorageBucket,\n normalizeCors,\n readBucketCors,\n type CorsEntry,\n} from './storage-cors.js';\nexport {\n collectVitestFailures,\n formatSuiteFailures,\n parseVitestJson,\n vitestStageVerdict,\n type SkippedTest,\n type SuiteFailure,\n type TestFailure,\n type VitestJsonReport,\n type VitestTotals,\n} from './vitest-report.js';\nexport {\n extractUnhandledErrorReport,\n formatUnhandledErrorReport,\n} from './vitest-unhandled-errors.js';\n"]}
|
|
@@ -20,9 +20,12 @@ export interface LiveService {
|
|
|
20
20
|
name: string;
|
|
21
21
|
port: number;
|
|
22
22
|
}
|
|
23
|
+
export declare const GATE_PHASES: readonly ["start", "live"];
|
|
24
|
+
export type GatePhase = (typeof GATE_PHASES)[number];
|
|
23
25
|
export interface GateStage {
|
|
24
26
|
id: string;
|
|
25
27
|
description: string;
|
|
28
|
+
phase?: GatePhase;
|
|
26
29
|
stopOnFailure: boolean;
|
|
27
30
|
steps: () => readonly GateStep[];
|
|
28
31
|
services?: readonly LiveService[];
|
|
@@ -42,6 +45,6 @@ export type GateSelection = {
|
|
|
42
45
|
kind: 'run';
|
|
43
46
|
only: ReadonlySet<string> | null;
|
|
44
47
|
};
|
|
45
|
-
export declare function selectStages(argv: readonly string[], stageIds: readonly string[]): GateSelection;
|
|
48
|
+
export declare function selectStages(argv: readonly string[], stageIds: readonly string[], phases?: Readonly<Record<string, GatePhase | undefined>>): GateSelection;
|
|
46
49
|
export declare function runQuietGate(config: QuietGateConfig, argv?: readonly string[]): Promise<never>;
|
|
47
50
|
//# sourceMappingURL=quiet-gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quiet-gate.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/quiet-gate.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACxE;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEN,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,MAAM,SAAS,QAAQ,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CAC9B;AAaD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;CAAE,CAAC;AAEtD,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"quiet-gate.d.ts","sourceRoot":"","sources":["../../../src/node/tooling/quiet-gate.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACxE;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEN,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,WAAW,4BAA6B,CAAC;AACtD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,MAAM,SAAS,QAAQ,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CAC9B;AAaD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;CAAE,CAAC;AAEtD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,CAAM,GAC3D,aAAa,CA0Df;AAsGD,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,IAAI,GAAE,SAAS,MAAM,EAA0B,GAC9C,OAAO,CAAC,KAAK,CAAC,CAuNhB"}
|
|
@@ -7,6 +7,7 @@ import { collectPlaywrightFailures, FLAKY_LOG_HEADER, flakyLogRows, } from './pl
|
|
|
7
7
|
import { collectVitestFailures, formatSuiteFailures, parseVitestJson, vitestStageVerdict, } from './vitest-report.js';
|
|
8
8
|
import { formatUnhandledErrorReport } from './vitest-unhandled-errors.js';
|
|
9
9
|
import { runCommand } from './shell.js';
|
|
10
|
+
export const GATE_PHASES = ['start', 'live'];
|
|
10
11
|
const RED = '\x1b[31m';
|
|
11
12
|
const GREEN = '\x1b[32m';
|
|
12
13
|
const YELLOW = '\x1b[33m';
|
|
@@ -14,9 +15,33 @@ const CYAN = '\x1b[36m';
|
|
|
14
15
|
const DIM = '\x1b[2m';
|
|
15
16
|
const BOLD = '\x1b[1m';
|
|
16
17
|
const RESET = '\x1b[0m';
|
|
17
|
-
export function selectStages(argv, stageIds) {
|
|
18
|
+
export function selectStages(argv, stageIds, phases = {}) {
|
|
18
19
|
if (argv.includes('--help') || argv.includes('-h'))
|
|
19
20
|
return { kind: 'help' };
|
|
21
|
+
const phaseEq = argv.find((a) => a.startsWith('--phase='));
|
|
22
|
+
const phaseAt = argv.indexOf('--phase');
|
|
23
|
+
if (phaseEq || phaseAt >= 0) {
|
|
24
|
+
const phase = phaseEq ? phaseEq.slice('--phase='.length) : (argv[phaseAt + 1] ?? '');
|
|
25
|
+
if (!GATE_PHASES.includes(phase)) {
|
|
26
|
+
return {
|
|
27
|
+
kind: 'usage-error',
|
|
28
|
+
message: `Unknown phase: ${phase || '(none)'}\nValid phases: ${GATE_PHASES.join(', ')}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const namesStages = argv.some((a) => a === '--only' || a.startsWith('--only=')) ||
|
|
32
|
+
stageIds.some((id) => argv.includes(`--${id}`));
|
|
33
|
+
if (namesStages) {
|
|
34
|
+
return {
|
|
35
|
+
kind: 'usage-error',
|
|
36
|
+
message: '--phase runs a whole phase and takes no --only or stage flag',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const only = new Set(stageIds.filter((id) => (phases[id] ?? 'start') === phase));
|
|
40
|
+
if (only.size === 0) {
|
|
41
|
+
return { kind: 'usage-error', message: `The ${phase} phase declares no stage` };
|
|
42
|
+
}
|
|
43
|
+
return { kind: 'run', only };
|
|
44
|
+
}
|
|
20
45
|
const eq = argv.find((a) => a.startsWith('--only='));
|
|
21
46
|
const at = argv.indexOf('--only');
|
|
22
47
|
let onlyRaw = eq
|
|
@@ -138,10 +163,11 @@ function detailOf(totals, elapsed, loadFailures = 0) {
|
|
|
138
163
|
}
|
|
139
164
|
export async function runQuietGate(config, argv = process.argv.slice(2)) {
|
|
140
165
|
const stageIds = config.stages.map((s) => s.id);
|
|
141
|
-
const selection = selectStages(argv, stageIds);
|
|
166
|
+
const selection = selectStages(argv, stageIds, Object.fromEntries(config.stages.map((s) => [s.id, s.phase])));
|
|
142
167
|
if (selection.kind === 'help') {
|
|
143
168
|
const width = Math.max(...stageIds.map((id) => id.length)) + 4;
|
|
144
169
|
write(`\nUsage: node ${config.script} [options]\n\nOptions:\n` +
|
|
170
|
+
` --phase <phase> Run every stage of one phase: ${GATE_PHASES.join(', ')}.\n` +
|
|
145
171
|
` --only <stages> Comma-separated list of stages to run.\n` +
|
|
146
172
|
` Stages: ${stageIds.join(', ')}\n` +
|
|
147
173
|
config.stages.map((s) => ` --${s.id.padEnd(width)}${s.description}\n`).join('') +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quiet-gate.js","sourceRoot":"","sources":["../../../src/node/tooling/quiet-gate.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n appendFileSync,\n existsSync,\n mkdtempSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport net from 'node:net';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { performance } from 'node:perf_hooks';\nimport {\n collectPlaywrightFailures,\n FLAKY_LOG_HEADER,\n flakyLogRows,\n type FlakyTest,\n type PlaywrightJsonReport,\n type PlaywrightTotals,\n} from './playwright-report.js';\nimport {\n collectVitestFailures,\n formatSuiteFailures,\n parseVitestJson,\n vitestStageVerdict,\n type TestFailure,\n} from './vitest-report.js';\nimport { formatUnhandledErrorReport } from './vitest-unhandled-errors.js';\nimport { runCommand } from './shell.js';\n\nexport type GateStep =\n | { kind: 'command'; label: string; command: string; args: readonly string[]; cwd: string }\n | { kind: 'vitest'; label: string; args?: readonly string[]; cwd: string }\n | {\n kind: 'playwright';\n label: string;\n cwd: string;\n flakyLogPath: string;\n clearBeforeRun?: readonly string[];\n };\n\nexport interface LiveService {\n name: string;\n port: number;\n}\n\nexport interface GateStage {\n id: string;\n description: string;\n stopOnFailure: boolean;\n steps: () => readonly GateStep[];\n services?: readonly LiveService[];\n startHint?: string;\n}\n\nexport interface QuietGateConfig {\n title: string;\n script: string;\n stages: readonly GateStage[];\n}\n\nconst RED = '\\x1b[31m';\nconst GREEN = '\\x1b[32m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\nconst DIM = '\\x1b[2m';\nconst BOLD = '\\x1b[1m';\nconst RESET = '\\x1b[0m';\n\ntype Totals = { passed: number; failed: number; skipped: number; flaky?: number };\ntype StepResult = { name: string; ok?: boolean; skipped?: boolean; totals?: Totals | null };\n\nexport type GateSelection =\n | { kind: 'help' }\n | { kind: 'usage-error'; message: string }\n | { kind: 'run'; only: ReadonlySet<string> | null };\n\nexport function selectStages(argv: readonly string[], stageIds: readonly string[]): GateSelection {\n if (argv.includes('--help') || argv.includes('-h')) return { kind: 'help' };\n const eq = argv.find((a) => a.startsWith('--only='));\n const at = argv.indexOf('--only');\n let onlyRaw: string | null = eq\n ? eq.slice('--only='.length)\n : at >= 0 && at + 1 < argv.length && !argv[at + 1]!.startsWith('--')\n ? argv[at + 1]!\n : null;\n const onlyGiven = argv.some((a) => a === '--only' || a.startsWith('--only='));\n if (!onlyGiven) {\n const shortcuts = stageIds.filter((id) => argv.includes(`--${id}`));\n if (shortcuts.length > 0) onlyRaw = shortcuts.join(',');\n }\n const only = onlyRaw\n ? new Set(\n onlyRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n )\n : null;\n const valid = `Valid stages: ${stageIds.join(', ')}`;\n if (onlyGiven && (!only || only.size === 0)) {\n return { kind: 'usage-error', message: `--only names no stage\\n${valid}` };\n }\n if (only) {\n const unknown = [...only].filter((s) => !stageIds.includes(s));\n if (unknown.length > 0) {\n return { kind: 'usage-error', message: `Unknown stage(s): ${unknown.join(', ')}\\n${valid}` };\n }\n }\n return { kind: 'run', only };\n}\n\nfunction fmtTime(ms: number): string {\n if (ms < 1000) return `${ms.toFixed(0)}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60000)}m${Math.floor((ms % 60000) / 1000)}s`;\n}\n\nfunction probePort(port: number, host = '127.0.0.1', timeoutMs = 500): Promise<boolean> {\n return new Promise((resolve) => {\n const sock = new net.Socket();\n let done = false;\n const finish = (ok: boolean): void => {\n if (done) return;\n done = true;\n sock.destroy();\n resolve(ok);\n };\n sock.setTimeout(timeoutMs);\n sock.once('connect', () => finish(true));\n sock.once('timeout', () => finish(false));\n sock.once('error', () => finish(false));\n sock.connect(port, host);\n });\n}\n\nconst write = (text: string): void => {\n process.stdout.write(text);\n};\n\nclass Heartbeat {\n private timer: NodeJS.Timeout | null = null;\n private start = 0;\n private name = '';\n private lineLen = 0;\n private readonly interactive = Boolean(process.stdout.isTTY);\n\n begin(name: string): void {\n this.name = name;\n this.start = performance.now();\n this.lineLen = 0;\n if (this.interactive) {\n this.paint();\n this.timer = setInterval(() => this.paint(), 1000);\n } else {\n write(`${CYAN}▶${RESET} ${name}...\\n`);\n }\n }\n\n end(finalLine: string): void {\n this.clear();\n write(`${finalLine}\\n`);\n }\n\n clear(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.interactive && this.lineLen > 0) write(`\\r${' '.repeat(this.lineLen)}\\r`);\n this.lineLen = 0;\n }\n\n private paint(): void {\n const line = `${CYAN}▶${RESET} ${this.name}... ${DIM}(${fmtTime(performance.now() - this.start)} elapsed)${RESET}`;\n write(`\\r${line}${' '.repeat(Math.max(0, this.lineLen - line.length))}`);\n this.lineLen = line.length;\n }\n}\n\nfunction printFailures(failures: readonly TestFailure[]): void {\n for (const f of failures) {\n write(` ${YELLOW}${f.title}${RESET}\\n ${DIM}${f.file}${RESET}\\n`);\n for (const msg of f.messages) {\n write(\n `${DIM}${msg\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n')}${RESET}\\n`,\n );\n }\n write('\\n');\n }\n}\n\nfunction printRawTail(tool: string, code: number, stdout: string, stderr: string): void {\n write(\n `${DIM}${tool} exited with code ${code} but the JSON report contains no failures.${RESET}\\n`,\n );\n write(`${DIM}Raw stderr (truncated):${RESET}\\n${DIM}${stderr.trim().slice(0, 4000)}${RESET}\\n`);\n write(\n `${DIM}Raw stdout (truncated, JSON portion likely present):${RESET}\\n${DIM}${stdout.trim().slice(0, 4000)}${RESET}\\n\\n`,\n );\n}\n\nfunction detailOf(totals: Totals, elapsed: number, loadFailures = 0): string {\n const loads = loadFailures\n ? `, ${loadFailures} ${loadFailures === 1 ? 'file' : 'files'} failed to load`\n : '';\n return `${totals.passed} passed${totals.failed ? `, ${totals.failed} failed` : ''}${loads}${totals.skipped ? `, ${totals.skipped} skipped` : ''}${totals.flaky ? `, ${totals.flaky} flaky` : ''} · ${fmtTime(elapsed)}`;\n}\n\nexport async function runQuietGate(\n config: QuietGateConfig,\n argv: readonly string[] = process.argv.slice(2),\n): Promise<never> {\n const stageIds = config.stages.map((s) => s.id);\n const selection = selectStages(argv, stageIds);\n if (selection.kind === 'help') {\n const width = Math.max(...stageIds.map((id) => id.length)) + 4;\n write(\n `\\nUsage: node ${config.script} [options]\\n\\nOptions:\\n` +\n ` --only <stages> Comma-separated list of stages to run.\\n` +\n ` Stages: ${stageIds.join(', ')}\\n` +\n config.stages.map((s) => ` --${s.id.padEnd(width)}${s.description}\\n`).join('') +\n ` -h, --help Show this help and exit\\n\\n`,\n );\n process.exit(0);\n }\n if (selection.kind === 'usage-error') {\n const [first, ...rest] = selection.message.split('\\n');\n process.stderr.write(`${RED}${first}${RESET}\\n${rest.join('\\n')}\\n`);\n process.exit(2);\n }\n const { only } = selection;\n\n const heartbeat = new Heartbeat();\n process.on('SIGINT', () => {\n heartbeat.clear();\n process.exit(130);\n });\n process.on('SIGTERM', () => {\n heartbeat.clear();\n process.exit(143);\n });\n process.on('exit', () => heartbeat.clear());\n\n const results: StepResult[] = [];\n const ok = (name: string, detail: string): void =>\n heartbeat.end(`${GREEN}✓${RESET} ${name} ${DIM}(${detail})${RESET}`);\n const fail = (name: string, detail: string): void =>\n heartbeat.end(`${RED}✖${RESET} ${name} ${DIM}(${detail})${RESET}`);\n\n async function commandStep(step: Extract<GateStep, { kind: 'command' }>): Promise<boolean> {\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const { code, stdout, stderr } = await runCommand(step.command, step.args, { cwd: step.cwd });\n const elapsed = performance.now() - t0;\n if (code === 0) {\n ok(step.label, fmtTime(elapsed));\n results.push({ name: step.label, ok: true });\n return true;\n }\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false });\n return false;\n }\n\n async function vitestStep(step: Extract<GateStep, { kind: 'vitest' }>): Promise<boolean> {\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const { code, stdout, stderr } = await runCommand(\n 'npx',\n ['vitest', 'run', '--reporter=json', ...(step.args ?? [])],\n { cwd: step.cwd },\n );\n const elapsed = performance.now() - t0;\n const { failures, suiteFailures, totals, skippedTests } = collectVitestFailures(\n parseVitestJson(stdout),\n );\n if (!totals) {\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}Could not parse vitest JSON output.${RESET}\\n`);\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false, totals: null });\n return false;\n }\n const verdict = vitestStageVerdict({ code, totals, suiteFailures });\n const detail = detailOf(totals, elapsed, suiteFailures.length);\n if (verdict.ok) {\n ok(step.label, detail);\n results.push({ name: step.label, ok: true, totals });\n return true;\n }\n fail(step.label, detail);\n if (verdict.skippedReason) {\n write(`${YELLOW}${verdict.skippedReason}${RESET}\\n`);\n for (const s of skippedTests) {\n write(\n ` ${YELLOW}${s.title}${RESET} ${DIM}(${s.status})${RESET}\\n ${DIM}${s.file}${RESET}\\n`,\n );\n }\n write('\\n');\n }\n if (suiteFailures.length > 0) {\n write(`${YELLOW}${formatSuiteFailures(suiteFailures)}${RESET}\\n\\n`);\n }\n if (failures.length === 0 && suiteFailures.length === 0 && code !== 0) {\n // The JSON reporter records an unhandled error against no test.\n const unhandled = formatUnhandledErrorReport(`${stderr}\\n${stdout}`);\n if (unhandled) write(`${YELLOW}${unhandled}${RESET}\\n\\n`);\n printRawTail('Vitest', code, stdout, stderr);\n }\n printFailures(failures);\n results.push({ name: step.label, ok: false, totals });\n return false;\n }\n\n async function playwrightStep(step: Extract<GateStep, { kind: 'playwright' }>): Promise<boolean> {\n for (const target of step.clearBeforeRun ?? []) {\n rmSync(path.join(step.cwd, target), { recursive: true, force: true });\n }\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const reportDir = mkdtempSync(path.join(os.tmpdir(), 'pw-quiet-'));\n const reportPath = path.join(reportDir, 'report.json');\n const { code, stdout, stderr } = await runCommand(\n 'npx',\n ['playwright', 'test', '--reporter=json'],\n {\n cwd: step.cwd,\n env: { ...process.env, PLAYWRIGHT_JSON_OUTPUT_NAME: reportPath },\n },\n );\n const elapsed = performance.now() - t0;\n const report = ((): PlaywrightJsonReport | null => {\n try {\n return JSON.parse(\n existsSync(reportPath) ? readFileSync(reportPath, 'utf8') : stdout.trim(),\n ) as PlaywrightJsonReport;\n } catch {\n return null;\n }\n })();\n rmSync(reportDir, { recursive: true, force: true });\n if (!report) {\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}Could not parse playwright JSON output.${RESET}\\n`);\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false });\n return false;\n }\n const { failures, flakyTests, totals } = collectPlaywrightFailures(report);\n appendFlakyLog(path.join(step.cwd, step.flakyLogPath), flakyTests);\n const green = code === 0 && totals.failed === 0 && totals.flaky === 0 && totals.skipped === 0;\n const detail = detailOf(totals, elapsed);\n if (green) {\n ok(step.label, detail);\n results.push({ name: step.label, ok: true, totals });\n return true;\n }\n fail(step.label, detail);\n if (totals.skipped > 0) {\n write(`${DIM}${totals.skipped} skipped test(s) make this stage non-green.${RESET}\\n`);\n }\n if (failures.length === 0 && code !== 0) printRawTail('Playwright', code, stdout, stderr);\n printFailures(failures);\n for (const flaky of flakyTests) {\n write(` ${YELLOW}retry-pass: ${flaky.title}${RESET}\\n ${DIM}${flaky.file}${RESET}\\n`);\n write(\n ` ${DIM}Passed only after retry; the zero-flake gate requires a fix before handoff.${RESET}\\n\\n`,\n );\n }\n results.push({ name: step.label, ok: false, totals: totals as PlaywrightTotals });\n return false;\n }\n\n const runStep = (step: GateStep): Promise<boolean> =>\n step.kind === 'command'\n ? commandStep(step)\n : step.kind === 'vitest'\n ? vitestStep(step)\n : playwrightStep(step);\n\n const overallStart = performance.now();\n write(\n only\n ? `${BOLD}Running ${config.title}${RESET} ${DIM}(only: ${[...only].join(', ')})${RESET}\\n\\n`\n : `${BOLD}Running ${config.title}${RESET}\\n\\n`,\n );\n\n stages: for (const stage of config.stages) {\n if (only && !only.has(stage.id)) continue;\n const steps = stage.steps();\n if (stage.services?.length) {\n const probes = await Promise.all(\n stage.services.map((s) => probePort(s.port).then((up) => ({ ...s, up }))),\n );\n const down = probes.filter((p) => !p.up).map((p) => p.name);\n if (down.length > 0) {\n for (const step of steps) {\n if (only?.has(stage.id)) {\n write(\n `${RED}✖${RESET} ${step.label} ${DIM}(local services not running: ${down.join(', ')})${RESET}\\n`,\n );\n write(`${DIM} ${stage.startHint ?? 'start the local stack'}, then rerun${RESET}\\n`);\n results.push({ name: step.label, ok: false });\n } else {\n write(\n `${YELLOW}⊘${RESET} ${step.label} ${DIM}(skipped — local services not running: ${down.join(', ')})${RESET}\\n`,\n );\n results.push({ name: step.label, skipped: true });\n }\n }\n continue;\n }\n }\n for (const step of steps) {\n const passed = await runStep(step);\n if (!passed && stage.stopOnFailure) break stages;\n }\n }\n\n return finish(results, performance.now() - overallStart);\n}\n\nfunction appendFlakyLog(logPath: string, flakyTests: readonly FlakyTest[]): void {\n if (flakyTests.length === 0) return;\n try {\n if (!existsSync(logPath)) writeFileSync(logPath, FLAKY_LOG_HEADER);\n appendFileSync(logPath, `${flakyLogRows(flakyTests, new Date())}\\n`);\n write(`${YELLOW}⚑${RESET} ${flakyTests.length} retry-pass(es) appended to ${logPath}\\n`);\n } catch (error) {\n write(\n `${DIM}Could not append to ${logPath}: ${error instanceof Error ? error.message : String(error)}${RESET}\\n`,\n );\n }\n}\n\nfunction finish(results: readonly StepResult[], total: number): never {\n const failed = results.filter((r) => r.ok === false);\n const skipped = results.filter((r) => r.skipped);\n write(`\\n${BOLD}Summary${RESET} ${DIM}(${fmtTime(total)})${RESET}\\n`);\n for (const r of results) {\n if (r.skipped) {\n write(` ${YELLOW}⊘${RESET} ${r.name} ${DIM}(skipped)${RESET}\\n`);\n continue;\n }\n const t = r.totals;\n const counts = t\n ? `${t.passed} passed${t.failed || !r.ok ? `, ${t.failed} failed` : ''}${t.skipped ? `, ${t.skipped} skipped` : ''}${t.flaky ? `, ${t.flaky} flaky` : ''}`\n : r.ok\n ? 'ok'\n : 'failed';\n write(` ${r.ok ? `${GREEN}✓` : `${RED}✖`}${RESET} ${r.name} ${DIM}(${counts})${RESET}\\n`);\n }\n if (failed.length > 0) {\n write(\n `\\n${RED}${BOLD}${failed.length} stage${failed.length === 1 ? '' : 's'} failed${RESET}\\n`,\n );\n process.exit(1);\n }\n if (results.length === 0) {\n write(`\\n${YELLOW}${BOLD}No stages ran${RESET}\\n`);\n process.exit(0);\n }\n if (skipped.length > 0) {\n write(\n `\\n${YELLOW}${BOLD}All run stages passed${RESET} ${DIM}(${skipped.length} skipped)${RESET}\\n`,\n );\n process.exit(0);\n }\n write(`\\n${GREEN}${BOLD}All stages passed${RESET}\\n`);\n process.exit(0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"quiet-gate.js","sourceRoot":"","sources":["../../../src/node/tooling/quiet-gate.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n appendFileSync,\n existsSync,\n mkdtempSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport net from 'node:net';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { performance } from 'node:perf_hooks';\nimport {\n collectPlaywrightFailures,\n FLAKY_LOG_HEADER,\n flakyLogRows,\n type FlakyTest,\n type PlaywrightJsonReport,\n type PlaywrightTotals,\n} from './playwright-report.js';\nimport {\n collectVitestFailures,\n formatSuiteFailures,\n parseVitestJson,\n vitestStageVerdict,\n type TestFailure,\n} from './vitest-report.js';\nimport { formatUnhandledErrorReport } from './vitest-unhandled-errors.js';\nimport { runCommand } from './shell.js';\n\nexport type GateStep =\n | { kind: 'command'; label: string; command: string; args: readonly string[]; cwd: string }\n | { kind: 'vitest'; label: string; args?: readonly string[]; cwd: string }\n | {\n kind: 'playwright';\n label: string;\n cwd: string;\n flakyLogPath: string;\n clearBeforeRun?: readonly string[];\n };\n\nexport interface LiveService {\n name: string;\n port: number;\n}\n\nexport const GATE_PHASES = ['start', 'live'] as const;\nexport type GatePhase = (typeof GATE_PHASES)[number];\n\nexport interface GateStage {\n id: string;\n description: string;\n phase?: GatePhase;\n stopOnFailure: boolean;\n steps: () => readonly GateStep[];\n services?: readonly LiveService[];\n startHint?: string;\n}\n\nexport interface QuietGateConfig {\n title: string;\n script: string;\n stages: readonly GateStage[];\n}\n\nconst RED = '\\x1b[31m';\nconst GREEN = '\\x1b[32m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\nconst DIM = '\\x1b[2m';\nconst BOLD = '\\x1b[1m';\nconst RESET = '\\x1b[0m';\n\ntype Totals = { passed: number; failed: number; skipped: number; flaky?: number };\ntype StepResult = { name: string; ok?: boolean; skipped?: boolean; totals?: Totals | null };\n\nexport type GateSelection =\n | { kind: 'help' }\n | { kind: 'usage-error'; message: string }\n | { kind: 'run'; only: ReadonlySet<string> | null };\n\nexport function selectStages(\n argv: readonly string[],\n stageIds: readonly string[],\n phases: Readonly<Record<string, GatePhase | undefined>> = {},\n): GateSelection {\n if (argv.includes('--help') || argv.includes('-h')) return { kind: 'help' };\n const phaseEq = argv.find((a) => a.startsWith('--phase='));\n const phaseAt = argv.indexOf('--phase');\n if (phaseEq || phaseAt >= 0) {\n const phase = phaseEq ? phaseEq.slice('--phase='.length) : (argv[phaseAt + 1] ?? '');\n if (!(GATE_PHASES as readonly string[]).includes(phase)) {\n return {\n kind: 'usage-error',\n message: `Unknown phase: ${phase || '(none)'}\\nValid phases: ${GATE_PHASES.join(', ')}`,\n };\n }\n const namesStages =\n argv.some((a) => a === '--only' || a.startsWith('--only=')) ||\n stageIds.some((id) => argv.includes(`--${id}`));\n if (namesStages) {\n return {\n kind: 'usage-error',\n message: '--phase runs a whole phase and takes no --only or stage flag',\n };\n }\n const only = new Set(stageIds.filter((id) => (phases[id] ?? 'start') === phase));\n if (only.size === 0) {\n return { kind: 'usage-error', message: `The ${phase} phase declares no stage` };\n }\n return { kind: 'run', only };\n }\n const eq = argv.find((a) => a.startsWith('--only='));\n const at = argv.indexOf('--only');\n let onlyRaw: string | null = eq\n ? eq.slice('--only='.length)\n : at >= 0 && at + 1 < argv.length && !argv[at + 1]!.startsWith('--')\n ? argv[at + 1]!\n : null;\n const onlyGiven = argv.some((a) => a === '--only' || a.startsWith('--only='));\n if (!onlyGiven) {\n const shortcuts = stageIds.filter((id) => argv.includes(`--${id}`));\n if (shortcuts.length > 0) onlyRaw = shortcuts.join(',');\n }\n const only = onlyRaw\n ? new Set(\n onlyRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n )\n : null;\n const valid = `Valid stages: ${stageIds.join(', ')}`;\n if (onlyGiven && (!only || only.size === 0)) {\n return { kind: 'usage-error', message: `--only names no stage\\n${valid}` };\n }\n if (only) {\n const unknown = [...only].filter((s) => !stageIds.includes(s));\n if (unknown.length > 0) {\n return { kind: 'usage-error', message: `Unknown stage(s): ${unknown.join(', ')}\\n${valid}` };\n }\n }\n return { kind: 'run', only };\n}\n\nfunction fmtTime(ms: number): string {\n if (ms < 1000) return `${ms.toFixed(0)}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60000)}m${Math.floor((ms % 60000) / 1000)}s`;\n}\n\nfunction probePort(port: number, host = '127.0.0.1', timeoutMs = 500): Promise<boolean> {\n return new Promise((resolve) => {\n const sock = new net.Socket();\n let done = false;\n const finish = (ok: boolean): void => {\n if (done) return;\n done = true;\n sock.destroy();\n resolve(ok);\n };\n sock.setTimeout(timeoutMs);\n sock.once('connect', () => finish(true));\n sock.once('timeout', () => finish(false));\n sock.once('error', () => finish(false));\n sock.connect(port, host);\n });\n}\n\nconst write = (text: string): void => {\n process.stdout.write(text);\n};\n\nclass Heartbeat {\n private timer: NodeJS.Timeout | null = null;\n private start = 0;\n private name = '';\n private lineLen = 0;\n private readonly interactive = Boolean(process.stdout.isTTY);\n\n begin(name: string): void {\n this.name = name;\n this.start = performance.now();\n this.lineLen = 0;\n if (this.interactive) {\n this.paint();\n this.timer = setInterval(() => this.paint(), 1000);\n } else {\n write(`${CYAN}▶${RESET} ${name}...\\n`);\n }\n }\n\n end(finalLine: string): void {\n this.clear();\n write(`${finalLine}\\n`);\n }\n\n clear(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.interactive && this.lineLen > 0) write(`\\r${' '.repeat(this.lineLen)}\\r`);\n this.lineLen = 0;\n }\n\n private paint(): void {\n const line = `${CYAN}▶${RESET} ${this.name}... ${DIM}(${fmtTime(performance.now() - this.start)} elapsed)${RESET}`;\n write(`\\r${line}${' '.repeat(Math.max(0, this.lineLen - line.length))}`);\n this.lineLen = line.length;\n }\n}\n\nfunction printFailures(failures: readonly TestFailure[]): void {\n for (const f of failures) {\n write(` ${YELLOW}${f.title}${RESET}\\n ${DIM}${f.file}${RESET}\\n`);\n for (const msg of f.messages) {\n write(\n `${DIM}${msg\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n')}${RESET}\\n`,\n );\n }\n write('\\n');\n }\n}\n\nfunction printRawTail(tool: string, code: number, stdout: string, stderr: string): void {\n write(\n `${DIM}${tool} exited with code ${code} but the JSON report contains no failures.${RESET}\\n`,\n );\n write(`${DIM}Raw stderr (truncated):${RESET}\\n${DIM}${stderr.trim().slice(0, 4000)}${RESET}\\n`);\n write(\n `${DIM}Raw stdout (truncated, JSON portion likely present):${RESET}\\n${DIM}${stdout.trim().slice(0, 4000)}${RESET}\\n\\n`,\n );\n}\n\nfunction detailOf(totals: Totals, elapsed: number, loadFailures = 0): string {\n const loads = loadFailures\n ? `, ${loadFailures} ${loadFailures === 1 ? 'file' : 'files'} failed to load`\n : '';\n return `${totals.passed} passed${totals.failed ? `, ${totals.failed} failed` : ''}${loads}${totals.skipped ? `, ${totals.skipped} skipped` : ''}${totals.flaky ? `, ${totals.flaky} flaky` : ''} · ${fmtTime(elapsed)}`;\n}\n\nexport async function runQuietGate(\n config: QuietGateConfig,\n argv: readonly string[] = process.argv.slice(2),\n): Promise<never> {\n const stageIds = config.stages.map((s) => s.id);\n const selection = selectStages(\n argv,\n stageIds,\n Object.fromEntries(config.stages.map((s) => [s.id, s.phase])),\n );\n if (selection.kind === 'help') {\n const width = Math.max(...stageIds.map((id) => id.length)) + 4;\n write(\n `\\nUsage: node ${config.script} [options]\\n\\nOptions:\\n` +\n ` --phase <phase> Run every stage of one phase: ${GATE_PHASES.join(', ')}.\\n` +\n ` --only <stages> Comma-separated list of stages to run.\\n` +\n ` Stages: ${stageIds.join(', ')}\\n` +\n config.stages.map((s) => ` --${s.id.padEnd(width)}${s.description}\\n`).join('') +\n ` -h, --help Show this help and exit\\n\\n`,\n );\n process.exit(0);\n }\n if (selection.kind === 'usage-error') {\n const [first, ...rest] = selection.message.split('\\n');\n process.stderr.write(`${RED}${first}${RESET}\\n${rest.join('\\n')}\\n`);\n process.exit(2);\n }\n const { only } = selection;\n\n const heartbeat = new Heartbeat();\n process.on('SIGINT', () => {\n heartbeat.clear();\n process.exit(130);\n });\n process.on('SIGTERM', () => {\n heartbeat.clear();\n process.exit(143);\n });\n process.on('exit', () => heartbeat.clear());\n\n const results: StepResult[] = [];\n const ok = (name: string, detail: string): void =>\n heartbeat.end(`${GREEN}✓${RESET} ${name} ${DIM}(${detail})${RESET}`);\n const fail = (name: string, detail: string): void =>\n heartbeat.end(`${RED}✖${RESET} ${name} ${DIM}(${detail})${RESET}`);\n\n async function commandStep(step: Extract<GateStep, { kind: 'command' }>): Promise<boolean> {\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const { code, stdout, stderr } = await runCommand(step.command, step.args, { cwd: step.cwd });\n const elapsed = performance.now() - t0;\n if (code === 0) {\n ok(step.label, fmtTime(elapsed));\n results.push({ name: step.label, ok: true });\n return true;\n }\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false });\n return false;\n }\n\n async function vitestStep(step: Extract<GateStep, { kind: 'vitest' }>): Promise<boolean> {\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const { code, stdout, stderr } = await runCommand(\n 'npx',\n ['vitest', 'run', '--reporter=json', ...(step.args ?? [])],\n { cwd: step.cwd },\n );\n const elapsed = performance.now() - t0;\n const { failures, suiteFailures, totals, skippedTests } = collectVitestFailures(\n parseVitestJson(stdout),\n );\n if (!totals) {\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}Could not parse vitest JSON output.${RESET}\\n`);\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false, totals: null });\n return false;\n }\n const verdict = vitestStageVerdict({ code, totals, suiteFailures });\n const detail = detailOf(totals, elapsed, suiteFailures.length);\n if (verdict.ok) {\n ok(step.label, detail);\n results.push({ name: step.label, ok: true, totals });\n return true;\n }\n fail(step.label, detail);\n if (verdict.skippedReason) {\n write(`${YELLOW}${verdict.skippedReason}${RESET}\\n`);\n for (const s of skippedTests) {\n write(\n ` ${YELLOW}${s.title}${RESET} ${DIM}(${s.status})${RESET}\\n ${DIM}${s.file}${RESET}\\n`,\n );\n }\n write('\\n');\n }\n if (suiteFailures.length > 0) {\n write(`${YELLOW}${formatSuiteFailures(suiteFailures)}${RESET}\\n\\n`);\n }\n if (failures.length === 0 && suiteFailures.length === 0 && code !== 0) {\n // The JSON reporter records an unhandled error against no test.\n const unhandled = formatUnhandledErrorReport(`${stderr}\\n${stdout}`);\n if (unhandled) write(`${YELLOW}${unhandled}${RESET}\\n\\n`);\n printRawTail('Vitest', code, stdout, stderr);\n }\n printFailures(failures);\n results.push({ name: step.label, ok: false, totals });\n return false;\n }\n\n async function playwrightStep(step: Extract<GateStep, { kind: 'playwright' }>): Promise<boolean> {\n for (const target of step.clearBeforeRun ?? []) {\n rmSync(path.join(step.cwd, target), { recursive: true, force: true });\n }\n heartbeat.begin(step.label);\n const t0 = performance.now();\n const reportDir = mkdtempSync(path.join(os.tmpdir(), 'pw-quiet-'));\n const reportPath = path.join(reportDir, 'report.json');\n const { code, stdout, stderr } = await runCommand(\n 'npx',\n ['playwright', 'test', '--reporter=json'],\n {\n cwd: step.cwd,\n env: { ...process.env, PLAYWRIGHT_JSON_OUTPUT_NAME: reportPath },\n },\n );\n const elapsed = performance.now() - t0;\n const report = ((): PlaywrightJsonReport | null => {\n try {\n return JSON.parse(\n existsSync(reportPath) ? readFileSync(reportPath, 'utf8') : stdout.trim(),\n ) as PlaywrightJsonReport;\n } catch {\n return null;\n }\n })();\n rmSync(reportDir, { recursive: true, force: true });\n if (!report) {\n fail(step.label, fmtTime(elapsed));\n write(`${DIM}Could not parse playwright JSON output.${RESET}\\n`);\n write(`${DIM}${`${stdout}\\n${stderr}`.trim().slice(0, 4000)}${RESET}\\n\\n`);\n results.push({ name: step.label, ok: false });\n return false;\n }\n const { failures, flakyTests, totals } = collectPlaywrightFailures(report);\n appendFlakyLog(path.join(step.cwd, step.flakyLogPath), flakyTests);\n const green = code === 0 && totals.failed === 0 && totals.flaky === 0 && totals.skipped === 0;\n const detail = detailOf(totals, elapsed);\n if (green) {\n ok(step.label, detail);\n results.push({ name: step.label, ok: true, totals });\n return true;\n }\n fail(step.label, detail);\n if (totals.skipped > 0) {\n write(`${DIM}${totals.skipped} skipped test(s) make this stage non-green.${RESET}\\n`);\n }\n if (failures.length === 0 && code !== 0) printRawTail('Playwright', code, stdout, stderr);\n printFailures(failures);\n for (const flaky of flakyTests) {\n write(` ${YELLOW}retry-pass: ${flaky.title}${RESET}\\n ${DIM}${flaky.file}${RESET}\\n`);\n write(\n ` ${DIM}Passed only after retry; the zero-flake gate requires a fix before handoff.${RESET}\\n\\n`,\n );\n }\n results.push({ name: step.label, ok: false, totals: totals as PlaywrightTotals });\n return false;\n }\n\n const runStep = (step: GateStep): Promise<boolean> =>\n step.kind === 'command'\n ? commandStep(step)\n : step.kind === 'vitest'\n ? vitestStep(step)\n : playwrightStep(step);\n\n const overallStart = performance.now();\n write(\n only\n ? `${BOLD}Running ${config.title}${RESET} ${DIM}(only: ${[...only].join(', ')})${RESET}\\n\\n`\n : `${BOLD}Running ${config.title}${RESET}\\n\\n`,\n );\n\n stages: for (const stage of config.stages) {\n if (only && !only.has(stage.id)) continue;\n const steps = stage.steps();\n if (stage.services?.length) {\n const probes = await Promise.all(\n stage.services.map((s) => probePort(s.port).then((up) => ({ ...s, up }))),\n );\n const down = probes.filter((p) => !p.up).map((p) => p.name);\n if (down.length > 0) {\n for (const step of steps) {\n if (only?.has(stage.id)) {\n write(\n `${RED}✖${RESET} ${step.label} ${DIM}(local services not running: ${down.join(', ')})${RESET}\\n`,\n );\n write(`${DIM} ${stage.startHint ?? 'start the local stack'}, then rerun${RESET}\\n`);\n results.push({ name: step.label, ok: false });\n } else {\n write(\n `${YELLOW}⊘${RESET} ${step.label} ${DIM}(skipped — local services not running: ${down.join(', ')})${RESET}\\n`,\n );\n results.push({ name: step.label, skipped: true });\n }\n }\n continue;\n }\n }\n for (const step of steps) {\n const passed = await runStep(step);\n if (!passed && stage.stopOnFailure) break stages;\n }\n }\n\n return finish(results, performance.now() - overallStart);\n}\n\nfunction appendFlakyLog(logPath: string, flakyTests: readonly FlakyTest[]): void {\n if (flakyTests.length === 0) return;\n try {\n if (!existsSync(logPath)) writeFileSync(logPath, FLAKY_LOG_HEADER);\n appendFileSync(logPath, `${flakyLogRows(flakyTests, new Date())}\\n`);\n write(`${YELLOW}⚑${RESET} ${flakyTests.length} retry-pass(es) appended to ${logPath}\\n`);\n } catch (error) {\n write(\n `${DIM}Could not append to ${logPath}: ${error instanceof Error ? error.message : String(error)}${RESET}\\n`,\n );\n }\n}\n\nfunction finish(results: readonly StepResult[], total: number): never {\n const failed = results.filter((r) => r.ok === false);\n const skipped = results.filter((r) => r.skipped);\n write(`\\n${BOLD}Summary${RESET} ${DIM}(${fmtTime(total)})${RESET}\\n`);\n for (const r of results) {\n if (r.skipped) {\n write(` ${YELLOW}⊘${RESET} ${r.name} ${DIM}(skipped)${RESET}\\n`);\n continue;\n }\n const t = r.totals;\n const counts = t\n ? `${t.passed} passed${t.failed || !r.ok ? `, ${t.failed} failed` : ''}${t.skipped ? `, ${t.skipped} skipped` : ''}${t.flaky ? `, ${t.flaky} flaky` : ''}`\n : r.ok\n ? 'ok'\n : 'failed';\n write(` ${r.ok ? `${GREEN}✓` : `${RED}✖`}${RESET} ${r.name} ${DIM}(${counts})${RESET}\\n`);\n }\n if (failed.length > 0) {\n write(\n `\\n${RED}${BOLD}${failed.length} stage${failed.length === 1 ? '' : 's'} failed${RESET}\\n`,\n );\n process.exit(1);\n }\n if (results.length === 0) {\n write(`\\n${YELLOW}${BOLD}No stages ran${RESET}\\n`);\n process.exit(0);\n }\n if (skipped.length > 0) {\n write(\n `\\n${YELLOW}${BOLD}All run stages passed${RESET} ${DIM}(${skipped.length} skipped)${RESET}\\n`,\n );\n process.exit(0);\n }\n write(`\\n${GREEN}${BOLD}All stages passed${RESET}\\n`);\n process.exit(0);\n}\n"]}
|