@telora/daemon 0.24.16 → 0.24.25
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/build-info.json +7 -3
- package/dist/ci/candidate-failure-record.d.ts +104 -0
- package/dist/ci/candidate-failure-record.d.ts.map +1 -0
- package/dist/ci/candidate-failure-record.js +135 -0
- package/dist/ci/candidate-failure-record.js.map +1 -0
- package/dist/ci/candidate-ref.d.ts.map +1 -1
- package/dist/ci/candidate-ref.js +10 -3
- package/dist/ci/candidate-ref.js.map +1 -1
- package/dist/ci/ci-status-git.d.ts.map +1 -1
- package/dist/ci/ci-status-git.js +1 -0
- package/dist/ci/ci-status-git.js.map +1 -1
- package/dist/ci/ci-status.d.ts.map +1 -1
- package/dist/ci/ci-status.js +1 -0
- package/dist/ci/ci-status.js.map +1 -1
- package/dist/ci/gate-ref.d.ts +10 -1
- package/dist/ci/gate-ref.d.ts.map +1 -1
- package/dist/ci/gate-ref.js +11 -4
- package/dist/ci/gate-ref.js.map +1 -1
- package/dist/ci/product-ci-repo.d.ts.map +1 -1
- package/dist/ci/product-ci-repo.js +3 -2
- package/dist/ci/product-ci-repo.js.map +1 -1
- package/dist/completion/review-exit/review-exit-phase.js +7 -3
- package/dist/completion/review-exit/review-exit-phase.js.map +1 -1
- package/dist/completion/review-exit/review-exit-rehoming.d.ts +27 -3
- package/dist/completion/review-exit/review-exit-rehoming.d.ts.map +1 -1
- package/dist/completion/review-exit/review-exit-rehoming.js +29 -5
- package/dist/completion/review-exit/review-exit-rehoming.js.map +1 -1
- package/dist/composition/execution-merge-context.d.ts +13 -0
- package/dist/composition/execution-merge-context.d.ts.map +1 -1
- package/dist/composition/execution-merge-context.js +76 -3
- package/dist/composition/execution-merge-context.js.map +1 -1
- package/dist/composition/focus-activity-live-sources.d.ts.map +1 -1
- package/dist/composition/focus-activity-live-sources.js +1 -0
- package/dist/composition/focus-activity-live-sources.js.map +1 -1
- package/dist/composition/runtime-heartbeat-context.d.ts +11 -0
- package/dist/composition/runtime-heartbeat-context.d.ts.map +1 -1
- package/dist/composition/runtime-heartbeat-context.js +26 -1
- package/dist/composition/runtime-heartbeat-context.js.map +1 -1
- package/dist/composition/team-liveness-phase-sources.d.ts.map +1 -1
- package/dist/composition/team-liveness-phase-sources.js +1 -0
- package/dist/composition/team-liveness-phase-sources.js.map +1 -1
- package/dist/composition/verification-context.d.ts.map +1 -1
- package/dist/composition/verification-context.js +34 -4
- package/dist/composition/verification-context.js.map +1 -1
- package/dist/focus/control-state.d.ts +12 -6
- package/dist/focus/control-state.d.ts.map +1 -1
- package/dist/focus/control-state.js +16 -9
- package/dist/focus/control-state.js.map +1 -1
- package/dist/focus/heartbeat-metadata.d.ts +5 -0
- package/dist/focus/heartbeat-metadata.d.ts.map +1 -1
- package/dist/focus/heartbeat-metadata.js +12 -0
- package/dist/focus/heartbeat-metadata.js.map +1 -1
- package/dist/focus/heartbeat.d.ts.map +1 -1
- package/dist/focus/heartbeat.js +1 -0
- package/dist/focus/heartbeat.js.map +1 -1
- package/dist/focus/host-pressure.d.ts +77 -0
- package/dist/focus/host-pressure.d.ts.map +1 -0
- package/dist/focus/host-pressure.js +83 -0
- package/dist/focus/host-pressure.js.map +1 -0
- package/dist/focus-stage-lifecycle/index.js +1 -1
- package/dist/focus-stage-lifecycle/index.js.map +1 -1
- package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts +17 -7
- package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts.map +1 -1
- package/dist/focus-stage-lifecycle/wedge-watchdog.js +58 -28
- package/dist/focus-stage-lifecycle/wedge-watchdog.js.map +1 -1
- package/dist/git/types.js +1 -1
- package/dist/merge/candidate-ci-failures.d.ts +72 -0
- package/dist/merge/candidate-ci-failures.d.ts.map +1 -0
- package/dist/merge/candidate-ci-failures.js +240 -0
- package/dist/merge/candidate-ci-failures.js.map +1 -0
- package/dist/merge/candidate-red-record.d.ts +44 -0
- package/dist/merge/candidate-red-record.d.ts.map +1 -0
- package/dist/merge/candidate-red-record.js +98 -0
- package/dist/merge/candidate-red-record.js.map +1 -0
- package/dist/merge/candidate-rework.d.ts +4 -3
- package/dist/merge/candidate-rework.d.ts.map +1 -1
- package/dist/merge/candidate-rework.js +46 -14
- package/dist/merge/candidate-rework.js.map +1 -1
- package/dist/merge/candidate-tip-attribution.d.ts +135 -0
- package/dist/merge/candidate-tip-attribution.d.ts.map +1 -0
- package/dist/merge/candidate-tip-attribution.js +319 -0
- package/dist/merge/candidate-tip-attribution.js.map +1 -0
- package/dist/merge/completion-merge-driver.d.ts +49 -5
- package/dist/merge/completion-merge-driver.d.ts.map +1 -1
- package/dist/merge/completion-merge-driver.js +56 -2
- package/dist/merge/completion-merge-driver.js.map +1 -1
- package/dist/merge/completion-merge-gate.d.ts +4 -1
- package/dist/merge/completion-merge-gate.d.ts.map +1 -1
- package/dist/merge/completion-merge-gate.js +9 -8
- package/dist/merge/completion-merge-gate.js.map +1 -1
- package/dist/queries/api-client/shared.d.ts.map +1 -1
- package/dist/queries/api-client/shared.js +6 -1
- package/dist/queries/api-client/shared.js.map +1 -1
- package/dist/queries/candidate-ci-reds/candidate-ci-reds.d.ts +35 -0
- package/dist/queries/candidate-ci-reds/candidate-ci-reds.d.ts.map +1 -0
- package/dist/queries/candidate-ci-reds/candidate-ci-reds.js +42 -0
- package/dist/queries/candidate-ci-reds/candidate-ci-reds.js.map +1 -0
- package/dist/queries/candidate-ci-reds/gate-escape-files.d.ts +16 -0
- package/dist/queries/candidate-ci-reds/gate-escape-files.d.ts.map +1 -0
- package/dist/queries/candidate-ci-reds/gate-escape-files.js +51 -0
- package/dist/queries/candidate-ci-reds/gate-escape-files.js.map +1 -0
- package/dist/queries/focuses/ended-arm.d.ts +55 -7
- package/dist/queries/focuses/ended-arm.d.ts.map +1 -1
- package/dist/queries/focuses/ended-arm.js +59 -8
- package/dist/queries/focuses/ended-arm.js.map +1 -1
- package/dist/queries/focuses/focus-discovery.d.ts +18 -8
- package/dist/queries/focuses/focus-discovery.d.ts.map +1 -1
- package/dist/queries/focuses/focus-discovery.js +1 -0
- package/dist/queries/focuses/focus-discovery.js.map +1 -1
- package/dist/queries/sessions/daemon-connection.d.ts.map +1 -1
- package/dist/queries/sessions/daemon-connection.js +1 -0
- package/dist/queries/sessions/daemon-connection.js.map +1 -1
- package/dist/queries/verification/verification.js +1 -1
- package/dist/queries/wire-schemas/schemas.d.ts +2 -0
- package/dist/queries/wire-schemas/schemas.d.ts.map +1 -1
- package/dist/queries/wire-schemas/schemas.js +10 -3
- package/dist/queries/wire-schemas/schemas.js.map +1 -1
- package/dist/resolvers/delivery-acceptance-criteria.d.ts +23 -1
- package/dist/resolvers/delivery-acceptance-criteria.d.ts.map +1 -1
- package/dist/resolvers/delivery-acceptance-criteria.js +52 -8
- package/dist/resolvers/delivery-acceptance-criteria.js.map +1 -1
- package/dist/shell/unified-shell.d.ts +25 -0
- package/dist/shell/unified-shell.d.ts.map +1 -1
- package/dist/shell/unified-shell.js +26 -80
- package/dist/shell/unified-shell.js.map +1 -1
- package/dist/shell/update-restart.d.ts +47 -0
- package/dist/shell/update-restart.d.ts.map +1 -0
- package/dist/shell/update-restart.js +124 -0
- package/dist/shell/update-restart.js.map +1 -0
- package/dist/supervision/escalation-suppression.js +1 -1
- package/dist/supervision/recorded-new-intent.d.ts +49 -0
- package/dist/supervision/recorded-new-intent.d.ts.map +1 -1
- package/dist/supervision/recorded-new-intent.js +10 -2
- package/dist/supervision/recorded-new-intent.js.map +1 -1
- package/dist/testing/fixtures/api-client.js +1 -1
- package/dist/testing/fixtures/completion-judge-stubs.d.ts +7 -2
- package/dist/testing/fixtures/completion-judge-stubs.d.ts.map +1 -1
- package/dist/testing/fixtures/completion-judge-stubs.js +11 -1
- package/dist/testing/fixtures/completion-judge-stubs.js.map +1 -1
- package/dist/testing/fixtures/index.js +1 -1
- package/dist/testing/fixtures/merge-log-capture.d.ts.map +1 -1
- package/dist/testing/fixtures/merge-log-capture.js +1 -0
- package/dist/testing/fixtures/merge-log-capture.js.map +1 -1
- package/dist/testing/fixtures/recording-api-client.js +1 -1
- package/dist/testing/fixtures/verification-deps.d.ts +7 -0
- package/dist/testing/fixtures/verification-deps.d.ts.map +1 -1
- package/dist/testing/fixtures/verification-deps.js +17 -1
- package/dist/testing/fixtures/verification-deps.js.map +1 -1
- package/dist/testing/fixtures/vitest-failure-log.d.ts.map +1 -1
- package/dist/testing/fixtures/vitest-failure-log.js +2 -1
- package/dist/testing/fixtures/vitest-failure-log.js.map +1 -1
- package/dist/update/auto-update.d.ts +11 -5
- package/dist/update/auto-update.d.ts.map +1 -1
- package/dist/update/auto-update.js +11 -5
- package/dist/update/auto-update.js.map +1 -1
- package/dist/update/restart-contract.d.ts +62 -0
- package/dist/update/restart-contract.d.ts.map +1 -0
- package/dist/update/restart-contract.js +137 -0
- package/dist/update/restart-contract.js.map +1 -0
- package/dist/verify/attribution/verification-baseline-run.d.ts.map +1 -1
- package/dist/verify/attribution/verification-baseline-run.js +1 -0
- package/dist/verify/attribution/verification-baseline-run.js.map +1 -1
- package/dist/verify/ci-gate/ci-gate-dispatch.d.ts +3 -0
- package/dist/verify/ci-gate/ci-gate-dispatch.d.ts.map +1 -1
- package/dist/verify/ci-gate/ci-gate-dispatch.js +31 -9
- package/dist/verify/ci-gate/ci-gate-dispatch.js.map +1 -1
- package/dist/verify/ci-gate/ci-gate-wait-record.d.ts +6 -0
- package/dist/verify/ci-gate/ci-gate-wait-record.d.ts.map +1 -1
- package/dist/verify/ci-gate/ci-gate-wait-record.js +1 -0
- package/dist/verify/ci-gate/ci-gate-wait-record.js.map +1 -1
- package/dist/verify/deterministic-gate/verification-checkout.d.ts +12 -2
- package/dist/verify/deterministic-gate/verification-checkout.d.ts.map +1 -1
- package/dist/verify/deterministic-gate/verification-checkout.js +18 -3
- package/dist/verify/deterministic-gate/verification-checkout.js.map +1 -1
- package/dist/verify/deterministic-gate/verification-deterministic.js +1 -1
- package/dist/verify/deterministic-gate/verification-failure-parser.d.ts +30 -9
- package/dist/verify/deterministic-gate/verification-failure-parser.d.ts.map +1 -1
- package/dist/verify/deterministic-gate/verification-failure-parser.js +52 -8
- package/dist/verify/deterministic-gate/verification-failure-parser.js.map +1 -1
- package/dist/verify/engine/verification-commit-sharing.d.ts.map +1 -1
- package/dist/verify/engine/verification-commit-sharing.js +6 -2
- package/dist/verify/engine/verification-commit-sharing.js.map +1 -1
- package/dist/verify/engine/verification-deps.d.ts +9 -0
- package/dist/verify/engine/verification-deps.d.ts.map +1 -1
- package/dist/verify/engine/verification-deps.js +1 -1
- package/dist/verify/engine/verification-engine.d.ts.map +1 -1
- package/dist/verify/engine/verification-engine.js +4 -1
- package/dist/verify/engine/verification-engine.js.map +1 -1
- package/dist/verify/escaped-tests/escaped-pass-store.d.ts +19 -0
- package/dist/verify/escaped-tests/escaped-pass-store.d.ts.map +1 -0
- package/dist/verify/escaped-tests/escaped-pass-store.js +90 -0
- package/dist/verify/escaped-tests/escaped-pass-store.js.map +1 -0
- package/dist/verify/escaped-tests/escaped-test-run.d.ts +39 -0
- package/dist/verify/escaped-tests/escaped-test-run.d.ts.map +1 -0
- package/dist/verify/escaped-tests/escaped-test-run.js +156 -0
- package/dist/verify/escaped-tests/escaped-test-run.js.map +1 -0
- package/dist/verify/escaped-tests/escaped-test-set.d.ts +65 -0
- package/dist/verify/escaped-tests/escaped-test-set.d.ts.map +1 -0
- package/dist/verify/escaped-tests/escaped-test-set.js +95 -0
- package/dist/verify/escaped-tests/escaped-test-set.js.map +1 -0
- package/dist/verify/escaped-tests/escaped-tests-source.d.ts +44 -0
- package/dist/verify/escaped-tests/escaped-tests-source.d.ts.map +1 -0
- package/dist/verify/escaped-tests/escaped-tests-source.js +142 -0
- package/dist/verify/escaped-tests/escaped-tests-source.js.map +1 -0
- package/dist/verify/gate-config/verification-manifest.d.ts +12 -1
- package/dist/verify/gate-config/verification-manifest.d.ts.map +1 -1
- package/dist/verify/gate-config/verification-manifest.js +12 -1
- package/dist/verify/gate-config/verification-manifest.js.map +1 -1
- package/dist/verify/gate-verdicts/commit-verdict-record.js +1 -1
- package/package.json +2 -2
- package/scripts/telora-daemon-wrapper.sh +16 -7
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/verify/ci-gate/ci-gate-dispatch.test.ts,
|
|
3
|
+
// packages/daemon/src/verify/escaped-tests/escaped-gate-run.test.ts,
|
|
4
|
+
// packages/daemon/src/verify/escaped-tests/escaped-test-run.test.ts,
|
|
5
|
+
// packages/daemon/src/verify/escaped-tests/escaped-tests-source.test.ts
|
|
6
|
+
// PINNED-BY-END
|
|
7
|
+
/**
|
|
8
|
+
* How escaped test files run INSIDE a gate run, and what the gate log then says
|
|
9
|
+
* about them. Pure.
|
|
10
|
+
*
|
|
11
|
+
* The gate run executes the gate command and THEN the product's declared re-run
|
|
12
|
+
* command over the escaped files (verify/failing-test-rerun/rerun-command.ts
|
|
13
|
+
* renderRerunCommand), in the same checkout and environment, as one POSIX shell
|
|
14
|
+
* script ({@link composeGateWithEscapedTests}). The local runner spawns it
|
|
15
|
+
* (`sh -c`); a CI-run gate ships it as the spec's command (scripts/ci-gate-run.sh
|
|
16
|
+
* runs it with bash). Either way the added run's output lands in the gate log
|
|
17
|
+
* after a marker block:
|
|
18
|
+
*
|
|
19
|
+
* (escaped tests: 2 file(s) a gate escape recorded)
|
|
20
|
+
* (escaped test: <first file>)
|
|
21
|
+
* (escaped test: <second file>)
|
|
22
|
+
* ...the re-run command's output...
|
|
23
|
+
* (escaped tests exit: 1; gate exit: 0)
|
|
24
|
+
*
|
|
25
|
+
* EXIT RULE: the script exits with the gate's own code when the gate failed,
|
|
26
|
+
* else with the added run's code -- so a failing escaped test fails the run, and
|
|
27
|
+
* every downstream reader (the failure parser, the same-commit flake retry,
|
|
28
|
+
* per-file base attribution, the rework Bug) sees its failures in the log with
|
|
29
|
+
* no path of its own. One exception is settled by the daemon after the run
|
|
30
|
+
* ({@link settleEscapedRun}): an added run that exited non-zero while naming NO
|
|
31
|
+
* failing test could not run the files (a file the re-run command's runner does
|
|
32
|
+
* not include, a crashed command). That is not evidence about the change, so it
|
|
33
|
+
* does not fail a gate that passed -- the stance per-file base attribution takes
|
|
34
|
+
* on an inconclusive run (verify/attribution/verification-baseline-files.ts).
|
|
35
|
+
*
|
|
36
|
+
* The gate's IDENTITY is untouched by any of this: the run applies and records
|
|
37
|
+
* the ORIGINAL gate command (appliedConfig, the per-commit verdict key, the CI
|
|
38
|
+
* spec key), so a verdict rendered with added files is read back under the
|
|
39
|
+
* gate's normal key.
|
|
40
|
+
*
|
|
41
|
+
* @module verify/escaped-tests/escaped-test-run
|
|
42
|
+
*/
|
|
43
|
+
import { parseFailingTests } from '../deterministic-gate/verification-failure-parser.js';
|
|
44
|
+
import { logRoots, renderRerunCommand, testFileOfId } from '../failing-test-rerun/rerun-command.js';
|
|
45
|
+
/** The marker line opening the added run's section of a gate log. */
|
|
46
|
+
export function escapedTestsMarker(count) {
|
|
47
|
+
return `(escaped tests: ${count} file(s) a gate escape recorded)`;
|
|
48
|
+
}
|
|
49
|
+
const MARKER_RE = /^\(escaped tests: (\d+) file\(s\) a gate escape recorded\)$/;
|
|
50
|
+
const FILE_RE = /^\(escaped test: (.+)\)$/;
|
|
51
|
+
const EXIT_RE = /^\(escaped tests exit: (\d+); gate exit: (\d+)\)$/;
|
|
52
|
+
// eslint-disable-next-line no-control-regex -- strips terminal colour codes from the log
|
|
53
|
+
const ANSI_RE = /\u001b\[[0-9;]*m/g;
|
|
54
|
+
/** POSIX single-quote one shell word, always. */
|
|
55
|
+
function quote(word) {
|
|
56
|
+
return `'${word.replace(/'/g, `'\\''`)}'`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The script that runs `gateCommand`, then the re-run command over `files`, and
|
|
60
|
+
* exits by the module's exit rule. Each command runs in its own subshell, on its
|
|
61
|
+
* own lines, so neither can end the other (an `exit`, a trailing comment). The
|
|
62
|
+
* added run's stderr joins its stdout, so its whole output lands in the log
|
|
63
|
+
* between the marker block and the exit line, in order, however the two streams
|
|
64
|
+
* of the run are read. Pure.
|
|
65
|
+
*/
|
|
66
|
+
export function composeGateWithEscapedTests(gateCommand, rerunTemplate, files) {
|
|
67
|
+
const markers = [escapedTestsMarker(files.length), ...files.map((f) => `(escaped test: ${f})`)].map(quote).join(' ');
|
|
68
|
+
return [
|
|
69
|
+
'(',
|
|
70
|
+
gateCommand,
|
|
71
|
+
')',
|
|
72
|
+
'__telora_gate_rc=$?',
|
|
73
|
+
`printf '%s\\n' ${markers}`,
|
|
74
|
+
'(',
|
|
75
|
+
renderRerunCommand(rerunTemplate, files),
|
|
76
|
+
') 2>&1',
|
|
77
|
+
'__telora_escaped_rc=$?',
|
|
78
|
+
`printf '(escaped tests exit: %s; gate exit: %s)\\n' "$__telora_escaped_rc" "$__telora_gate_rc"`,
|
|
79
|
+
'if [ "$__telora_gate_rc" -ne 0 ]; then exit "$__telora_gate_rc"; fi',
|
|
80
|
+
'exit "$__telora_escaped_rc"',
|
|
81
|
+
].join('\n');
|
|
82
|
+
}
|
|
83
|
+
/** The escaped-run section of a gate log, or null when the run added no files. Pure. */
|
|
84
|
+
export function readEscapedRun(logText) {
|
|
85
|
+
const lines = (typeof logText === 'string' ? logText : '').replace(ANSI_RE, '').split(/\r?\n/);
|
|
86
|
+
const start = lines.findIndex((line) => MARKER_RE.test(line.trim()));
|
|
87
|
+
if (start < 0)
|
|
88
|
+
return null;
|
|
89
|
+
const count = Number(MARKER_RE.exec(lines[start].trim())[1]);
|
|
90
|
+
const files = [];
|
|
91
|
+
let at = start + 1;
|
|
92
|
+
while (files.length < count && at < lines.length) {
|
|
93
|
+
const match = FILE_RE.exec(lines[at].trim());
|
|
94
|
+
if (!match)
|
|
95
|
+
break;
|
|
96
|
+
files.push(match[1]);
|
|
97
|
+
at++;
|
|
98
|
+
}
|
|
99
|
+
const end = lines.findIndex((line, index) => index >= at && EXIT_RE.test(line.trim()));
|
|
100
|
+
const exit = end >= 0 ? EXIT_RE.exec(lines[end].trim()) : null;
|
|
101
|
+
return {
|
|
102
|
+
files,
|
|
103
|
+
output: lines.slice(at, end >= 0 ? end : lines.length).join('\n'),
|
|
104
|
+
escapedExit: exit ? Number(exit[1]) : null,
|
|
105
|
+
gateExit: exit ? Number(exit[2]) : null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** True when the added run exited non-zero while naming no failing test (module doc). Pure. */
|
|
109
|
+
function isInconclusive(run) {
|
|
110
|
+
return run.escapedExit !== null && run.escapedExit !== 0 && parseFailingTests(run.output).size === 0;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The files the added run PASSED: every file when it exited 0; else every file
|
|
114
|
+
* none of whose failing tests is in its output -- provided each failing test
|
|
115
|
+
* names its file. No file when the run was cut short, could not run the files,
|
|
116
|
+
* or named a failure no file can be told from. Pure.
|
|
117
|
+
*/
|
|
118
|
+
export function passedEscapedFiles(logText) {
|
|
119
|
+
const run = readEscapedRun(logText);
|
|
120
|
+
if (run === null || run.escapedExit === null)
|
|
121
|
+
return [];
|
|
122
|
+
if (run.escapedExit === 0)
|
|
123
|
+
return [...run.files];
|
|
124
|
+
const ids = parseFailingTests(run.output);
|
|
125
|
+
if (ids.size === 0)
|
|
126
|
+
return [];
|
|
127
|
+
const roots = logRoots(logText);
|
|
128
|
+
const failing = new Set();
|
|
129
|
+
for (const id of ids) {
|
|
130
|
+
const file = testFileOfId(id, roots);
|
|
131
|
+
if (file === null)
|
|
132
|
+
return [];
|
|
133
|
+
failing.add(file);
|
|
134
|
+
}
|
|
135
|
+
return run.files.filter((file) => !failing.has(file));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The run's result with the one exception of the exit rule applied (module
|
|
139
|
+
* doc): a run whose gate passed and whose added run only failed INCONCLUSIVELY
|
|
140
|
+
* is the gate's pass. Every other result is returned unchanged. Pure.
|
|
141
|
+
*/
|
|
142
|
+
export function settleEscapedRun(result, logText) {
|
|
143
|
+
if (result.outcome !== 'failed' || result.timedOut)
|
|
144
|
+
return result;
|
|
145
|
+
const run = readEscapedRun(logText);
|
|
146
|
+
if (run === null || run.gateExit !== 0 || !isInconclusive(run))
|
|
147
|
+
return result;
|
|
148
|
+
return {
|
|
149
|
+
...result,
|
|
150
|
+
outcome: 'passed',
|
|
151
|
+
exitCode: 0,
|
|
152
|
+
rationale: `deterministic check passed (exit 0); the ${run.files.length} escaped test file(s) it added could not be run by the `
|
|
153
|
+
+ `declared re-run command (exit ${run.escapedExit}, no failing test named) -- not charged to the change`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=escaped-test-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escaped-test-run.js","sourceRoot":"","sources":["../../../src/verify/escaped-tests/escaped-test-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which escaped test files a product's next gate run adds: the pure rule.
|
|
3
|
+
*
|
|
4
|
+
* A GATE ESCAPE is a red integration candidate whose approved head the verify
|
|
5
|
+
* gate had passed (queries/candidate-ci-reds/). The test files CI named there
|
|
6
|
+
* are a gap in the product's own test selection -- not one focus's -- so the
|
|
7
|
+
* set is per product: every focus of the product runs them.
|
|
8
|
+
*
|
|
9
|
+
* The rule:
|
|
10
|
+
* - A file is IN the set while it has passed fewer than
|
|
11
|
+
* ESCAPED_FILE_REQUIRED_PASSES gate runs on distinct commits SINCE its
|
|
12
|
+
* newest escape. A pass recorded before that escape does not count, so a
|
|
13
|
+
* newer escape of the file restarts its count.
|
|
14
|
+
* - The set is the newest-escaped files first, at most ESCAPED_SET_MAX_FILES.
|
|
15
|
+
* - A path that is not a plain repo-relative path (absolute, `..`, a control
|
|
16
|
+
* character) is never in it: it is handed to a shell command.
|
|
17
|
+
*
|
|
18
|
+
* Passes are kept per product, host-local ({@link EscapedPassState}; the durable
|
|
19
|
+
* store, which reads a missing or unreadable record as no passes, is
|
|
20
|
+
* escaped-pass-store.ts): the rule fails toward running a test, never toward
|
|
21
|
+
* dropping it. The record keeps EVERY file's passes -- at most
|
|
22
|
+
* ESCAPED_FILE_REQUIRED_PASSES each, so it grows only with the product's distinct
|
|
23
|
+
* escaped files -- and never evicts one, so a file that met the exit rule stays
|
|
24
|
+
* out of the set until a newer escape names it again.
|
|
25
|
+
*
|
|
26
|
+
* @module verify/escaped-tests/escaped-test-set
|
|
27
|
+
*/
|
|
28
|
+
/** Gate runs on distinct commits an escaped file must pass, since its newest escape, to leave the set. */
|
|
29
|
+
export declare const ESCAPED_FILE_REQUIRED_PASSES = 3;
|
|
30
|
+
/** The most escaped files one gate run adds. */
|
|
31
|
+
export declare const ESCAPED_SET_MAX_FILES = 10;
|
|
32
|
+
/** One escaped file as the product's escape record lists it. */
|
|
33
|
+
export interface EscapedFile {
|
|
34
|
+
/** Repo-relative test file path. */
|
|
35
|
+
file: string;
|
|
36
|
+
/** When the newest escape naming the file was recorded (ISO 8601). */
|
|
37
|
+
lastEscapeAt: string;
|
|
38
|
+
}
|
|
39
|
+
/** One gate run an escaped file passed: the commit it judged, and when (epoch ms). */
|
|
40
|
+
export interface EscapedPass {
|
|
41
|
+
sha: string;
|
|
42
|
+
at: number;
|
|
43
|
+
}
|
|
44
|
+
/** A product's recorded passes, per file. */
|
|
45
|
+
export interface EscapedPassState {
|
|
46
|
+
files: Record<string, EscapedPass[]>;
|
|
47
|
+
}
|
|
48
|
+
/** A path safe to hand a re-run command as one test file: repo-relative, no `..`, no control characters. Pure. */
|
|
49
|
+
export declare function isRunnableTestPath(file: string): boolean;
|
|
50
|
+
/** Distinct-commit passes of `file` recorded after `lastEscapeAt` (an unparseable instant counts every pass as before it). Pure. */
|
|
51
|
+
export declare function passesSinceEscape(state: EscapedPassState, file: string, lastEscapeAt: string): number;
|
|
52
|
+
/**
|
|
53
|
+
* The files a gate run adds (module doc): runnable paths, newest escape first,
|
|
54
|
+
* fewer than the required passes since that escape, at most the cap. Pure.
|
|
55
|
+
*/
|
|
56
|
+
export declare function escapedTestSet(escapes: readonly EscapedFile[], state: EscapedPassState): string[];
|
|
57
|
+
/**
|
|
58
|
+
* The state with one pass recorded for each of `files` at commit `sha`, at
|
|
59
|
+
* `now`. A commit already recorded for a file counts once (its instant moves to
|
|
60
|
+
* `now`). Each file keeps its newest ESCAPED_FILE_REQUIRED_PASSES passes -- only
|
|
61
|
+
* passes after the newest escape count, and no more are needed -- and every
|
|
62
|
+
* other file's record is kept as it was: none is ever evicted (module doc). Pure.
|
|
63
|
+
*/
|
|
64
|
+
export declare function recordEscapedPasses(state: EscapedPassState, files: readonly string[], sha: string, now: number): EscapedPassState;
|
|
65
|
+
//# sourceMappingURL=escaped-test-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escaped-test-set.d.ts","sourceRoot":"","sources":["../../../src/verify/escaped-tests/escaped-test-set.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,0GAA0G;AAC1G,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,gDAAgD;AAChD,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,sFAAsF;AACtF,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;CACtC;AAED,kHAAkH;AAClH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMxD;AAED,oIAAoI;AACpI,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAKrG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAcjG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAOjI"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/verify/ci-gate/ci-gate-dispatch.test.ts,
|
|
3
|
+
// packages/daemon/src/verify/escaped-tests/escaped-gate-run.test.ts,
|
|
4
|
+
// packages/daemon/src/verify/escaped-tests/escaped-pass-store.test.ts,
|
|
5
|
+
// packages/daemon/src/verify/escaped-tests/escaped-test-set.test.ts,
|
|
6
|
+
// packages/daemon/src/verify/escaped-tests/escaped-tests-source.test.ts
|
|
7
|
+
// PINNED-BY-END
|
|
8
|
+
/**
|
|
9
|
+
* Which escaped test files a product's next gate run adds: the pure rule.
|
|
10
|
+
*
|
|
11
|
+
* A GATE ESCAPE is a red integration candidate whose approved head the verify
|
|
12
|
+
* gate had passed (queries/candidate-ci-reds/). The test files CI named there
|
|
13
|
+
* are a gap in the product's own test selection -- not one focus's -- so the
|
|
14
|
+
* set is per product: every focus of the product runs them.
|
|
15
|
+
*
|
|
16
|
+
* The rule:
|
|
17
|
+
* - A file is IN the set while it has passed fewer than
|
|
18
|
+
* ESCAPED_FILE_REQUIRED_PASSES gate runs on distinct commits SINCE its
|
|
19
|
+
* newest escape. A pass recorded before that escape does not count, so a
|
|
20
|
+
* newer escape of the file restarts its count.
|
|
21
|
+
* - The set is the newest-escaped files first, at most ESCAPED_SET_MAX_FILES.
|
|
22
|
+
* - A path that is not a plain repo-relative path (absolute, `..`, a control
|
|
23
|
+
* character) is never in it: it is handed to a shell command.
|
|
24
|
+
*
|
|
25
|
+
* Passes are kept per product, host-local ({@link EscapedPassState}; the durable
|
|
26
|
+
* store, which reads a missing or unreadable record as no passes, is
|
|
27
|
+
* escaped-pass-store.ts): the rule fails toward running a test, never toward
|
|
28
|
+
* dropping it. The record keeps EVERY file's passes -- at most
|
|
29
|
+
* ESCAPED_FILE_REQUIRED_PASSES each, so it grows only with the product's distinct
|
|
30
|
+
* escaped files -- and never evicts one, so a file that met the exit rule stays
|
|
31
|
+
* out of the set until a newer escape names it again.
|
|
32
|
+
*
|
|
33
|
+
* @module verify/escaped-tests/escaped-test-set
|
|
34
|
+
*/
|
|
35
|
+
/** Gate runs on distinct commits an escaped file must pass, since its newest escape, to leave the set. */
|
|
36
|
+
export const ESCAPED_FILE_REQUIRED_PASSES = 3;
|
|
37
|
+
/** The most escaped files one gate run adds. */
|
|
38
|
+
export const ESCAPED_SET_MAX_FILES = 10;
|
|
39
|
+
/** A path safe to hand a re-run command as one test file: repo-relative, no `..`, no control characters. Pure. */
|
|
40
|
+
export function isRunnableTestPath(file) {
|
|
41
|
+
if (file.length === 0 || file.length > 1000 || file.trim() !== file)
|
|
42
|
+
return false;
|
|
43
|
+
// eslint-disable-next-line no-control-regex -- a control character in a path handed to a shell is exactly what is refused.
|
|
44
|
+
if (/[\u0000-\u001f\u007f]/.test(file))
|
|
45
|
+
return false;
|
|
46
|
+
if (file.startsWith('/') || file.startsWith('-'))
|
|
47
|
+
return false;
|
|
48
|
+
return !file.split('/').some((segment) => segment === '..' || segment === '');
|
|
49
|
+
}
|
|
50
|
+
/** Distinct-commit passes of `file` recorded after `lastEscapeAt` (an unparseable instant counts every pass as before it). Pure. */
|
|
51
|
+
export function passesSinceEscape(state, file, lastEscapeAt) {
|
|
52
|
+
const since = Date.parse(lastEscapeAt);
|
|
53
|
+
const passes = state.files[file] ?? [];
|
|
54
|
+
if (!Number.isFinite(since))
|
|
55
|
+
return 0;
|
|
56
|
+
return new Set(passes.filter((p) => p.at > since).map((p) => p.sha)).size;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The files a gate run adds (module doc): runnable paths, newest escape first,
|
|
60
|
+
* fewer than the required passes since that escape, at most the cap. Pure.
|
|
61
|
+
*/
|
|
62
|
+
export function escapedTestSet(escapes, state) {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const ordered = escapes
|
|
65
|
+
.map((e, index) => ({ ...e, index, t: Date.parse(e.lastEscapeAt) }))
|
|
66
|
+
.sort((a, b) => (Number.isFinite(b.t) ? b.t : 0) - (Number.isFinite(a.t) ? a.t : 0) || a.index - b.index);
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const escape of ordered) {
|
|
69
|
+
if (seen.has(escape.file) || !isRunnableTestPath(escape.file))
|
|
70
|
+
continue;
|
|
71
|
+
seen.add(escape.file);
|
|
72
|
+
if (passesSinceEscape(state, escape.file, escape.lastEscapeAt) >= ESCAPED_FILE_REQUIRED_PASSES)
|
|
73
|
+
continue;
|
|
74
|
+
out.push(escape.file);
|
|
75
|
+
if (out.length >= ESCAPED_SET_MAX_FILES)
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The state with one pass recorded for each of `files` at commit `sha`, at
|
|
82
|
+
* `now`. A commit already recorded for a file counts once (its instant moves to
|
|
83
|
+
* `now`). Each file keeps its newest ESCAPED_FILE_REQUIRED_PASSES passes -- only
|
|
84
|
+
* passes after the newest escape count, and no more are needed -- and every
|
|
85
|
+
* other file's record is kept as it was: none is ever evicted (module doc). Pure.
|
|
86
|
+
*/
|
|
87
|
+
export function recordEscapedPasses(state, files, sha, now) {
|
|
88
|
+
const next = { ...state.files };
|
|
89
|
+
for (const file of files) {
|
|
90
|
+
const kept = (next[file] ?? []).filter((p) => p.sha !== sha);
|
|
91
|
+
next[file] = [...kept, { sha, at: now }].sort((a, b) => b.at - a.at).slice(0, ESCAPED_FILE_REQUIRED_PASSES);
|
|
92
|
+
}
|
|
93
|
+
return { files: next };
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=escaped-test-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escaped-test-set.js","sourceRoot":"","sources":["../../../src/verify/escaped-tests/escaped-test-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DeclaredRerun, StrategyResult } from '../deterministic-gate/verification-deterministic.js';
|
|
2
|
+
import { type EscapedFile } from './escaped-test-set.js';
|
|
3
|
+
import type { EscapedPassStore } from './escaped-pass-store.js';
|
|
4
|
+
/** How long a gate run waits for the product's escapes before it runs without them. */
|
|
5
|
+
export declare const ESCAPED_SET_READ_TIMEOUT_MS = 10000;
|
|
6
|
+
/** The collaborators, bound at the composition root (composition/verification-context.ts). */
|
|
7
|
+
export interface EscapedTestsDeps {
|
|
8
|
+
/** The product's escaped files, newest escape first (product-api); throws on a failed read. */
|
|
9
|
+
listEscapes: (productId: string) => Promise<EscapedFile[]>;
|
|
10
|
+
passes: EscapedPassStore;
|
|
11
|
+
now: () => number;
|
|
12
|
+
/** How long the escape read may take before the run goes ahead with no added files. */
|
|
13
|
+
readTimeoutMs: number;
|
|
14
|
+
/** Which of `files` exist at commit `sha` of the repo at `repoPath` (a CI-run gate has no checkout here). */
|
|
15
|
+
filesAtCommit: (repoPath: string, sha: string, files: readonly string[]) => string[];
|
|
16
|
+
}
|
|
17
|
+
/** The gate a run applies, as far as adding files is concerned. */
|
|
18
|
+
type GateToExtend = {
|
|
19
|
+
command: string;
|
|
20
|
+
rerun?: DeclaredRerun | undefined;
|
|
21
|
+
};
|
|
22
|
+
/** The product's escaped set (module doc); [] on any failed or slow read. */
|
|
23
|
+
export declare function escapedFilesFor(productId: string | null, deps: EscapedTestsDeps): Promise<string[]>;
|
|
24
|
+
/** The files of `files` present in the checkout at `checkoutPath` (never a path outside it). */
|
|
25
|
+
export declare function filesInCheckout(checkoutPath: string, files: readonly string[]): string[];
|
|
26
|
+
/** The command a LOCAL gate run of `productId` spawns in the checkout at `checkoutPath` (module doc). */
|
|
27
|
+
export declare function localGateCommand(productId: string | null, gate: GateToExtend, checkoutPath: string, deps: EscapedTestsDeps): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* The command a CI-run gate of `productId` at `sha` ships in its spec (module
|
|
30
|
+
* doc), and the escaped files it adds ([] when the command is the gate's own).
|
|
31
|
+
*/
|
|
32
|
+
export declare function ciGateCommand(productId: string | null, gate: GateToExtend, repoPath: string, sha: string, deps: EscapedTestsDeps): Promise<{
|
|
33
|
+
command: string;
|
|
34
|
+
files: string[];
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* A gate run's result with its escaped files judged (module doc): the exit
|
|
38
|
+
* rule's exception applied, and the files it passed counted. A product that
|
|
39
|
+
* declares no re-run command added no files, and its result is returned as is,
|
|
40
|
+
* with no log read.
|
|
41
|
+
*/
|
|
42
|
+
export declare function judgeEscapedTests(productId: string | null, result: StrategyResult, readLogText: (source: StrategyResult) => string, deps: EscapedTestsDeps): StrategyResult;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=escaped-tests-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escaped-tests-source.d.ts","sourceRoot":"","sources":["../../../src/verify/escaped-tests/escaped-tests-source.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qDAAqD,CAAC;AAEzG,OAAO,EAAuC,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,uFAAuF;AACvF,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,8FAA8F;AAC9F,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3D,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,uFAAuF;IACvF,aAAa,EAAE,MAAM,CAAC;IACtB,6GAA6G;IAC7G,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CACtF;AAED,mEAAmE;AACnE,KAAK,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,CAAC;AAY3E,6EAA6E;AAC7E,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUzG;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAMxF;AASD,yGAAyG;AACzG,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAc/C;AAoBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,MAAM,EAC/C,IAAI,EAAE,gBAAgB,GACrB,cAAc,CAOhB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/verify/escaped-tests/escaped-gate-run.test.ts,
|
|
3
|
+
// packages/daemon/src/verify/escaped-tests/escaped-tests-source.test.ts
|
|
4
|
+
// PINNED-BY-END
|
|
5
|
+
/**
|
|
6
|
+
* Escaped test files in a product's gate runs: what a gate run adds, and what
|
|
7
|
+
* its verdict counts.
|
|
8
|
+
*
|
|
9
|
+
* ADDED, ONLY TO THE GATE RUN OF A FOCUS HEAD (the local strategy's run of a
|
|
10
|
+
* default-on candidate, verify/deterministic-gate/verification-checkout.ts, and
|
|
11
|
+
* the CI hand-over of one, verify/ci-gate/ci-gate-dispatch.ts) -- never to a
|
|
12
|
+
* re-run, a continuation, a base run or a rework re-check. A run adds files only
|
|
13
|
+
* when the judged commit's manifest declares a `rerunCommand` and the product's
|
|
14
|
+
* escaped set (escaped-test-set.ts) holds files that exist at the judged commit;
|
|
15
|
+
* the gate command it then spawns is escaped-test-run.ts
|
|
16
|
+
* composeGateWithEscapedTests. With no `rerunCommand`, or no such file, the run
|
|
17
|
+
* spawns exactly the gate command, as before.
|
|
18
|
+
*
|
|
19
|
+
* The set is read ONCE per gate run, fail-soft: a failed or slow read of the
|
|
20
|
+
* product's escapes (bounded by `readTimeoutMs`) adds no files and is logged --
|
|
21
|
+
* the gate is never blocked or failed by it.
|
|
22
|
+
*
|
|
23
|
+
* COUNTED, when a run rendered a verdict about its commit (verify/engine/
|
|
24
|
+
* verification-commit-sharing.ts judges every local and CI run through
|
|
25
|
+
* {@link judgeEscapedTests}): each added file the run passed
|
|
26
|
+
* (escaped-test-run.ts passedEscapedFiles) gets one pass for the judged commit
|
|
27
|
+
* in the product's host-local record (escaped-pass-store.ts); a commit counts
|
|
28
|
+
* once. The same step applies the exit rule's one exception
|
|
29
|
+
* (escaped-test-run.ts settleEscapedRun).
|
|
30
|
+
*
|
|
31
|
+
* @module verify/escaped-tests/escaped-tests-source
|
|
32
|
+
*/
|
|
33
|
+
import { existsSync } from 'node:fs';
|
|
34
|
+
import { resolve, sep } from 'node:path';
|
|
35
|
+
import { createLogger } from '../../log/daemon-log.js';
|
|
36
|
+
import { escapedTestSet, recordEscapedPasses } from './escaped-test-set.js';
|
|
37
|
+
import { composeGateWithEscapedTests, passedEscapedFiles, settleEscapedRun } from './escaped-test-run.js';
|
|
38
|
+
const log = createLogger({ module: 'verification' });
|
|
39
|
+
/** How long a gate run waits for the product's escapes before it runs without them. */
|
|
40
|
+
export const ESCAPED_SET_READ_TIMEOUT_MS = 10_000;
|
|
41
|
+
/** `promise`, or a rejection once `ms` has passed. */
|
|
42
|
+
function withTimeout(promise, ms) {
|
|
43
|
+
let timer;
|
|
44
|
+
const timeout = new Promise((_, reject) => {
|
|
45
|
+
timer = setTimeout(() => reject(new Error(`no answer within ${ms} ms`)), ms);
|
|
46
|
+
timer.unref?.();
|
|
47
|
+
});
|
|
48
|
+
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
49
|
+
}
|
|
50
|
+
/** The product's escaped set (module doc); [] on any failed or slow read. */
|
|
51
|
+
export async function escapedFilesFor(productId, deps) {
|
|
52
|
+
if (!productId)
|
|
53
|
+
return [];
|
|
54
|
+
try {
|
|
55
|
+
const escapes = await withTimeout(deps.listEscapes(productId), deps.readTimeoutMs);
|
|
56
|
+
return escapedTestSet(escapes, deps.passes.read(productId));
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
log.warn(`[verification] escaped tests: the gate escapes of product ${productId} could not be read `
|
|
60
|
+
+ `(${err.message}); this gate run adds no escaped test files`);
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** The files of `files` present in the checkout at `checkoutPath` (never a path outside it). */
|
|
65
|
+
export function filesInCheckout(checkoutPath, files) {
|
|
66
|
+
const root = resolve(checkoutPath);
|
|
67
|
+
return files.filter((file) => {
|
|
68
|
+
const path = resolve(root, file);
|
|
69
|
+
return path.startsWith(root + sep) && existsSync(path);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** The command a gate run spawns: the gate's own, plus the escaped `files` when there are any and a re-run command names them. */
|
|
73
|
+
function extendGate(gate, files, where) {
|
|
74
|
+
if (!gate.rerun || files.length === 0)
|
|
75
|
+
return gate.command;
|
|
76
|
+
log.info(`[verification] escaped tests: ${where} adds ${files.length} test file(s) a gate escape recorded: ${files.join(', ')}`);
|
|
77
|
+
return composeGateWithEscapedTests(gate.command, gate.rerun.command, files);
|
|
78
|
+
}
|
|
79
|
+
/** The command a LOCAL gate run of `productId` spawns in the checkout at `checkoutPath` (module doc). */
|
|
80
|
+
export async function localGateCommand(productId, gate, checkoutPath, deps) {
|
|
81
|
+
if (!gate.rerun)
|
|
82
|
+
return gate.command;
|
|
83
|
+
const files = filesInCheckout(checkoutPath, await escapedFilesFor(productId, deps));
|
|
84
|
+
return extendGate(gate, files, `the gate run in ${checkoutPath}`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The command a CI-run gate of `productId` at `sha` ships in its spec (module
|
|
88
|
+
* doc), and the escaped files it adds ([] when the command is the gate's own).
|
|
89
|
+
*/
|
|
90
|
+
export async function ciGateCommand(productId, gate, repoPath, sha, deps) {
|
|
91
|
+
const unchanged = { command: gate.command, files: [] };
|
|
92
|
+
if (!gate.rerun)
|
|
93
|
+
return unchanged;
|
|
94
|
+
const wanted = await escapedFilesFor(productId, deps);
|
|
95
|
+
if (wanted.length === 0)
|
|
96
|
+
return unchanged;
|
|
97
|
+
let present;
|
|
98
|
+
try {
|
|
99
|
+
present = new Set(deps.filesAtCommit(repoPath, sha, wanted));
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
log.warn(`[verification] escaped tests: could not list the escaped files at ${sha.slice(0, 8)} (${err.message}); none added`);
|
|
103
|
+
return unchanged;
|
|
104
|
+
}
|
|
105
|
+
const files = wanted.filter((f) => present.has(f));
|
|
106
|
+
return { command: extendGate(gate, files, `the CI gate run of ${sha.slice(0, 8)}`), files };
|
|
107
|
+
}
|
|
108
|
+
/** True when `result` is a gate run's verdict about its commit (no re-run, timeout or unavailable checkout). */
|
|
109
|
+
function renderedGateVerdict(result) {
|
|
110
|
+
return (result.outcome === 'passed' || result.outcome === 'failed')
|
|
111
|
+
&& typeof result.verifiedSha === 'string' && result.verifiedSha.length > 0
|
|
112
|
+
&& result.timedOut !== true && result.renderedBeforeKill === undefined
|
|
113
|
+
&& result.rerunOf === undefined && result.checkoutUnavailable !== true && result.configUnresolved !== true;
|
|
114
|
+
}
|
|
115
|
+
/** Record one pass at the judged commit for each added file the run passed (module doc). */
|
|
116
|
+
function notePasses(productId, result, logText, deps) {
|
|
117
|
+
const passed = passedEscapedFiles(logText);
|
|
118
|
+
if (passed.length === 0)
|
|
119
|
+
return;
|
|
120
|
+
const next = recordEscapedPasses(deps.passes.read(productId), passed, result.verifiedSha, deps.now());
|
|
121
|
+
if (deps.passes.write(productId, next)) {
|
|
122
|
+
log.info(`[verification] escaped tests: ${passed.length} escaped test file(s) passed at ${result.verifiedSha.slice(0, 8)}: ${passed.join(', ')}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A gate run's result with its escaped files judged (module doc): the exit
|
|
127
|
+
* rule's exception applied, and the files it passed counted. A product that
|
|
128
|
+
* declares no re-run command added no files, and its result is returned as is,
|
|
129
|
+
* with no log read.
|
|
130
|
+
*/
|
|
131
|
+
export function judgeEscapedTests(productId, result, readLogText, deps) {
|
|
132
|
+
if (!result.appliedConfig?.rerun || !renderedGateVerdict(result))
|
|
133
|
+
return result;
|
|
134
|
+
const logText = readLogText(result);
|
|
135
|
+
const settled = settleEscapedRun(result, logText);
|
|
136
|
+
if (settled !== result)
|
|
137
|
+
log.info(`[verification] escaped tests: ${settled.rationale}`);
|
|
138
|
+
if (productId)
|
|
139
|
+
notePasses(productId, result, logText, deps);
|
|
140
|
+
return settled;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=escaped-tests-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escaped-tests-source.js","sourceRoot":"","sources":["../../../src/verify/escaped-tests/escaped-tests-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,6 +74,17 @@ export interface VerifyManifest {
|
|
|
74
74
|
* docs/runbook-verify-gate-in-ci.md.
|
|
75
75
|
*/
|
|
76
76
|
gateRunner?: GateRunnerName;
|
|
77
|
+
/**
|
|
78
|
+
* Optional: `true` declares that the product's CI publishes a FAILURE RECORD
|
|
79
|
+
* for a failed run (refs/ci-failures/<sha>/<run>/<job>, ci/candidate-failure-record.ts;
|
|
80
|
+
* contract: docs/runbook-ci-log-diagnosis.md, "The failure record"). Declared,
|
|
81
|
+
* a red integration candidate whose record has not landed yet waits a bounded
|
|
82
|
+
* window for it before its rework is routed, even on the first record the
|
|
83
|
+
* product ever publishes (merge/candidate-ci-failures.ts awaitsFailureRecord).
|
|
84
|
+
* Absent or `false` => no wait unless this host has held one of the product's
|
|
85
|
+
* records before.
|
|
86
|
+
*/
|
|
87
|
+
ciFailureRecords?: boolean;
|
|
77
88
|
}
|
|
78
89
|
/** The completion judges a manifest may name. */
|
|
79
90
|
export declare const COMPLETION_JUDGE_NAMES: readonly ["ci", "local"];
|
|
@@ -118,7 +129,7 @@ export declare function gateRunsOnCi(manifest: Pick<VerifyManifest, 'gateRunner'
|
|
|
118
129
|
* `rerunMaxFailures` / carries an unknown `completionJudge`, a
|
|
119
130
|
* `completionCommand` that is not a non-empty string, a non-positive
|
|
120
131
|
* `completionTimeoutMs`, or a completion command beside `"ci"` /
|
|
121
|
-
* carries an unknown `gateRunner`.
|
|
132
|
+
* carries an unknown `gateRunner` / carries a non-boolean `ciFailureRecords`.
|
|
122
133
|
*/
|
|
123
134
|
export declare function readVerifyManifestFrom(repoPath: string | undefined, fs: VerifyManifestFs): VerifyManifest | undefined;
|
|
124
135
|
/** Read the repo's verification manifest from the working tree on disk (see readVerifyManifestFrom). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-manifest.d.ts","sourceRoot":"","sources":["../../../src/verify/gate-config/verification-manifest.ts"],"names":[],"mappings":"AA8DA;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"verification-manifest.d.ts","sourceRoot":"","sources":["../../../src/verify/gate-config/verification-manifest.ts"],"names":[],"mappings":"AA8DA;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,iDAAiD;AACjD,eAAO,MAAM,sBAAsB,0BAA2B,CAAC;AAC/D,MAAM,MAAM,mBAAmB,GAAG,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAExE,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,0BAA2B,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAG,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE9D,0EAA0E;AAC1E,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAEjD,wGAAwG;AACxG,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAQD,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,cAAc,GAAG,SAAS,CAAC;AAEhG,0DAA0D;AAC1D,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElE;AAsFD,8GAA8G;AAC9G,wBAAgB,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,GAAG,SAAS,GAAG,OAAO,CAE9F;AAoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAuDrH;AAED,wGAAwG;AACxG,eAAO,MAAM,kBAAkB,EAAE,oBAAoF,CAAC;AAEtH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,GAAG,SAAS,CAOzG"}
|
|
@@ -172,6 +172,15 @@ function optionalGateRunner(raw, path) {
|
|
|
172
172
|
}
|
|
173
173
|
return { gateRunner: runner };
|
|
174
174
|
}
|
|
175
|
+
/** Validate the optional failure-record declaration (present-but-not-boolean is malformed, like every key). */
|
|
176
|
+
function optionalCiFailureRecords(raw, path) {
|
|
177
|
+
const value = raw.ciFailureRecords;
|
|
178
|
+
if (value === undefined)
|
|
179
|
+
return {};
|
|
180
|
+
if (typeof value !== 'boolean')
|
|
181
|
+
manifestError(path, `"ciFailureRecords" must be true or false (got ${JSON.stringify(value)})`);
|
|
182
|
+
return { ciFailureRecords: value };
|
|
183
|
+
}
|
|
175
184
|
/**
|
|
176
185
|
* Read the repo's verification manifest through `fs`.
|
|
177
186
|
*
|
|
@@ -187,7 +196,7 @@ function optionalGateRunner(raw, path) {
|
|
|
187
196
|
* `rerunMaxFailures` / carries an unknown `completionJudge`, a
|
|
188
197
|
* `completionCommand` that is not a non-empty string, a non-positive
|
|
189
198
|
* `completionTimeoutMs`, or a completion command beside `"ci"` /
|
|
190
|
-
* carries an unknown `gateRunner`.
|
|
199
|
+
* carries an unknown `gateRunner` / carries a non-boolean `ciFailureRecords`.
|
|
191
200
|
*/
|
|
192
201
|
export function readVerifyManifestFrom(repoPath, fs) {
|
|
193
202
|
if (!repoPath)
|
|
@@ -228,6 +237,7 @@ export function readVerifyManifestFrom(repoPath, fs) {
|
|
|
228
237
|
const rerun = optionalRerun(raw, path);
|
|
229
238
|
const completion = optionalCompletion(raw, path);
|
|
230
239
|
const gateRunner = optionalGateRunner(raw, path);
|
|
240
|
+
const ciFailureRecords = optionalCiFailureRecords(raw, path);
|
|
231
241
|
return {
|
|
232
242
|
command,
|
|
233
243
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
@@ -236,6 +246,7 @@ export function readVerifyManifestFrom(repoPath, fs) {
|
|
|
236
246
|
...rerun,
|
|
237
247
|
...completion,
|
|
238
248
|
...gateRunner,
|
|
249
|
+
...ciFailureRecords,
|
|
239
250
|
};
|
|
240
251
|
}
|
|
241
252
|
/** Read the repo's verification manifest from the working tree on disk (see readVerifyManifestFrom). */
|