@hominis/fireforge 0.52.0 → 0.54.0
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/CHANGELOG.md +45 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/bootstrap.js +2 -3
- package/dist/src/commands/build-prelock.d.ts +3 -3
- package/dist/src/commands/build-prelock.js +3 -3
- package/dist/src/commands/build.js +4 -0
- package/dist/src/commands/declarations-report.d.ts +9 -3
- package/dist/src/commands/declarations-report.js +18 -11
- package/dist/src/commands/discard.js +3 -3
- package/dist/src/commands/doctor-furnace-config-sync.js +4 -4
- package/dist/src/commands/doctor-furnace.js +5 -5
- package/dist/src/commands/export-adopt-check.d.ts +5 -6
- package/dist/src/commands/export-adopt-check.js +5 -6
- package/dist/src/commands/export-flow.js +6 -9
- package/dist/src/commands/export-staged-registration.d.ts +4 -4
- package/dist/src/commands/export-staged-registration.js +4 -4
- package/dist/src/commands/forward-import-remedy.d.ts +2 -3
- package/dist/src/commands/forward-import-remedy.js +2 -3
- package/dist/src/commands/furnace/create-dry-run.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.js +2 -2
- package/dist/src/commands/furnace/index.js +2 -2
- package/dist/src/commands/lint.js +4 -4
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/lint-ignore-from.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore-from.js +3 -4
- package/dist/src/commands/patch/move-files-adopt.d.ts +33 -0
- package/dist/src/commands/patch/move-files-adopt.js +65 -0
- package/dist/src/commands/patch/move-files-create.js +41 -20
- package/dist/src/commands/patch/move-files-into.d.ts +18 -0
- package/dist/src/commands/patch/move-files-into.js +125 -60
- package/dist/src/commands/patch/move-files-retire.d.ts +39 -0
- package/dist/src/commands/patch/move-files-retire.js +91 -0
- package/dist/src/commands/patch/move-files.d.ts +3 -0
- package/dist/src/commands/patch/move-files.js +42 -12
- package/dist/src/commands/patch/move-size-tier.d.ts +27 -0
- package/dist/src/commands/patch/move-size-tier.js +66 -0
- package/dist/src/commands/patch/rename.js +1 -1
- package/dist/src/commands/patch/reorder-projection.d.ts +17 -0
- package/dist/src/commands/patch/reorder-projection.js +49 -0
- package/dist/src/commands/patch/reorder-shift.d.ts +30 -0
- package/dist/src/commands/patch/reorder-shift.js +307 -0
- package/dist/src/commands/patch/reorder.d.ts +9 -15
- package/dist/src/commands/patch/reorder.js +52 -50
- package/dist/src/commands/patch/split-plan.d.ts +31 -3
- package/dist/src/commands/patch/split-plan.js +36 -12
- package/dist/src/commands/patch/split-staged.d.ts +2 -2
- package/dist/src/commands/patch/split-staged.js +2 -2
- package/dist/src/commands/patch/split.js +18 -5
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +9 -1
- package/dist/src/commands/patch/staged-dependency-entries.js +32 -4
- package/dist/src/commands/patch/staged-dependency-from.js +15 -9
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +26 -4
- package/dist/src/commands/patch/staged-dependency-remove.js +60 -23
- package/dist/src/commands/patch/staged-dependency.js +35 -24
- package/dist/src/commands/patch/tier.js +2 -2
- package/dist/src/commands/patch-rename-map.d.ts +14 -3
- package/dist/src/commands/patch-rename-map.js +21 -3
- package/dist/src/commands/re-export-adjacent.d.ts +4 -5
- package/dist/src/commands/re-export-lint.d.ts +4 -3
- package/dist/src/commands/re-export-lint.js +4 -3
- package/dist/src/commands/re-export-options.js +8 -2
- package/dist/src/commands/re-export-preflight.js +1 -2
- package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
- package/dist/src/commands/re-export-purity-scope.js +13 -7
- package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
- package/dist/src/commands/re-export-retired-declarations.js +113 -0
- package/dist/src/commands/re-export-single.js +2 -2
- package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
- package/dist/src/commands/re-export-stale-registrations.js +65 -21
- package/dist/src/commands/re-export.js +4 -0
- package/dist/src/commands/rebase/continue.js +3 -3
- package/dist/src/commands/register.js +5 -4
- package/dist/src/commands/run.js +11 -4
- package/dist/src/commands/status.js +1 -1
- package/dist/src/commands/test-build-furnace.d.ts +1 -2
- package/dist/src/commands/test-build-furnace.js +1 -2
- package/dist/src/commands/test-build-phase.d.ts +8 -0
- package/dist/src/commands/test-build-phase.js +42 -7
- package/dist/src/commands/test-control-restore.d.ts +40 -0
- package/dist/src/commands/test-control-restore.js +86 -0
- package/dist/src/commands/test-dispatch.js +68 -7
- package/dist/src/commands/test-multi-verdict.js +1 -0
- package/dist/src/commands/test-orchestrate.d.ts +6 -0
- package/dist/src/commands/test-orchestrate.js +32 -1
- package/dist/src/commands/test-perf-scope.d.ts +1 -1
- package/dist/src/commands/test-perf-scope.js +1 -1
- package/dist/src/commands/test-prelock.d.ts +18 -8
- package/dist/src/commands/test-prelock.js +42 -14
- package/dist/src/commands/test-register.js +4 -3
- package/dist/src/commands/test-results.d.ts +10 -1
- package/dist/src/commands/test-results.js +20 -3
- package/dist/src/commands/test-run.d.ts +6 -0
- package/dist/src/commands/test-run.js +23 -4
- package/dist/src/commands/test-shards.d.ts +7 -3
- package/dist/src/commands/test-shards.js +24 -7
- package/dist/src/commands/test-stale-gate.d.ts +6 -1
- package/dist/src/commands/test-stale-gate.js +40 -2
- package/dist/src/commands/test-verdict.d.ts +5 -3
- package/dist/src/commands/test.js +14 -2
- package/dist/src/commands/token.js +2 -2
- package/dist/src/commands/verify.js +1 -1
- package/dist/src/commands/watch.js +1 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/build-audit-resolve.d.ts +4 -5
- package/dist/src/core/build-audit-resolve.js +4 -5
- package/dist/src/core/build-audit-skip.d.ts +2 -2
- package/dist/src/core/build-audit.d.ts +3 -4
- package/dist/src/core/build-baseline-types.d.ts +24 -3
- package/dist/src/core/build-baseline-validate.d.ts +30 -1
- package/dist/src/core/build-baseline-validate.js +127 -35
- package/dist/src/core/build-baseline.d.ts +8 -2
- package/dist/src/core/build-baseline.js +25 -16
- package/dist/src/core/build-jar-escalation.d.ts +4 -4
- package/dist/src/core/build-jar-escalation.js +4 -4
- package/dist/src/core/build-prepare.js +4 -4
- package/dist/src/core/config-validate.js +4 -4
- package/dist/src/core/coverage-extend.d.ts +5 -3
- package/dist/src/core/coverage-extend.js +8 -3
- package/dist/src/core/coverage-records.d.ts +4 -5
- package/dist/src/core/coverage-records.js +4 -5
- package/dist/src/core/destructive.d.ts +2 -2
- package/dist/src/core/destructive.js +2 -2
- package/dist/src/core/discard-baseline.d.ts +2 -2
- package/dist/src/core/discard-baseline.js +3 -3
- package/dist/src/core/engine-session-lock.d.ts +1 -1
- package/dist/src/core/engine-session-lock.js +1 -1
- package/dist/src/core/file-lock-owner.d.ts +5 -5
- package/dist/src/core/file-lock-owner.js +5 -5
- package/dist/src/core/file-lock-queue.js +6 -8
- package/dist/src/core/file-lock-shared.d.ts +4 -4
- package/dist/src/core/file-lock-shared.js +4 -4
- package/dist/src/core/file-lock.js +7 -10
- package/dist/src/core/firefox.js +2 -2
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
- package/dist/src/core/furnace-apply.js +3 -3
- package/dist/src/core/furnace-operation.js +5 -5
- package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
- package/dist/src/core/furnace-registration-rename.d.ts +5 -5
- package/dist/src/core/furnace-registration-rename.js +5 -5
- package/dist/src/core/furnace-registration-validate.d.ts +2 -1
- package/dist/src/core/furnace-registration-validate.js +2 -1
- package/dist/src/core/furnace-registration.js +2 -2
- package/dist/src/core/git-base.js +4 -3
- package/dist/src/core/git-diff.js +1 -1
- package/dist/src/core/git.js +1 -1
- package/dist/src/core/harness-orphans.d.ts +6 -6
- package/dist/src/core/harness-orphans.js +6 -6
- package/dist/src/core/harness-port-reservation.d.ts +60 -0
- package/dist/src/core/harness-port-reservation.js +122 -0
- package/dist/src/core/history-log-file.d.ts +9 -9
- package/dist/src/core/history-log-file.js +15 -15
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- package/dist/src/core/launchable-build.d.ts +39 -0
- package/dist/src/core/launchable-build.js +85 -0
- package/dist/src/core/marionette-port.js +1 -3
- package/dist/src/core/moz-manifest-rules.js +3 -2
- package/dist/src/core/negative-control-compiled.d.ts +13 -3
- package/dist/src/core/negative-control-compiled.js +27 -5
- package/dist/src/core/negative-control-diff.js +31 -6
- package/dist/src/core/parser-fallback.d.ts +5 -5
- package/dist/src/core/parser-fallback.js +5 -5
- package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
- package/dist/src/core/patch-identifier-suggest.js +11 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
- package/dist/src/core/patch-lint-checkjs.js +1 -1
- package/dist/src/core/patch-lint-css.js +2 -2
- package/dist/src/core/patch-lint-file-size.d.ts +5 -7
- package/dist/src/core/patch-lint-file-size.js +5 -7
- package/dist/src/core/patch-lint-ignore.d.ts +3 -3
- package/dist/src/core/patch-lint-ignore.js +3 -3
- package/dist/src/core/patch-lint-prettier.d.ts +4 -6
- package/dist/src/core/patch-lint-prettier.js +4 -6
- package/dist/src/core/patch-lint-projection.d.ts +1 -1
- package/dist/src/core/patch-lint-projection.js +1 -1
- package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
- package/dist/src/core/patch-lint-queue-types.js +2 -2
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
- package/dist/src/core/patch-manifest-consistency.js +2 -2
- package/dist/src/core/patch-manifest-io.d.ts +5 -1
- package/dist/src/core/patch-manifest-io.js +12 -10
- package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
- package/dist/src/core/patch-manifest-key-order.js +3 -4
- package/dist/src/core/patch-parse.d.ts +3 -3
- package/dist/src/core/patch-parse.js +3 -3
- package/dist/src/core/patch-policy.d.ts +1 -1
- package/dist/src/core/patch-policy.js +1 -1
- package/dist/src/core/patch-source-metadata.d.ts +1 -1
- package/dist/src/core/patch-source-metadata.js +1 -1
- package/dist/src/core/patch-subset.d.ts +5 -3
- package/dist/src/core/patch-subset.js +8 -7
- package/dist/src/core/patch-transform.d.ts +2 -2
- package/dist/src/core/patch-transform.js +2 -2
- package/dist/src/core/rebase-session.js +4 -6
- package/dist/src/core/register-xpcshell-test.d.ts +28 -7
- package/dist/src/core/register-xpcshell-test.js +76 -27
- package/dist/src/core/run-log.d.ts +8 -8
- package/dist/src/core/run-log.js +8 -8
- package/dist/src/core/status-classify.d.ts +1 -2
- package/dist/src/core/status-classify.js +1 -2
- package/dist/src/core/test-harness-crash.d.ts +5 -3
- package/dist/src/core/test-harness-crash.js +13 -14
- package/dist/src/core/test-harness-infra.d.ts +32 -0
- package/dist/src/core/test-harness-infra.js +69 -0
- package/dist/src/core/test-harness-signature.d.ts +6 -0
- package/dist/src/core/test-stale-check.d.ts +38 -0
- package/dist/src/core/test-stale-check.js +82 -1
- package/dist/src/core/test-stall-triage.js +5 -7
- package/dist/src/core/token-category.js +2 -2
- package/dist/src/core/token-inventory.js +3 -3
- package/dist/src/core/token-manager.d.ts +2 -2
- package/dist/src/core/token-manager.js +5 -7
- package/dist/src/core/token-variant.d.ts +6 -6
- package/dist/src/core/token-variant.js +7 -7
- package/dist/src/core/typecheck-shim.js +1 -1
- package/dist/src/core/wire-destroy.d.ts +1 -1
- package/dist/src/core/wire-destroy.js +1 -1
- package/dist/src/core/wire-dom-fragment.js +1 -1
- package/dist/src/core/wire-init.d.ts +1 -1
- package/dist/src/core/wire-init.js +1 -1
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +1 -1
- package/dist/src/core/wire-utils.d.ts +2 -2
- package/dist/src/core/wire-utils.js +3 -3
- package/dist/src/errors/base.d.ts +1 -1
- package/dist/src/errors/base.js +1 -1
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- package/dist/src/types/commands/options.d.ts +38 -3
- package/dist/src/types/config.d.ts +5 -7
- package/dist/src/utils/options.js +2 -2
- package/dist/src/utils/process.js +2 -2
- package/dist/src/utils/regex.d.ts +2 -2
- package/dist/src/utils/regex.js +3 -3
- package/dist/src/utils/sleep.d.ts +5 -6
- package/dist/src/utils/sleep.js +5 -6
- package/dist/src/utils/validation.js +2 -2
- package/docs/configuration.md +28 -23
- package/docs/exit-codes.md +8 -11
- package/docs/furnace.md +3 -3
- package/docs/lifecycle-invariants.md +36 -45
- package/docs/machine-output.md +41 -24
- package/docs/patch-workflow.md +140 -29
- package/docs/run-logs.md +8 -9
- package/docs/testing.md +114 -48
- package/package.json +1 -1
|
@@ -29,9 +29,8 @@ const REBASE_PATCH_STATUSES = [
|
|
|
29
29
|
/**
|
|
30
30
|
* Drops payload that does not belong to an entry's status.
|
|
31
31
|
*
|
|
32
|
-
* Applied on read so a session
|
|
33
|
-
* `
|
|
34
|
-
* entry, loads cleanly and is corrected, instead of being refused by a
|
|
32
|
+
* Applied on read so a session whose `resolved` entry still carries
|
|
33
|
+
* `error`/`conflictingFiles` loads cleanly and is corrected, instead of being refused by a
|
|
35
34
|
* stricter validator mid-rebase.
|
|
36
35
|
*
|
|
37
36
|
* @param entry - A structurally valid entry, possibly carrying stale payload
|
|
@@ -145,11 +144,10 @@ export async function readRebaseSession(projectRoot) {
|
|
|
145
144
|
if (!isValidSession(data)) {
|
|
146
145
|
return { present: true, valid: false, reason: 'the file is not a valid rebase session' };
|
|
147
146
|
}
|
|
148
|
-
// Normalize on read:
|
|
147
|
+
// Normalize on read: a session can carry a failure's
|
|
149
148
|
// `error`/`conflictingFiles` on an entry whose status has since been
|
|
150
149
|
// flipped to `resolved`. Correcting it here is what lets the validator
|
|
151
|
-
// stay permissive, so an in-flight rebase
|
|
152
|
-
// loads.
|
|
150
|
+
// stay permissive, so such an in-flight rebase still loads.
|
|
153
151
|
return {
|
|
154
152
|
present: true,
|
|
155
153
|
valid: true,
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* xpcshell test-file registration. Without it, xpcshell test files (e.g.
|
|
3
3
|
* `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
|
|
4
4
|
* as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
|
|
5
|
-
* into the directory's `xpcshell.toml` (alphabetically
|
|
5
|
+
* into the directory's `xpcshell.toml` (alphabetically or after the
|
|
6
|
+
* `--after` entry, idempotently). With
|
|
6
7
|
* `--create-manifest` it also creates the manifest and wires
|
|
7
8
|
* `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
|
|
8
9
|
*/
|
|
@@ -14,16 +15,36 @@ import type { RegisterResult } from './register-result.js';
|
|
|
14
15
|
* missing rather than the file as unregistered).
|
|
15
16
|
*/
|
|
16
17
|
export declare function isXpcshellTestRegistered(engineDir: string, dirRel: string, fileName: string): Promise<boolean>;
|
|
18
|
+
/** Where a new section goes and what placed it there. */
|
|
19
|
+
export interface XpcshellSectionPlacement {
|
|
20
|
+
/** The manifest content with the section inserted. */
|
|
21
|
+
content: string;
|
|
22
|
+
/** The `["…"]` header of the `--after` entry the section follows. */
|
|
23
|
+
previousEntry?: string | undefined;
|
|
24
|
+
/** `--after` named no entry, so the section went in sort order. */
|
|
25
|
+
afterFallback?: boolean | undefined;
|
|
26
|
+
}
|
|
17
27
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
28
|
+
* Places the `["<fileName>"]` section in the manifest content.
|
|
29
|
+
*
|
|
30
|
+
* Without `after`, the section goes in mozbuild's case-insensitive sort
|
|
31
|
+
* order relative to the other test sections. With `after`, it goes right
|
|
32
|
+
* after the named entry's whole block (its keys included). Either way it
|
|
33
|
+
* is inserted ahead of the `#` comment lines that introduce the next
|
|
34
|
+
* entry, never between a comment and its entry, keeping one
|
|
35
|
+
* blank line between sections.
|
|
22
36
|
*/
|
|
23
|
-
export declare function
|
|
37
|
+
export declare function placeXpcshellManifestSection(content: string, fileName: string, after?: string): XpcshellSectionPlacement;
|
|
38
|
+
/**
|
|
39
|
+
* Inserts the `["<fileName>"]` section into the manifest content; see
|
|
40
|
+
* {@link placeXpcshellManifestSection}. Exported for direct unit testing.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export declare function insertXpcshellManifestSection(content: string, fileName: string, after?: string): string;
|
|
24
45
|
/**
|
|
25
46
|
* Registers an xpcshell test file in its directory's `xpcshell.toml`.
|
|
26
47
|
* With `createManifest`, a missing manifest is scaffolded and wired into
|
|
27
48
|
* the nearest moz.build via `XPCSHELL_TESTS_MANIFESTS`.
|
|
28
49
|
*/
|
|
29
|
-
export declare function registerXpcshellTest(engineDir: string, dirRel: string, fileName: string, dryRun?: boolean, createManifest?: boolean): Promise<RegisterResult>;
|
|
50
|
+
export declare function registerXpcshellTest(engineDir: string, dirRel: string, fileName: string, dryRun?: boolean, createManifest?: boolean, after?: string): Promise<RegisterResult>;
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* xpcshell test-file registration. Without it, xpcshell test files (e.g.
|
|
4
4
|
* `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
|
|
5
5
|
* as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
|
|
6
|
-
* into the directory's `xpcshell.toml` (alphabetically
|
|
6
|
+
* into the directory's `xpcshell.toml` (alphabetically or after the
|
|
7
|
+
* `--after` entry, idempotently). With
|
|
7
8
|
* `--create-manifest` it also creates the manifest and wires
|
|
8
9
|
* `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
|
|
9
10
|
*/
|
|
@@ -32,40 +33,82 @@ export async function isXpcshellTestRegistered(engineDir, dirRel, fileName) {
|
|
|
32
33
|
const content = await readText(manifestPath);
|
|
33
34
|
return content.includes(`["${fileName}"]`);
|
|
34
35
|
}
|
|
36
|
+
const SECTION_HEADER = /^\["([^"]+)"\]\s*$/;
|
|
35
37
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* The line where the block headed at `headerIndex` starts: the header
|
|
39
|
+
* itself, or the first of the `#` comment lines directly above it. A
|
|
40
|
+
* comment describes the entry below it, so nothing is inserted between
|
|
41
|
+
* them.
|
|
40
42
|
*/
|
|
41
|
-
|
|
43
|
+
function blockStart(lines, headerIndex) {
|
|
44
|
+
let start = headerIndex;
|
|
45
|
+
while (start > 0 && (lines[start - 1] ?? '').trimStart().startsWith('#'))
|
|
46
|
+
start -= 1;
|
|
47
|
+
return start;
|
|
48
|
+
}
|
|
49
|
+
/** Index of the section header `after` names: exact name first, then a substring. */
|
|
50
|
+
function findAfterHeader(lines, after) {
|
|
51
|
+
const headers = lines
|
|
52
|
+
.map((line, index) => ({ index, line, name: SECTION_HEADER.exec(line)?.[1] }))
|
|
53
|
+
.filter((header) => header.name !== undefined);
|
|
54
|
+
const exact = headers.find((header) => header.name === after || header.line.trim() === after);
|
|
55
|
+
return (exact ?? headers.find((header) => header.line.includes(after)))?.index ?? -1;
|
|
56
|
+
}
|
|
57
|
+
function spliceSection(lines, index, fileName) {
|
|
58
|
+
if (index === -1) {
|
|
59
|
+
// Append after the last section (or at end of file when there are no
|
|
60
|
+
// sections yet), keeping exactly one trailing newline.
|
|
61
|
+
while (lines.length > 0 && (lines.at(-1) ?? '').trim() === '')
|
|
62
|
+
lines.pop();
|
|
63
|
+
return [...lines, '', `["${fileName}"]`, ''].join('\n');
|
|
64
|
+
}
|
|
65
|
+
lines.splice(index, 0, `["${fileName}"]`, '');
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Places the `["<fileName>"]` section in the manifest content.
|
|
70
|
+
*
|
|
71
|
+
* Without `after`, the section goes in mozbuild's case-insensitive sort
|
|
72
|
+
* order relative to the other test sections. With `after`, it goes right
|
|
73
|
+
* after the named entry's whole block (its keys included). Either way it
|
|
74
|
+
* is inserted ahead of the `#` comment lines that introduce the next
|
|
75
|
+
* entry, never between a comment and its entry, keeping one
|
|
76
|
+
* blank line between sections.
|
|
77
|
+
*/
|
|
78
|
+
export function placeXpcshellManifestSection(content, fileName, after) {
|
|
42
79
|
const lines = content.split('\n');
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
80
|
+
const headerIndexes = lines.flatMap((line, index) => (SECTION_HEADER.test(line) ? [index] : []));
|
|
81
|
+
if (after !== undefined) {
|
|
82
|
+
const afterIndex = findAfterHeader(lines, after);
|
|
83
|
+
if (afterIndex !== -1) {
|
|
84
|
+
const next = headerIndexes.find((index) => index > afterIndex);
|
|
85
|
+
return {
|
|
86
|
+
content: spliceSection(lines, next === undefined ? -1 : blockStart(lines, next), fileName),
|
|
87
|
+
previousEntry: (lines[afterIndex] ?? '').trim(),
|
|
88
|
+
};
|
|
51
89
|
}
|
|
52
90
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
const before = headerIndexes.find((index) => mozbuildSortCompare(fileName, SECTION_HEADER.exec(lines[index] ?? '')?.[1] ?? '') < 0);
|
|
92
|
+
return {
|
|
93
|
+
content: spliceSection(lines, before === undefined ? -1 : blockStart(lines, before), fileName),
|
|
94
|
+
...(after !== undefined ? { afterFallback: true } : {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Inserts the `["<fileName>"]` section into the manifest content; see
|
|
99
|
+
* {@link placeXpcshellManifestSection}. Exported for direct unit testing.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
export function insertXpcshellManifestSection(content, fileName, after) {
|
|
104
|
+
return placeXpcshellManifestSection(content, fileName, after).content;
|
|
62
105
|
}
|
|
63
106
|
/**
|
|
64
107
|
* Registers an xpcshell test file in its directory's `xpcshell.toml`.
|
|
65
108
|
* With `createManifest`, a missing manifest is scaffolded and wired into
|
|
66
109
|
* the nearest moz.build via `XPCSHELL_TESTS_MANIFESTS`.
|
|
67
110
|
*/
|
|
68
|
-
export async function registerXpcshellTest(engineDir, dirRel, fileName, dryRun = false, createManifest = false) {
|
|
111
|
+
export async function registerXpcshellTest(engineDir, dirRel, fileName, dryRun = false, createManifest = false, after) {
|
|
69
112
|
const manifestRel = `${dirRel}/xpcshell.toml`;
|
|
70
113
|
const manifestPath = join(engineDir, manifestRel);
|
|
71
114
|
const entry = `["${fileName}"]`;
|
|
@@ -86,9 +129,15 @@ export async function registerXpcshellTest(engineDir, dirRel, fileName, dryRun =
|
|
|
86
129
|
if (content.includes(entry)) {
|
|
87
130
|
return { manifest: manifestRel, entry, skipped: true };
|
|
88
131
|
}
|
|
89
|
-
const
|
|
132
|
+
const placement = placeXpcshellManifestSection(content, fileName, after);
|
|
90
133
|
if (!dryRun) {
|
|
91
|
-
await writeText(manifestPath,
|
|
134
|
+
await writeText(manifestPath, placement.content);
|
|
92
135
|
}
|
|
93
|
-
return {
|
|
136
|
+
return {
|
|
137
|
+
manifest: manifestRel,
|
|
138
|
+
entry,
|
|
139
|
+
skipped: false,
|
|
140
|
+
previousEntry: placement.previousEntry,
|
|
141
|
+
afterFallback: placement.afterFallback,
|
|
142
|
+
};
|
|
94
143
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-run output logs under `.fireforge/logs/`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* through `tail`/`grep`, the ergonomic default when output is long,
|
|
6
|
-
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
7
|
-
* broke, and it launders the exit code besides.
|
|
8
|
-
* pipe a run")
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* Without a log, a run's diagnosis exists in exactly one place: the terminal.
|
|
5
|
+
* Piping through `tail`/`grep`, the ergonomic default when output is long,
|
|
6
|
+
* keeps the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
7
|
+
* what broke, and it launders the exit code besides. An operator rule
|
|
8
|
+
* ("never pipe a run") does not hold in practice, so this is not an operator
|
|
9
|
+
* problem: the tool is the only party that can make the log survive the
|
|
10
|
+
* mistake.
|
|
11
11
|
*
|
|
12
12
|
* So `test` and `build` write their own complete copy as they stream, and the
|
|
13
13
|
* `FIREFORGE-VERDICT:` line names the path. A piped, truncated, or
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Everything here is best-effort. A log is a diagnostic aid, and a run must
|
|
17
17
|
* never fail because one could not be opened, written, or pruned.
|
|
18
18
|
* Every entry point swallows its errors and degrades to "no log", which is
|
|
19
|
-
* exactly the behaviour
|
|
19
|
+
* exactly the behaviour of a run without this module.
|
|
20
20
|
*/
|
|
21
21
|
/** A run log sink. `write` never throws. */
|
|
22
22
|
export interface RunLog {
|
package/dist/src/core/run-log.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Per-run output logs under `.fireforge/logs/`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* through `tail`/`grep`, the ergonomic default when output is long,
|
|
7
|
-
* the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
8
|
-
* broke, and it launders the exit code besides.
|
|
9
|
-
* pipe a run")
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* Without a log, a run's diagnosis exists in exactly one place: the terminal.
|
|
6
|
+
* Piping through `tail`/`grep`, the ergonomic default when output is long,
|
|
7
|
+
* keeps the summary and discards the `TEST-UNEXPECTED-FAIL` lines that say
|
|
8
|
+
* what broke, and it launders the exit code besides. An operator rule
|
|
9
|
+
* ("never pipe a run") does not hold in practice, so this is not an operator
|
|
10
|
+
* problem: the tool is the only party that can make the log survive the
|
|
11
|
+
* mistake.
|
|
12
12
|
*
|
|
13
13
|
* So `test` and `build` write their own complete copy as they stream, and the
|
|
14
14
|
* `FIREFORGE-VERDICT:` line names the path. A piped, truncated, or
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Everything here is best-effort. A log is a diagnostic aid, and a run must
|
|
18
18
|
* never fail because one could not be opened, written, or pruned.
|
|
19
19
|
* Every entry point swallows its errors and degrades to "no log", which is
|
|
20
|
-
* exactly the behaviour
|
|
20
|
+
* exactly the behaviour of a run without this module.
|
|
21
21
|
*/
|
|
22
22
|
import { createWriteStream } from 'node:fs';
|
|
23
23
|
import { mkdir, readdir, stat, unlink } from 'node:fs/promises';
|
|
@@ -63,8 +63,7 @@ export interface ClassifiedFile extends StatusFile {
|
|
|
63
63
|
* Builds the file → owning-patch-filenames multimap from manifest rows.
|
|
64
64
|
* Single source of truth for cross-patch claim detection: status
|
|
65
65
|
* classification, verify's cross-claim check, and the ownership table all
|
|
66
|
-
* consume this builder
|
|
67
|
-
* disagreeing about what "claimed" means).
|
|
66
|
+
* consume this builder, so they cannot disagree about what "claimed" means.
|
|
68
67
|
*/
|
|
69
68
|
export declare function buildPatchClaims(manifestPatches: ReadonlyArray<{
|
|
70
69
|
filename: string;
|
|
@@ -20,8 +20,7 @@ import { classifyBinaryOwnedFile } from './status-binary.js';
|
|
|
20
20
|
* Builds the file → owning-patch-filenames multimap from manifest rows.
|
|
21
21
|
* Single source of truth for cross-patch claim detection: status
|
|
22
22
|
* classification, verify's cross-claim check, and the ownership table all
|
|
23
|
-
* consume this builder
|
|
24
|
-
* disagreeing about what "claimed" means).
|
|
23
|
+
* consume this builder, so they cannot disagree about what "claimed" means.
|
|
25
24
|
*/
|
|
26
25
|
export function buildPatchClaims(manifestPatches) {
|
|
27
26
|
const ownersByPath = new Map();
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
export type { HarnessCrashSignature } from './test-harness-signature.js';
|
|
25
25
|
import { type HarnessCrashSignature, type IncompleteRunEvidence } from './test-harness-signature.js';
|
|
26
|
+
export { buildHarnessCrashMessage } from './test-harness-infra.js';
|
|
26
27
|
export { headedDisplayAsleepVerdictNote, headedNoOutputTimeoutHint } from './test-stall-triage.js';
|
|
27
28
|
/** How a completed harness run should be interpreted. */
|
|
28
29
|
export type HarnessRunClassification = 'tests-ran-ok' | 'test-failures' | 'harness-crash' | 'harness-arguments' | 'no-tests';
|
|
@@ -160,7 +161,10 @@ export declare function detectHarnessCrashSignature(output: string): HarnessCras
|
|
|
160
161
|
* 1. A recognized crash signature wins regardless of exit code (the
|
|
161
162
|
* shutdown re-entry shape exits non-zero on an otherwise green run,
|
|
162
163
|
* and the hang shape can even exit zero with a `Passed: 0` summary).
|
|
163
|
-
* 2. No execution signal with explicit paths requested means no test ran
|
|
164
|
+
* 2. No execution signal with explicit paths requested means no test ran.
|
|
165
|
+
* A mochitest server that failed to start explains that, and is a
|
|
166
|
+
* retriable infrastructure failure (`harness-crash` with
|
|
167
|
+
* `reason=server-startup` on the verdict line). Otherwise it is
|
|
164
168
|
* `no-tests`, even when the exit code is zero. The execution signal is
|
|
165
169
|
* a `TEST-START` line (generic `mach test` / browser-chrome dispatch)
|
|
166
170
|
* or the suite-specific xpcshell result-summary block (the xpcshell
|
|
@@ -206,8 +210,6 @@ export declare function formatFireforgeVerdictLine(verdict: HarnessRunVerdict, s
|
|
|
206
210
|
* pass, regardless of how green the embedded counts look).
|
|
207
211
|
*/
|
|
208
212
|
export declare function buildGreenSummaryRejectedMessage(rejection: GreenSummaryRejection, exitCode: number): string;
|
|
209
|
-
/** Builds the operator-facing failure message after retries are exhausted. */
|
|
210
|
-
export declare function buildHarnessCrashMessage(signature: HarnessCrashSignature, attempts: number, commandLabel?: string): string;
|
|
211
213
|
/**
|
|
212
214
|
* True when a harness run died on SIGSEGV having produced no test evidence
|
|
213
215
|
* whatsoever.
|
|
@@ -23,9 +23,13 @@
|
|
|
23
23
|
* reporting phantom test failures (or phantom passes).
|
|
24
24
|
*/
|
|
25
25
|
import { hasKnownTeardownNoise } from './mach-known-noise-filter.js';
|
|
26
|
+
import { detectServerStartupFailure } from './test-harness-infra.js';
|
|
26
27
|
import { truncateEvidence, unmarkedFailureEvidenceNote, } from './test-harness-verdict-notes.js';
|
|
27
28
|
import { classifyProfileArgumentFailure } from './test-profile-files.js';
|
|
28
29
|
import { formatIncompleteSuffix, formatShardsSuffix, } from './test-harness-signature.js';
|
|
30
|
+
// The operator message after exhausted retries lives beside the
|
|
31
|
+
// server-startup shape in `test-harness-infra.ts`.
|
|
32
|
+
export { buildHarnessCrashMessage } from './test-harness-infra.js';
|
|
29
33
|
// The no-output-stall triage text lives in `test-stall-triage.ts` (it is
|
|
30
34
|
// operator advice, not classification) and is re-exported here so the
|
|
31
35
|
// command layer keeps importing its harness diagnostics from one module.
|
|
@@ -458,7 +462,10 @@ export function detectHarnessCrashSignature(output) {
|
|
|
458
462
|
* 1. A recognized crash signature wins regardless of exit code (the
|
|
459
463
|
* shutdown re-entry shape exits non-zero on an otherwise green run,
|
|
460
464
|
* and the hang shape can even exit zero with a `Passed: 0` summary).
|
|
461
|
-
* 2. No execution signal with explicit paths requested means no test ran
|
|
465
|
+
* 2. No execution signal with explicit paths requested means no test ran.
|
|
466
|
+
* A mochitest server that failed to start explains that, and is a
|
|
467
|
+
* retriable infrastructure failure (`harness-crash` with
|
|
468
|
+
* `reason=server-startup` on the verdict line). Otherwise it is
|
|
462
469
|
* `no-tests`, even when the exit code is zero. The execution signal is
|
|
463
470
|
* a `TEST-START` line (generic `mach test` / browser-chrome dispatch)
|
|
464
471
|
* or the suite-specific xpcshell result-summary block (the xpcshell
|
|
@@ -512,7 +519,10 @@ export function classifyHarnessRun(exitCode, output, requestedPaths) {
|
|
|
512
519
|
}
|
|
513
520
|
const ranTests = hasExecutionSignal(output);
|
|
514
521
|
if (!ranTests && requestedPaths.length > 0) {
|
|
515
|
-
|
|
522
|
+
const serverStartup = detectServerStartupFailure(output);
|
|
523
|
+
return serverStartup === undefined
|
|
524
|
+
? { kind: 'no-tests', ...counts }
|
|
525
|
+
: { kind: 'harness-crash', signature: serverStartup, ...counts };
|
|
516
526
|
}
|
|
517
527
|
if (exitCode === 0) {
|
|
518
528
|
return { kind: 'tests-ran-ok', ...counts };
|
|
@@ -663,7 +673,7 @@ export function formatFireforgeVerdictLine(verdict, shards) {
|
|
|
663
673
|
const tail = `${formatShardsSuffix(shards)}${verdict.note !== undefined ? ` (${verdict.note})` : ''}`;
|
|
664
674
|
if (verdict.kind === 'tests-ran-ok')
|
|
665
675
|
return `FIREFORGE-VERDICT: PASS${counts}${tail}`;
|
|
666
|
-
const reason = verdict.kind === 'harness-crash' ? 'crash' : verdict.kind;
|
|
676
|
+
const reason = verdict.kind === 'harness-crash' ? (verdict.signature?.verdictReason ?? 'crash') : verdict.kind;
|
|
667
677
|
return `FIREFORGE-VERDICT: FAIL reason=${reason}${counts}${formatIncompleteSuffix(verdict.incomplete)}${tail}`;
|
|
668
678
|
}
|
|
669
679
|
/**
|
|
@@ -690,17 +700,6 @@ export function buildGreenSummaryRejectedMessage(rejection, exitCode) {
|
|
|
690
700
|
'FAILED run — check the crash/truncation point in the output above, then re-run the ' +
|
|
691
701
|
'remaining files.');
|
|
692
702
|
}
|
|
693
|
-
/** Builds the operator-facing failure message after retries are exhausted. */
|
|
694
|
-
export function buildHarnessCrashMessage(signature, attempts, commandLabel = 'mach test') {
|
|
695
|
-
return (`${commandLabel} crashed in the harness itself (not in your tests) on all ${attempts} attempt(s).\n\n` +
|
|
696
|
-
`Detected shape: ${signature.reason}\n` +
|
|
697
|
-
`Evidence line: ${signature.line}\n\n` +
|
|
698
|
-
'This failure mode is environmental (mozlog resource monitor / psutil on macOS, focus-stall ' +
|
|
699
|
-
'shutdown re-entry, or a pre-test hang) rather than a test regression. Re-run the command, ' +
|
|
700
|
-
'raise the retry budget with --harness-retries <n>, or run the file in isolation. ' +
|
|
701
|
-
'If it persists across many runs, inspect the mach virtualenv (mach resyncs psutil on its own; ' +
|
|
702
|
-
'patching it manually does not stick).');
|
|
703
|
-
}
|
|
704
703
|
/**
|
|
705
704
|
* Exit codes that mean "the child died on SIGSEGV": Node reports a
|
|
706
705
|
* signal-killed child as the negated signal number, while a shell layer
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness failures that are the environment's, not the tests': the
|
|
3
|
+
* operator message for a recognized harness crash after its retries ran
|
|
4
|
+
* out, and the mochitest server that never came up.
|
|
5
|
+
*
|
|
6
|
+
* A server never comes up when the harness's httpd cannot bind its port,
|
|
7
|
+
* typically because a parallel `--jobs` instance, a sibling checkout or a
|
|
8
|
+
* leftover httpd held it (see `harness-port-reservation.ts`). Without this
|
|
9
|
+
* shape the run read as `no-tests`, a finding about the
|
|
10
|
+
* request, and was not retried. It is an infrastructure failure instead:
|
|
11
|
+
* `classifyHarnessRun` reports it as a `harness-crash` carrying
|
|
12
|
+
* `verdictReason: 'server-startup'`, so the harness-crash retry loop
|
|
13
|
+
* (`--harness-retries`) reruns the shard, and a run that exhausts the
|
|
14
|
+
* budget says `reason=server-startup` on its verdict line.
|
|
15
|
+
*/
|
|
16
|
+
import type { HarnessCrashSignature } from './test-harness-signature.js';
|
|
17
|
+
/**
|
|
18
|
+
* Detects a mochitest server that failed to start. The caller checks that
|
|
19
|
+
* no test ran first: both lines precede any test.
|
|
20
|
+
*
|
|
21
|
+
* @param output - Captured mach stdout and stderr
|
|
22
|
+
* @returns The infrastructure signature, or undefined
|
|
23
|
+
*/
|
|
24
|
+
export declare function detectServerStartupFailure(output: string): HarnessCrashSignature | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Builds the operator-facing failure message after retries are exhausted.
|
|
27
|
+
*
|
|
28
|
+
* @param signature - The recognized shape
|
|
29
|
+
* @param attempts - Attempts made
|
|
30
|
+
* @param commandLabel - The mach command, for the message
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildHarnessCrashMessage(signature: HarnessCrashSignature, attempts: number, commandLabel?: string): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Harness failures that are the environment's, not the tests': the
|
|
4
|
+
* operator message for a recognized harness crash after its retries ran
|
|
5
|
+
* out, and the mochitest server that never came up.
|
|
6
|
+
*
|
|
7
|
+
* A server never comes up when the harness's httpd cannot bind its port,
|
|
8
|
+
* typically because a parallel `--jobs` instance, a sibling checkout or a
|
|
9
|
+
* leftover httpd held it (see `harness-port-reservation.ts`). Without this
|
|
10
|
+
* shape the run read as `no-tests`, a finding about the
|
|
11
|
+
* request, and was not retried. It is an infrastructure failure instead:
|
|
12
|
+
* `classifyHarnessRun` reports it as a `harness-crash` carrying
|
|
13
|
+
* `verdictReason: 'server-startup'`, so the harness-crash retry loop
|
|
14
|
+
* (`--harness-retries`) reruns the shard, and a run that exhausts the
|
|
15
|
+
* budget says `reason=server-startup` on its verdict line.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The harness's own lines for the shape: the httpd's bind failure
|
|
19
|
+
* (`!!! could not start server on port 8888`) and `runtests.py`'s wait for
|
|
20
|
+
* it (`Timed out while waiting for server startup`).
|
|
21
|
+
*/
|
|
22
|
+
const SERVER_STARTUP_FAILURE_PATTERNS = [
|
|
23
|
+
/could not start server on port \d+/,
|
|
24
|
+
/Timed out while waiting for server startup/,
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Detects a mochitest server that failed to start. The caller checks that
|
|
28
|
+
* no test ran first: both lines precede any test.
|
|
29
|
+
*
|
|
30
|
+
* @param output - Captured mach stdout and stderr
|
|
31
|
+
* @returns The infrastructure signature, or undefined
|
|
32
|
+
*/
|
|
33
|
+
export function detectServerStartupFailure(output) {
|
|
34
|
+
for (const line of output.split(/\r?\n/)) {
|
|
35
|
+
if (SERVER_STARTUP_FAILURE_PATTERNS.some((pattern) => pattern.test(line))) {
|
|
36
|
+
return {
|
|
37
|
+
reason: 'mochitest server failed to start (server-startup)',
|
|
38
|
+
line: line.trim(),
|
|
39
|
+
verdictReason: 'server-startup',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Builds the operator-facing failure message after retries are exhausted.
|
|
47
|
+
*
|
|
48
|
+
* @param signature - The recognized shape
|
|
49
|
+
* @param attempts - Attempts made
|
|
50
|
+
* @param commandLabel - The mach command, for the message
|
|
51
|
+
*/
|
|
52
|
+
export function buildHarnessCrashMessage(signature, attempts, commandLabel = 'mach test') {
|
|
53
|
+
if (signature.verdictReason !== 'server-startup') {
|
|
54
|
+
return (`${commandLabel} crashed in the harness itself (not in your tests) on all ${attempts} attempt(s).\n\n` +
|
|
55
|
+
`Detected shape: ${signature.reason}\n` +
|
|
56
|
+
`Evidence line: ${signature.line}\n\n` +
|
|
57
|
+
'This failure mode is environmental (mozlog resource monitor / psutil on macOS, focus-stall ' +
|
|
58
|
+
'shutdown re-entry, or a pre-test hang) rather than a test regression. Re-run the command, ' +
|
|
59
|
+
'raise the retry budget with --harness-retries <n>, or run the file in isolation. ' +
|
|
60
|
+
'If it persists across many runs, inspect the mach virtualenv (mach resyncs psutil on its own; ' +
|
|
61
|
+
'patching it manually does not stick).');
|
|
62
|
+
}
|
|
63
|
+
return (`${commandLabel} could not start a mochitest server on all ${attempts} attempt(s), so no ` +
|
|
64
|
+
'test ran (an infrastructure failure, not a test result).\n\n' +
|
|
65
|
+
`Evidence line: ${signature.line}\n\n` +
|
|
66
|
+
'Another harness (a parallel --jobs instance, a sibling checkout, or a leftover httpd) ' +
|
|
67
|
+
'most likely held the server port when this one started. Re-run the shard, raise the ' +
|
|
68
|
+
'retry budget with --harness-retries <n>, or check "lsof -nP -iTCP:8888".');
|
|
69
|
+
}
|
|
@@ -19,6 +19,12 @@ export interface HarnessCrashSignature {
|
|
|
19
19
|
reason: string;
|
|
20
20
|
/** The concrete output line the recognition was based on. */
|
|
21
21
|
line: string;
|
|
22
|
+
/**
|
|
23
|
+
* The verdict line's `reason=` for an infrastructure shape that is not a
|
|
24
|
+
* crash of the harness: `server-startup` when a mochitest server never
|
|
25
|
+
* came up. Unset: `reason=crash`.
|
|
26
|
+
*/
|
|
27
|
+
verdictReason?: 'server-startup';
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* The verdict line's `started=<n>/<m> first-unstarted=<path>
|
|
@@ -48,6 +48,44 @@ export declare function checkStaleBuildForTest(projectRoot: string, engineDir: s
|
|
|
48
48
|
* result without matching the rendered copy.
|
|
49
49
|
*/
|
|
50
50
|
export declare function formatStaleBuildWarning(result: StaleBuildResult): string;
|
|
51
|
+
/** Result of {@link findCompiledSourcesNewerThanBinary}. */
|
|
52
|
+
export interface StaleCompiledResult {
|
|
53
|
+
/** Engine-relative compiled sources modified after the binary was linked. Sorted. */
|
|
54
|
+
paths: string[];
|
|
55
|
+
/** Engine-relative file that anchored the comparison (the binary or its libxul). */
|
|
56
|
+
linkedPath: string;
|
|
57
|
+
/** When that file was last written. */
|
|
58
|
+
linkedAt: Date;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Changed compiled sources (C++, Rust, IDL, WebIDL, IPDL, StaticPrefList
|
|
62
|
+
* YAML, …) whose mtime is newer than the launchable build's last link.
|
|
63
|
+
* `mach build faster` compiles none of them, so such a run tests the
|
|
64
|
+
* binary from before the edit, which reads as a failed fix rather than a
|
|
65
|
+
* stale build. Candidates are the engine paths changed since the baseline
|
|
66
|
+
* plus every workdir edit; a fork's persistent patch diff is older than any
|
|
67
|
+
* build that followed it, so only genuine post-build edits remain.
|
|
68
|
+
* Returns undefined when there is nothing to compare against (no
|
|
69
|
+
* launchable binary).
|
|
70
|
+
*
|
|
71
|
+
* @param engineDir - Absolute engine directory
|
|
72
|
+
* @param baseline - Last-build baseline, when one exists
|
|
73
|
+
* @param launchablePath - Engine-relative launchable binary path
|
|
74
|
+
*/
|
|
75
|
+
export declare function findCompiledSourcesNewerThanBinary(engineDir: string, baseline: BuildBaseline | undefined, launchablePath: string | undefined): Promise<StaleCompiledResult | undefined>;
|
|
76
|
+
/**
|
|
77
|
+
* The `stale-compiled` refusal (or, under `--allow-stale-build`, warning).
|
|
78
|
+
*
|
|
79
|
+
* @param result - A non-empty {@link StaleCompiledResult}
|
|
80
|
+
*/
|
|
81
|
+
export declare function formatStaleCompiledRefusal(result: StaleCompiledResult): string;
|
|
82
|
+
/**
|
|
83
|
+
* The notice that explains why a `test --build` pre-test build escalated
|
|
84
|
+
* to a full `mach build` for stale compiled sources.
|
|
85
|
+
*
|
|
86
|
+
* @param result - A non-empty {@link StaleCompiledResult}
|
|
87
|
+
*/
|
|
88
|
+
export declare function formatStaleCompiledBuildNotice(result: StaleCompiledResult): string;
|
|
51
89
|
/**
|
|
52
90
|
* Sentinel returned by {@link findUncoveredRequestPaths} when a full-suite
|
|
53
91
|
* request (no paths) is checked against a scoped coverage record.
|