@hominis/fireforge 0.50.0 → 0.51.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 +47 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/check-report.d.ts +17 -4
- package/dist/src/commands/check-report.js +19 -6
- package/dist/src/commands/check-run.d.ts +5 -0
- package/dist/src/commands/check-run.js +9 -1
- package/dist/src/commands/check-steps.d.ts +8 -0
- package/dist/src/commands/check-steps.js +31 -6
- package/dist/src/commands/check.js +1 -1
- package/dist/src/commands/declarations-report.d.ts +43 -0
- package/dist/src/commands/declarations-report.js +76 -0
- package/dist/src/commands/export-placement-gate.js +8 -0
- package/dist/src/commands/furnace/rename-registrations.js +7 -2
- package/dist/src/commands/furnace/validate.js +26 -1
- package/dist/src/commands/lint-per-patch.js +6 -2
- package/dist/src/commands/lint-per-run-checkjs.js +2 -2
- package/dist/src/commands/lint-report.js +7 -2
- package/dist/src/commands/manifest.js +2 -0
- package/dist/src/commands/park.d.ts +22 -0
- package/dist/src/commands/park.js +232 -0
- package/dist/src/commands/patch/delete.js +11 -6
- package/dist/src/commands/patch/index.d.ts +3 -3
- package/dist/src/commands/patch/index.js +8 -4
- package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
- package/dist/src/commands/patch/lint-ignore-from.js +142 -0
- package/dist/src/commands/patch/lint-ignore.js +39 -29
- package/dist/src/commands/patch/move-files-create.js +11 -4
- package/dist/src/commands/patch/move-files-into.js +10 -4
- package/dist/src/commands/patch/move-files.js +3 -1
- package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
- package/dist/src/commands/patch/removal-created-files.js +83 -0
- package/dist/src/commands/patch/rename.js +15 -3
- package/dist/src/commands/patch/reserve.d.ts +33 -0
- package/dist/src/commands/patch/reserve.js +152 -0
- package/dist/src/commands/patch/retire.js +11 -6
- package/dist/src/commands/patch/split-plan.d.ts +10 -1
- package/dist/src/commands/patch/split-plan.js +16 -1
- package/dist/src/commands/patch/split.js +14 -5
- package/dist/src/commands/patch/stage.d.ts +34 -0
- package/dist/src/commands/patch/stage.js +153 -0
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
- package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
- package/dist/src/commands/patch/staged-dependency.js +40 -98
- package/dist/src/commands/re-export-adjacent.d.ts +5 -0
- package/dist/src/commands/re-export-adjacent.js +4 -3
- package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
- package/dist/src/commands/re-export-bulk-scan.js +22 -7
- package/dist/src/commands/re-export-hunks.d.ts +35 -0
- package/dist/src/commands/re-export-hunks.js +220 -0
- package/dist/src/commands/re-export-options.js +29 -2
- package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
- package/dist/src/commands/re-export-purity-scope.js +131 -0
- package/dist/src/commands/re-export-register.js +15 -1
- package/dist/src/commands/re-export-removed.d.ts +1 -1
- package/dist/src/commands/re-export-removed.js +17 -2
- package/dist/src/commands/re-export-scan.d.ts +2 -0
- package/dist/src/commands/re-export-scan.js +4 -1
- package/dist/src/commands/re-export-single.js +102 -42
- package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
- package/dist/src/commands/re-export-stale-registrations.js +62 -0
- package/dist/src/commands/re-export.js +35 -34
- package/dist/src/commands/test-build-furnace.d.ts +3 -2
- package/dist/src/commands/test-build-furnace.js +8 -2
- package/dist/src/commands/test-build-phase.js +24 -7
- package/dist/src/commands/test-checkjs.js +3 -2
- package/dist/src/commands/test-dispatch.d.ts +39 -0
- package/dist/src/commands/test-dispatch.js +211 -0
- package/dist/src/commands/test-furnace-reach.d.ts +37 -0
- package/dist/src/commands/test-furnace-reach.js +132 -0
- package/dist/src/commands/test-orchestrate.d.ts +9 -0
- package/dist/src/commands/test-orchestrate.js +22 -4
- package/dist/src/commands/test-perf-scope.d.ts +21 -0
- package/dist/src/commands/test-perf-scope.js +55 -0
- package/dist/src/commands/test-prelock.js +100 -4
- package/dist/src/commands/test-register.js +18 -3
- package/dist/src/commands/test-results.d.ts +62 -0
- package/dist/src/commands/test-results.js +62 -0
- package/dist/src/commands/test-run.d.ts +13 -55
- package/dist/src/commands/test-run.js +73 -101
- package/dist/src/commands/test-shards.d.ts +110 -0
- package/dist/src/commands/test-shards.js +255 -0
- package/dist/src/commands/test-stale-gate.d.ts +5 -1
- package/dist/src/commands/test-stale-gate.js +4 -2
- package/dist/src/commands/test-verdict.d.ts +2 -1
- package/dist/src/commands/test.d.ts +1 -1
- package/dist/src/commands/test.js +65 -75
- package/dist/src/commands/token-lint.js +48 -8
- package/dist/src/commands/verify.js +9 -2
- package/dist/src/core/build-prepare.d.ts +6 -0
- package/dist/src/core/build-prepare.js +29 -3
- package/dist/src/core/config-paths.d.ts +1 -1
- package/dist/src/core/config-paths.js +2 -0
- package/dist/src/core/config-validate-check.js +83 -7
- package/dist/src/core/config-validate-test-toolchains.js +14 -0
- package/dist/src/core/config-validate-token-scales.d.ts +3 -0
- package/dist/src/core/config-validate-token-scales.js +47 -5
- package/dist/src/core/config-validate.js +6 -0
- package/dist/src/core/coverage-extend.js +2 -2
- package/dist/src/core/coverage-records.d.ts +11 -0
- package/dist/src/core/coverage-records.js +34 -0
- package/dist/src/core/engine-session-lock.d.ts +6 -0
- package/dist/src/core/engine-session-lock.js +10 -2
- package/dist/src/core/file-lock-shared.d.ts +57 -0
- package/dist/src/core/file-lock-shared.js +117 -0
- package/dist/src/core/file-lock.d.ts +9 -0
- package/dist/src/core/file-lock.js +58 -2
- package/dist/src/core/furnace-apply.js +10 -10
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +10 -3
- package/dist/src/core/furnace-config-validate-exceptions.js +39 -8
- package/dist/src/core/furnace-config-validate.js +7 -1
- package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
- package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
- package/dist/src/core/furnace-validate-accessibility.d.ts +4 -2
- package/dist/src/core/furnace-validate-accessibility.js +61 -27
- package/dist/src/core/furnace-validate-exceptions.d.ts +12 -4
- package/dist/src/core/furnace-validate-exceptions.js +41 -4
- package/dist/src/core/furnace-validate-icon-button.js +30 -1
- package/dist/src/core/history-log-file.js +8 -1
- package/dist/src/core/line-prefixer.d.ts +18 -0
- package/dist/src/core/line-prefixer.js +34 -0
- package/dist/src/core/mach.d.ts +7 -0
- package/dist/src/core/mach.js +24 -9
- package/dist/src/core/module-resolution-preflight.d.ts +19 -3
- package/dist/src/core/module-resolution-preflight.js +24 -6
- package/dist/src/core/negative-control-compiled.d.ts +27 -0
- package/dist/src/core/negative-control-compiled.js +73 -0
- package/dist/src/core/negative-control-diff.d.ts +14 -2
- package/dist/src/core/negative-control-diff.js +49 -6
- package/dist/src/core/negative-control.d.ts +12 -0
- package/dist/src/core/negative-control.js +48 -5
- package/dist/src/core/park-store.d.ts +63 -0
- package/dist/src/core/park-store.js +216 -0
- package/dist/src/core/patch-export-update.d.ts +4 -0
- package/dist/src/core/patch-export-update.js +12 -3
- package/dist/src/core/patch-export.d.ts +3 -2
- package/dist/src/core/patch-export.js +21 -14
- package/dist/src/core/patch-files.js +26 -8
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +6 -4
- package/dist/src/core/patch-lint-checkjs-any-import.js +9 -7
- package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
- package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
- package/dist/src/core/patch-lint-checkjs.js +13 -3
- package/dist/src/core/patch-lint-cross.d.ts +3 -1
- package/dist/src/core/patch-lint-cross.js +5 -0
- package/dist/src/core/patch-lint-css.js +14 -10
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +5 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +1 -1
- package/dist/src/core/patch-lint-ignore.d.ts +56 -12
- package/dist/src/core/patch-lint-ignore.js +173 -43
- package/dist/src/core/patch-lint-ownership.d.ts +10 -0
- package/dist/src/core/patch-lint-ownership.js +26 -0
- package/dist/src/core/patch-lint-size.js +9 -1
- package/dist/src/core/patch-lint-token-scale.d.ts +26 -8
- package/dist/src/core/patch-lint-token-scale.js +206 -29
- package/dist/src/core/patch-lint.js +2 -2
- package/dist/src/core/patch-manifest-io.js +8 -1
- package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
- package/dist/src/core/patch-manifest-key-order.js +61 -0
- package/dist/src/core/patch-manifest-stage.d.ts +46 -0
- package/dist/src/core/patch-manifest-stage.js +96 -0
- package/dist/src/core/patch-manifest-validate.js +27 -1
- package/dist/src/core/patch-order-legal.d.ts +2 -1
- package/dist/src/core/patch-order-legal.js +7 -2
- package/dist/src/core/patch-policy.d.ts +6 -2
- package/dist/src/core/patch-policy.js +14 -7
- package/dist/src/core/patch-retired.d.ts +26 -4
- package/dist/src/core/patch-retired.js +40 -2
- package/dist/src/core/run-log.d.ts +6 -0
- package/dist/src/core/run-log.js +17 -1
- package/dist/src/core/test-harness-crash.d.ts +2 -1
- package/dist/src/core/test-harness-crash.js +5 -8
- package/dist/src/core/test-harness-signature.d.ts +16 -0
- package/dist/src/core/test-harness-signature.js +19 -1
- package/dist/src/core/test-raw-log.d.ts +66 -0
- package/dist/src/core/test-raw-log.js +122 -0
- package/dist/src/core/test-run-completeness.d.ts +36 -3
- package/dist/src/core/test-run-completeness.js +57 -17
- package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
- package/dist/src/core/test-xpcshell-retry.js +2 -1
- package/dist/src/core/token-lint.d.ts +5 -2
- package/dist/src/core/token-lint.js +8 -3
- package/dist/src/core/token-sibling-sheets.d.ts +46 -0
- package/dist/src/core/token-sibling-sheets.js +119 -0
- package/dist/src/core/tree-guard.js +2 -0
- package/dist/src/core/typecheck-shim.d.ts +5 -1
- package/dist/src/core/typecheck-shim.js +115 -2
- package/dist/src/core/typecheck.js +3 -1
- package/dist/src/index.d.ts +9 -3
- package/dist/src/index.js +4 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +68 -7
- package/dist/src/types/commands/patches.d.ts +43 -0
- package/dist/src/types/config.d.ts +74 -2
- package/dist/src/types/furnace.d.ts +20 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +3 -2
- package/dist/src/utils/options.js +9 -4
- package/docs/configuration.md +94 -9
- package/docs/furnace.md +43 -1
- package/docs/lifecycle-invariants.md +13 -11
- package/docs/machine-output.md +64 -18
- package/docs/patch-workflow.md +174 -13
- package/docs/testing.md +73 -4
- package/package.json +3 -3
|
@@ -21,10 +21,11 @@ command, read the decision table at the bottom first.
|
|
|
21
21
|
take the `.fireforge/engine-session.lock`, then subsystem locks such as
|
|
22
22
|
build, furnace, or patch-directory locks. Furnace mutations serialize on a
|
|
23
23
|
per-root lock, and patch directory mutations (filename allocation plus
|
|
24
|
-
manifest writes) on a per-directory lock.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
manifest writes) on a per-directory lock. `re-export --dry-run` is the
|
|
25
|
+
exception: it writes nothing, runs its git plumbing on a private index
|
|
26
|
+
(so even the `--intent-to-add` staging an untracked binary needs never
|
|
27
|
+
reaches the shared `.git/index`), and serializes only against other dry
|
|
28
|
+
runs, so a preview no longer queues behind a peer's build or test run.
|
|
28
29
|
|
|
29
30
|
3. **A furnace mutation that does not finish restores the engine or says
|
|
30
31
|
so.** Both a signal (SIGINT or SIGTERM) and a thrown error trigger a
|
|
@@ -348,13 +349,14 @@ real-procfs `withFileLock` reap of a live-PID stale record.
|
|
|
348
349
|
The project-wide engine-session lock under `.fireforge/`, stamped with PID,
|
|
349
350
|
command, and start time metadata. CLI `build`, `test`, `export`, `re-export`,
|
|
350
351
|
`furnace apply`, `furnace deploy` and `furnace sync` take it before subsystem
|
|
351
|
-
locks
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
divergence
|
|
352
|
+
locks. `re-export --dry-run` does not: it runs inside `withPrivateGitIndex`,
|
|
353
|
+
so its temporary `--intent-to-add` staging lands on a throwaway index, and it
|
|
354
|
+
serializes only against other dry runs. Dry-run purity is enforced at runtime
|
|
355
|
+
by `withDryRunPurityGuard` (`re-export-bulk-scan.ts`). For `re-export` it
|
|
356
|
+
fingerprints what the dry run could touch (the engine HEAD and index, the
|
|
357
|
+
selected patches' bodies, their `patches.json` rows and the engine files they
|
|
358
|
+
own) and fails hard on divergence, naming a foreign writer when the history
|
|
359
|
+
log or the engine-session lock shows one in the window (`re-export-purity-scope.ts`).
|
|
358
360
|
|
|
359
361
|
Contention fails fast after about a second by default, with the fixed message
|
|
360
362
|
"Another FireForge engine-mutating command is already running. Wait for it to
|
package/docs/machine-output.md
CHANGED
|
@@ -53,21 +53,21 @@ if (options.json === true) {
|
|
|
53
53
|
|
|
54
54
|
## Current surfaces
|
|
55
55
|
|
|
56
|
-
| Surface | Shape
|
|
57
|
-
| ---------------------------------- |
|
|
58
|
-
| `status --json` | `{ schemaVersion: 1, … }`
|
|
59
|
-
| `status --json` under `--check` | adds `check: { enabled, failOn, allow?, failOnUnknown?, failed, offenders }`
|
|
60
|
-
| `furnace validate --json` | `{ schemaVersion: 1, passed, summary, maxWarnings?, components, issues, excepted, staleExceptions }`
|
|
61
|
-
| `check --json` | `{ schemaVersion: 1, verdict, reason?, summary, steps }`
|
|
62
|
-
| `check` verdict line | `FIREFORGE-VERDICT: PASS\|FAIL [reason=step-failures\|lock-timeout failed=<steps>] steps=<n> skipped=<n
|
|
63
|
-
| `tree list --json` | `{ schemaVersion: 1, trees }`
|
|
64
|
-
| `token list --json` | `{ schemaVersion: 1, tokensCssPath, categories }`
|
|
65
|
-
| `token show --json` | `{ schemaVersion: 1, name, category, declarations }`
|
|
66
|
-
| `token lint --json` | `{ schemaVersion: 1, tokensCssPath, tokenPrefix, filesScanned, findings }`
|
|
67
|
-
| `test` verdict line | `FIREFORGE-VERDICT: PASS\|FAIL reason=… [note=<class>] [started=<n>/<m> first-unstarted=<path>] [runs=<p>/<n>] [control=<outcome>] [shuffle=<seed>] [furnace-applied=<names>\|furnace-apply=skipped] [log=<path>]` | Not JSON. A single final stdout line, sealed by `setStdoutSealed` so nothing can displace it. `log=` names the run's own complete output under `.fireforge/logs/`, so a piped or truncated run still leaves a re-readable artifact |
|
|
68
|
-
| `lint --per-patch --report <path>` | `{ schemaVersion: 1, patches, queueIssues, totals, … }`
|
|
69
|
-
| `status --raw` | `git status --porcelain` lines
|
|
70
|
-
| `build` log announcement | `Full build output: <path>`
|
|
56
|
+
| Surface | Shape | Notes |
|
|
57
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `status --json` | `{ schemaVersion: 1, … }` | Error envelope on three engine preconditions |
|
|
59
|
+
| `status --json` under `--check` | adds `check: { enabled, failOn, allow?, failOnUnknown?, failed, offenders }` | Since 0.50.0 on the full payload too, not only `--summary`. `allow` and `failOnUnknown` appear only when set. An offender failing only through `--fail-on-unknown` carries `unnamed: true`. `--patches` adds `scope: { patches }` |
|
|
60
|
+
| `furnace validate --json` | `{ schemaVersion: 1, passed, summary, maxWarnings?, components, issues, excepted, staleExceptions }` | `issues` counts after `validationExceptions`, stale-exception warnings included. `excepted` carries each suppressed finding with its `reason` |
|
|
61
|
+
| `check --json` | `{ schemaVersion: 1, verdict, reason?, summary, steps }` | One entry per step: `name`, `kind`, `command`, `status` (`pass`/`fail`/`skipped`), `exitCode`, `durationMs`, `detail`, and on failure `outputTail` (`timedOut` when killed at its budget). No verdict line under `--json` |
|
|
62
|
+
| `check` verdict line | `FIREFORGE-VERDICT: PASS\|FAIL [reason=step-failures\|lock-timeout\|skipped-steps failed=<steps>] steps=<n> skipped=<n> [skipped-steps=<steps>]` | Not JSON. The last stdout line, after the step table, sealed like `test`'s. Its `reason=` set is its own, not `test`'s |
|
|
63
|
+
| `tree list --json` | `{ schemaVersion: 1, trees }` | Error envelope added in 0.44.0 |
|
|
64
|
+
| `token list --json` | `{ schemaVersion: 1, tokensCssPath, categories }` | Categories in file order, each with its tokens (`name`, `line`, `value`) |
|
|
65
|
+
| `token show --json` | `{ schemaVersion: 1, name, category, declarations }` | One entry per declaring block, with its selector trail and line |
|
|
66
|
+
| `token lint --json` | `{ schemaVersion: 1, tokensCssPath, tokenPrefix, filesScanned, findings }` | Each finding has `check`, `file`, `line`, `token`, `message`. The document is written even when findings exist; the exit is then non-zero, as with `status --check --json` |
|
|
67
|
+
| `test` verdict line | `FIREFORGE-VERDICT: PASS\|FAIL reason=… [note=<class>] [started=<n>/<m> first-unstarted=<path> started-source=<src>] [shards=<p>/<t> [failed-shards=<labels>]] [runs=<p>/<n>] [control=<outcome>] [shuffle=<seed>] [furnace-applied=<names>\|furnace-apply=skipped] [log=<path>]` | Not JSON. A single final stdout line, sealed by `setStdoutSealed` so nothing can displace it. `log=` names the run's own complete output under `.fireforge/logs/`, so a piped or truncated run still leaves a re-readable artifact |
|
|
68
|
+
| `lint --per-patch --report <path>` | `{ schemaVersion: 1, patches, queueIssues, totals, … }` | Written to a file. `queueIssues` holds the cross-patch findings; `patch staged-dependency --add --from` reads back their `stagedDeclarations` |
|
|
69
|
+
| `status --raw` | `git status --porcelain` lines | Not JSON, but still a machine surface: it engages the same stdout discipline, so rules 3 and 4 apply and rules 1 and 2 do not. A clean tree prints nothing |
|
|
70
|
+
| `build` log announcement | `Full build output: <path>` | Not JSON. `build` prints no verdict line, so it names its run log directly on the way out |
|
|
71
71
|
|
|
72
72
|
`--raw` is why `cli.ts` reads `process.argv` for `--json` or `--raw` before
|
|
73
73
|
dispatching. Rule 3 is about who owns stdout, and that question is settled
|
|
@@ -80,6 +80,19 @@ it. Follow the rules above rather than inventing a shape.
|
|
|
80
80
|
|
|
81
81
|
The run logs behind `log=` are specified in [`run-logs.md`](run-logs.md).
|
|
82
82
|
|
|
83
|
+
Additive keys since 0.51.0 outside `test`:
|
|
84
|
+
|
|
85
|
+
- `check --json`: a skipped step carries `skipKind`, `config` when
|
|
86
|
+
`check.skip` names it and `unavailable` when the project has nothing for
|
|
87
|
+
it to run. The verdict line adds `skipped-steps=<steps>` whenever a step
|
|
88
|
+
is skipped, and `reason=skipped-steps` when `check.failOnSkipped` fails a
|
|
89
|
+
run on an `unavailable` skip alone.
|
|
90
|
+
- `furnace validate --json`: a finding about particular elements carries
|
|
91
|
+
`tags` (`no-keyboard-handler` names each synthetic element with an
|
|
92
|
+
`@click`). An exception that matched an error adds a
|
|
93
|
+
`validation-exception-on-error` error, and a full run under
|
|
94
|
+
`furnace.json#minComponents` a `component-floor` error on `furnace.json`.
|
|
95
|
+
|
|
83
96
|
## Versioning
|
|
84
97
|
|
|
85
98
|
`schemaVersion` is `MACHINE_OUTPUT_SCHEMA_VERSION` in
|
|
@@ -159,6 +172,35 @@ that has none. A run refused only for a non-zero `unexpected=` count or a
|
|
|
159
172
|
mid-test shutdown carries neither. Absent on every other line. See
|
|
160
173
|
[`testing.md`](testing.md#the-verdict-line).
|
|
161
174
|
|
|
175
|
+
`started-source=raw|stream|capture` follows them and names the evidence the
|
|
176
|
+
count came from: the mozlog structured log (a run with `--results` or
|
|
177
|
+
`--shard-size`), the complete streamed output (every other run), or, only
|
|
178
|
+
when nothing was streamed, the last 2 MB of the capture.
|
|
179
|
+
|
|
180
|
+
### Shards: `FIREFORGE-SHARD:` and `failed-shards=`
|
|
181
|
+
|
|
182
|
+
A sharded run prints one `FIREFORGE-SHARD:` line per finished shard, before
|
|
183
|
+
the verdict line:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
FIREFORGE-SHARD: PASS|FAIL [reason=…] [checks=<n>] [unexpected=<n>] shard=<i>/<n> path=<label> [failed-files=<path>,…]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`path=` is the shard's path argument (whitespace replaced by `_`), or a
|
|
190
|
+
`--shard-size`/`--jobs` chunk's first file plus `+<k>`. `failed-files=`
|
|
191
|
+
appears under `--shard-size` and names the chunk's files that failed. The
|
|
192
|
+
aggregate verdict appends `failed-shards=<label>,…` after `shards=` when any
|
|
193
|
+
shard did not pass; under `--shard-size` `shards=` counts files and
|
|
194
|
+
`failed-shards=` names files. Both are absent on a green run.
|
|
195
|
+
|
|
196
|
+
### Additive keys of parallel and per-file runs
|
|
197
|
+
|
|
198
|
+
`jobs=<n>` marks a `--jobs` run, `lock=shared` a run that held the engine
|
|
199
|
+
session lock shared, and `results=<path>` names the `--results` document. A
|
|
200
|
+
run whose engine changed mid-run only in files the running browser cannot
|
|
201
|
+
see keeps its verdict and appends `drift-tolerated=<n>`. A negative control
|
|
202
|
+
on compiled source appends `control-build=compiled`.
|
|
203
|
+
|
|
162
204
|
### The additive `shuffle=` key
|
|
163
205
|
|
|
164
206
|
A `fireforge test --shuffle [seed]` run records the seed used to permute
|
|
@@ -210,8 +252,10 @@ the verdict `reason=inconclusive` only when HEAD moved or a changed path is
|
|
|
210
252
|
packaged by the running build: a source an objdir install manifest names, a
|
|
211
253
|
directory one installs from, or a test file. Edits that no manifest installs
|
|
212
254
|
(compiled sources, build files, docs) leave the sample standing with a
|
|
213
|
-
warning naming them. Other runs
|
|
214
|
-
|
|
255
|
+
warning naming them. Other runs are inconclusive only when a changed path is
|
|
256
|
+
one the running browser can see: a file the objdir links to its source, one
|
|
257
|
+
staged at dispatch, or a test file or staging input of the run; anything
|
|
258
|
+
else leaves the verdict standing with `drift-tolerated=<n>`.
|
|
215
259
|
|
|
216
260
|
### Additive Furnace keys
|
|
217
261
|
|
|
@@ -219,4 +263,6 @@ A `fireforge test --build` or `--build-only` run whose pre-test Furnace apply
|
|
|
219
263
|
deployed components appends `furnace-applied=<name>,<name>…`: the components
|
|
220
264
|
whose `components/` source changed since their last deploy, which the
|
|
221
265
|
runtime under test therefore includes. `--no-furnace-apply` skips that apply
|
|
222
|
-
and appends `furnace-apply=skipped`.
|
|
266
|
+
and appends `furnace-apply=skipped`. `--furnace-apply reached` appends
|
|
267
|
+
`furnace-skipped=<names>` for components with undeployed edits that no
|
|
268
|
+
requested test reaches. All are absent otherwise.
|
package/docs/patch-workflow.md
CHANGED
|
@@ -37,6 +37,14 @@ directories. The manifest is JSON:
|
|
|
37
37
|
The command can be dry-run, refuses ambiguous ownership, and reports each
|
|
38
38
|
file-to-patch assignment before refreshing the patch.
|
|
39
39
|
|
|
40
|
+
`re-export --dry-run` takes no engine-session lock: it writes nothing, so it
|
|
41
|
+
does not queue behind a peer's build or test run, and its git plumbing runs on
|
|
42
|
+
a private index. Its purity guard covers what the dry run could touch (the
|
|
43
|
+
selected patches, their `patches.json` rows, the engine files they own, and
|
|
44
|
+
the engine HEAD and index). A peer writing any of those during the preview is
|
|
45
|
+
named from the history log or the engine-session lock, and the preview is
|
|
46
|
+
simply rerun.
|
|
47
|
+
|
|
40
48
|
To adopt files into several patches in one call, name each file's owner
|
|
41
49
|
with `--scan-file <patch>:<path>`. A call with more than one target patch
|
|
42
50
|
requires the prefix on every `--scan-file`. Selected patches that get no
|
|
@@ -68,6 +76,29 @@ module a later patch creates. They also refuse a forward registration
|
|
|
68
76
|
module), in the same refusal and with the `patch staged-dependency` command
|
|
69
77
|
that declares it, so one declaration pass covers both.
|
|
70
78
|
|
|
79
|
+
### Exporting by hunk
|
|
80
|
+
|
|
81
|
+
Re-export captures whole files, so on a shared engine a peer's unexported
|
|
82
|
+
line in a shared manifest or chrome document lands in the exporting patch.
|
|
83
|
+
Two flags export a file by hunk instead. Each takes one explicit patch and
|
|
84
|
+
cannot combine with `--scan`, `--files` or `--all`:
|
|
85
|
+
|
|
86
|
+
- `--hunks-from <diff>` exports each file the diff names as the patch's
|
|
87
|
+
current body for it plus only the diff's hunks. Files the diff does not
|
|
88
|
+
name keep their old section.
|
|
89
|
+
- `--exclude-hunks <diff>` exports each named file as the working tree minus
|
|
90
|
+
the diff's hunks. The other files export as usual.
|
|
91
|
+
|
|
92
|
+
Hunks are placed by their context, so a diff taken before a peer's edit
|
|
93
|
+
above it still applies, and a hunk whose context is gone refuses. The
|
|
94
|
+
section is diffed by git against HEAD on a throwaway index, and the engine
|
|
95
|
+
is not touched. A spine patch can then export one change's lines at a time:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
git -C engine diff -- browser/base/content/hominis.js > my-change.diff # trim to your hunks
|
|
99
|
+
fireforge re-export 200 --hunks-from my-change.diff
|
|
100
|
+
```
|
|
101
|
+
|
|
71
102
|
### Re-export belts and arguments
|
|
72
103
|
|
|
73
104
|
`--refuse-adjacent-unmanaged` refuses a patch when an unmanaged file is
|
|
@@ -82,6 +113,10 @@ session's unexported test in `test/hominis-tiles/` no longer refuses a
|
|
|
82
113
|
patch that owns `test/hominis/browser.toml`. The refusal names every file
|
|
83
114
|
with its anchor (`beside engine/<dir>` or `registered by engine/<carrier>`).
|
|
84
115
|
|
|
116
|
+
Beside `--scan` and `--scan-file` the belt judges the adjacent files the
|
|
117
|
+
scan did not adopt, so one call can adopt a new widget and its test and
|
|
118
|
+
still refuse a peer's neighbour. It cannot combine with `--files`.
|
|
119
|
+
|
|
85
120
|
Three carve-outs keep the belt armed for everything they do not name. Each
|
|
86
121
|
requires `--refuse-adjacent-unmanaged`, and each admitted file is still
|
|
87
122
|
listed:
|
|
@@ -142,7 +177,10 @@ deleted whose engine copy is back at HEAD:
|
|
|
142
177
|
fireforge re-export 202 --refuse-adjacent-unmanaged --refuse-foreign-drift --expect browser/themes/shared/hominis/widgets.css --expect-removed browser/themes/shared/hominis/stop.svg
|
|
143
178
|
```
|
|
144
179
|
|
|
145
|
-
|
|
180
|
+
Each removal must have exactly one selected owner, and one call may retire
|
|
181
|
+
paths from several selected patches (`re-export 102 202 --expect-removed a
|
|
182
|
+
--expect-removed b`). A path whose owner was left out of the selection is
|
|
183
|
+
refused with that owner named. A patch-created file must
|
|
146
184
|
be absent from disk and engine HEAD, and have a `new file mode` section in
|
|
147
185
|
that owner's patch. An upstream file must be tracked in HEAD, match it on
|
|
148
186
|
disk, and have a section in that owner's patch. Without the retirement, a
|
|
@@ -161,7 +199,18 @@ later patch creates names the earliest legal order for exporting those
|
|
|
161
199
|
files as their own patch (free, inside the category range, and not opening
|
|
162
200
|
a gap under `allowGaps: false`), and prints the exact `patch
|
|
163
201
|
staged-dependency --add` command for each edge, with a `--reason`
|
|
164
|
-
placeholder.
|
|
202
|
+
placeholder. A refused `--scan` adoption, `patch move-files` or `patch split`
|
|
203
|
+
also writes every declaration it proposes into one lint-report-shaped JSON
|
|
204
|
+
(`--declarations-out <path>`, by default under `.fireforge/declarations/`)
|
|
205
|
+
and names the single `patch staged-dependency <holder> --add --from <file>`
|
|
206
|
+
call per holding patch that discharges them all. Moving tests out of a patch
|
|
207
|
+
that owns a shared manifest no longer needs one declaration typed per
|
|
208
|
+
manifest line.
|
|
209
|
+
|
|
210
|
+
A re-export also drops a staged registration whose `creates` path no patch
|
|
211
|
+
in the queue owns any more, for example after a merge deleted the file it
|
|
212
|
+
registered. The dry run names the drop, and the write records it in the
|
|
213
|
+
history log (`re-export-staged-prune`).
|
|
165
214
|
|
|
166
215
|
An `export --order` (or `--before`/`--after`) refused on a new system
|
|
167
216
|
module that no patch registers in moz.build says "register first". When the
|
|
@@ -214,6 +263,40 @@ Under `fireforge patch`:
|
|
|
214
263
|
occupied. A patch that later takes the order (`export --order <n>`, a
|
|
215
264
|
rename or a renumber) fills the slot, which then disappears. `patch
|
|
216
265
|
compact` renumbers through retired slots like any other gap.
|
|
266
|
+
- `patch delete` and `patch retire` name each file the patch creates that is
|
|
267
|
+
still on disk, in the dry run and at the prompt: once the patch is gone
|
|
268
|
+
nothing owns it, so `status` would report it unmanaged. Delete those files
|
|
269
|
+
first, or pass `--delete-created` to remove them as part of the confirmed
|
|
270
|
+
operation (under the engine lock as well). Files the patch only modifies
|
|
271
|
+
keep their edits and become unmanaged, as before.
|
|
272
|
+
- `patch reserve <order> --category <c> --owner <label> [--reason <text>]`
|
|
273
|
+
holds an order for a patch a session has agreed to export but has not
|
|
274
|
+
exported yet. The reservation lives in `patches.json#reserved`. Like a
|
|
275
|
+
retired slot, the gap check counts it as occupied, so `export --order 571`
|
|
276
|
+
is legal while a peer holds 569 and 570. Unlike a retired slot, the
|
|
277
|
+
earliest-legal-order search and a default `export` skip it, because it is
|
|
278
|
+
held for its owner. The export that lands on the order fills it, with a
|
|
279
|
+
notice naming the owner. `patch reserve <order> --release` drops a
|
|
280
|
+
reservation whose patch will not come. An order a patch, a retired slot or
|
|
281
|
+
another reservation holds, or one outside the category's range, is
|
|
282
|
+
refused.
|
|
283
|
+
- `patch stage <name>...` stages the named patches' `.patch` files and only
|
|
284
|
+
their rows of `patches/patches.json` in the project repository's git index.
|
|
285
|
+
Every other row stays as at HEAD. The staged manifest is built from HEAD's
|
|
286
|
+
rows plus the named working rows (with their retired slots; a reservation
|
|
287
|
+
a staged row fills is dropped), validated, and written with `git
|
|
288
|
+
hash-object` and `git update-index`. A collision (two rows at one order) or
|
|
289
|
+
an invalid result is refused before the index is touched. The working copy
|
|
290
|
+
is never changed and nothing is committed. Name a patch the working copy
|
|
291
|
+
no longer has by its HEAD filename to stage its removal, and name both
|
|
292
|
+
filenames of a renamed patch.
|
|
293
|
+
- `patch staged-dependency <name> --remove` names the entries to remove by
|
|
294
|
+
any of `--file`, `--specifier`/`--line`, `--creates` and `--owner`. It needs
|
|
295
|
+
`--creates`, or `--file` with the matcher. `--creates` alone removes every
|
|
296
|
+
declaration for that created path, which is the cleanup after a merge
|
|
297
|
+
deletes it. Registration lines compare whitespace-insensitively, as the
|
|
298
|
+
lint does. A selection that matches nothing is refused with exit 8 (it used
|
|
299
|
+
to print "no staged registration matched" and exit 0), on a dry run too.
|
|
217
300
|
- `patch staged-dependency <name> --add --from <json-file>` adds many
|
|
218
301
|
declarations in one call under one lock hold. The file is a `lint
|
|
219
302
|
--per-patch --report` document (its findings' `stagedDeclarations` for
|
|
@@ -223,6 +306,24 @@ reason?, patch? }` entries; entries naming another patch are skipped, and
|
|
|
223
306
|
only its delta (`added` / `removed`) in the history; records written
|
|
224
307
|
before 0.50.0 carry the whole `before` / `after` lists instead.
|
|
225
308
|
|
|
309
|
+
### Parking a session's edits
|
|
310
|
+
|
|
311
|
+
Several sessions edit the same files, and a peer's `re-export
|
|
312
|
+
--refuse-foreign-drift` refuses while another session's hunks sit in its
|
|
313
|
+
patch's files. `fireforge park <patch>` sets them aside: every drifted file of
|
|
314
|
+
the patch goes back to its queue-applied baseline (or, with `--hunks <diff>`,
|
|
315
|
+
only the named hunks come out of the working tree), and both sides of each
|
|
316
|
+
file are kept under `.fireforge/park/<label>/`. After the owner commits,
|
|
317
|
+
`fireforge park --restore <label>` three-way merges the parked edits back on
|
|
318
|
+
top of the commit. A conflict leaves markers, keeps the park and exits
|
|
319
|
+
non-zero. `park --list` and `park --drop <label>` manage parks, `--dry-run`
|
|
320
|
+
previews, and park takes the engine lock.
|
|
321
|
+
|
|
322
|
+
Before parking it warns when a hunk it takes out removes a Fluent message id,
|
|
323
|
+
or a whole file, that files outside the patch still reference. A parked
|
|
324
|
+
string still used by markup another patch owns makes `document.l10n.ready`
|
|
325
|
+
reject in every new window, so move it somewhere you own first.
|
|
326
|
+
|
|
226
327
|
Every queue-mutating patch command accepts `--wait-lock [seconds]`. See
|
|
227
328
|
[`configuration.md`](configuration.md#lock-waits) for how the budget
|
|
228
329
|
resolves.
|
|
@@ -260,7 +361,15 @@ programmatic API, with the file-size helpers `isTestFile`,
|
|
|
260
361
|
`file-too-large` measures in a patch: the JS files it creates, and never a
|
|
261
362
|
modified file or a new file of another kind. The rule selects its files
|
|
262
363
|
through that same function, so an audit that uses it cannot drift from the
|
|
263
|
-
rule.
|
|
364
|
+
rule. Since 0.51.0 the API also exports the measurement the size rules
|
|
365
|
+
themselves take, `measurePatchSize(engineDir, diff, filesAffected, config)`
|
|
366
|
+
(lines, test-file lines, files and registration files under the configured
|
|
367
|
+
metric), `isPatchSizeRegistrationFile(file, globs)`, the per-line
|
|
368
|
+
`codeLineMask(file, content)` behind `countCodeLines`, and
|
|
369
|
+
`evaluatePatchPolicyContentForQueue(config, projectRoot, patchesDir,
|
|
370
|
+
manifest)`, the body-dependent `patchPolicy` rules `verify` runs. A waiver
|
|
371
|
+
audit or a policy probe can then measure a patch exactly as the lint does,
|
|
372
|
+
without importing `dist/` files by path.
|
|
264
373
|
|
|
265
374
|
`lint --per-patch` measures sizes on the working tree, the way export and
|
|
266
375
|
re-export do: each patch's diff is taken against the engine baseline from
|
|
@@ -272,10 +381,13 @@ thresholds.
|
|
|
272
381
|
|
|
273
382
|
Per-patch lint type-checks plain Firefox JS against a built-in
|
|
274
383
|
Firefox-globals shim that tracks upstream WebIDL additions per release. A
|
|
275
|
-
`resource://` or `chrome://` import
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
384
|
+
`resource://` or `chrome://` import resolves to the module the queue
|
|
385
|
+
creates under that name; a test script's own program sees the modules
|
|
386
|
+
created up to the test's patch. An import the program cannot resolve (a
|
|
387
|
+
module a later patch creates, an upstream module, or a basename two
|
|
388
|
+
patches create) is typed `any`; an implicit-`any` finding in a file with
|
|
389
|
+
such an import names it, since the whole-tree `fireforge typecheck` sees
|
|
390
|
+
the real type. See
|
|
279
391
|
[`configuration.md`](configuration.md#patchlint) for the project hooks
|
|
280
392
|
(`checkJsExtraShim`, `checkJsTestFiles`, `checkJsTestShim`).
|
|
281
393
|
|
|
@@ -328,11 +440,49 @@ longer reaches its own warning band, `lint --per-patch` prints a
|
|
|
328
440
|
`lint-ignore-removable` notice naming the `patch lint-ignore --remove`
|
|
329
441
|
command, and the `--report` JSON carries each ceiling under
|
|
330
442
|
`lintIgnoreCeilings` with its current `measurement` and a `state` of
|
|
331
|
-
`within`, `exceeded` or `removable`.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
443
|
+
`within`, `exceeded` or `removable`. A notice never exceeds a ceiling: it
|
|
444
|
+
gates nothing, so a notice-band measurement past `max` surfaces as the plain
|
|
445
|
+
notice it is. The report's `lintIgnoreWaivers` lists every entry, bare IDs
|
|
446
|
+
included (`kind: "bare"`, `max: null`), with the same `measurement` and
|
|
447
|
+
`state`, so an audit does not have to re-measure bare waivers from
|
|
448
|
+
`suppressedIssues`. For a bare waiver the state is informational:
|
|
449
|
+
`removable` also covers a rule this lint does not run. An `--add` for a rule
|
|
450
|
+
that already has an entry replaces it, so the same command moves a ceiling
|
|
451
|
+
or widens it back to a bare waiver. `export` and `re-export --lint-ignore
|
|
452
|
+
<id>` only append bare IDs, and never widen an existing ceiling. The manifest
|
|
453
|
+
refuses a ceiling on any other rule, and a second entry for the same rule.
|
|
454
|
+
|
|
455
|
+
Under `patchSizeMetric: "addedCode"` a general-tier patch's
|
|
456
|
+
`large-patch-lines` findings carry `share: "product"` (non-test files) or
|
|
457
|
+
`share: "test"` (test files, held to the test tier). A ceiling can name the
|
|
458
|
+
share it bounds, and `large-patch-lines` may then carry one ceiling per
|
|
459
|
+
share instead of a single one:
|
|
460
|
+
|
|
461
|
+
```json
|
|
462
|
+
"lintIgnore": [
|
|
463
|
+
{ "rule": "large-patch-lines", "share": "product", "max": 900, "reason": "…" },
|
|
464
|
+
{ "rule": "large-patch-lines", "share": "test", "max": 4000, "reason": "…",
|
|
465
|
+
"meta": { "kind": "structural", "owner": "tiles" } }
|
|
466
|
+
]
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
A ceiling's optional `meta` is a free-form JSON object FireForge keeps
|
|
470
|
+
verbatim and never reads, for a project's own waiver bookkeeping (kind,
|
|
471
|
+
owner, exit condition). The report echoes it.
|
|
472
|
+
|
|
473
|
+
Several ceilings go in one call, under one lock hold and one manifest write:
|
|
474
|
+
`--add <rule>=<max>` gives each entry its own ceiling (`--reason` applies to
|
|
475
|
+
all of them, `--share` scopes a `large-patch-lines` one), and `--from
|
|
476
|
+
<json-file>` adds every entry of a JSON array (check IDs, or `{ rule, max,
|
|
477
|
+
reason?, share?, meta?, patch? }` objects; entries naming another patch are
|
|
478
|
+
skipped, and `--reason` fills objects without one). Given a `lint --per-patch
|
|
479
|
+
--report` document instead, `--from` rebaselines each of the patch's
|
|
480
|
+
ceilings to its current `measurement`.
|
|
481
|
+
|
|
482
|
+
```sh
|
|
483
|
+
fireforge patch lint-ignore 310-ui-sidebar --add file-too-large=1200 --add large-patch-files=40 --reason "Rebaseline 2026-10"
|
|
484
|
+
fireforge patch lint-ignore 310-ui-sidebar --from lint-report.json
|
|
485
|
+
```
|
|
336
486
|
|
|
337
487
|
## CI enforcement
|
|
338
488
|
|
|
@@ -369,9 +519,20 @@ them (filename, stem, order number, manifest name or slug). A peer's drifted
|
|
|
369
519
|
patch then no longer turns this session's gate red. The limit is the
|
|
370
520
|
point: an unmanaged file belongs to no patch, so a scoped run never judges
|
|
371
521
|
unexported files, this session's included. Run the unscoped gate before a
|
|
372
|
-
commit that should cover them. `
|
|
522
|
+
commit that should cover them. `lint --per-patch --patches` keeps every
|
|
523
|
+
queue finding that names a scoped patch, even on a file the patch no longer
|
|
524
|
+
touches (a stale `staged-dependency-unused` declaration, since 0.51.0). `verify --patches` keeps findings about the
|
|
373
525
|
queue as a whole (a `patches.json` that does not parse) whatever the scope.
|
|
374
526
|
|
|
527
|
+
`verify` resolves every `resource:///modules/…` and `resource://gre/modules/…`
|
|
528
|
+
`.sys.mjs` specifier the queue's files import, and fails on a fork module that
|
|
529
|
+
is missing or that no `moz.build` at or above its directory registers. Such
|
|
530
|
+
an import otherwise crashes every browser start of the objdir, or kills
|
|
531
|
+
xpcshell with no output. An unscoped run also scans the engine worktree:
|
|
532
|
+
changed files are read for imports, and untracked files count as fork
|
|
533
|
+
modules. That covers a chrome script's lazy getter for a module that neither
|
|
534
|
+
file has exported yet.
|
|
535
|
+
|
|
375
536
|
`fireforge check` composes the static gates into one command: `status`
|
|
376
537
|
(as `--json --summary --check`), `verify`, `lint --per-patch`,
|
|
377
538
|
`typecheck`, `furnace validate` and `token coverage`, plus the project's
|
package/docs/testing.md
CHANGED
|
@@ -107,6 +107,21 @@ read from the objdir, not from `engine/`, so a control on it stays green
|
|
|
107
107
|
and reports `missed`: that result is the signal to target the file the
|
|
108
108
|
browser actually loads.
|
|
109
109
|
|
|
110
|
+
A control on compiled source (C/C++, Rust, IDL, WebIDL, IPDL or YAML that no
|
|
111
|
+
install manifest ships) can only reach the binary through a build. Without
|
|
112
|
+
`--build` it is refused before the lock. With `--build` it is applied before
|
|
113
|
+
the pre-test build, so the binary under test carries it, stays applied for
|
|
114
|
+
every `--repeat` run, and is restored with a fresh mtime so the next build
|
|
115
|
+
recompiles the original. The verdict adds `control-build=compiled`. A
|
|
116
|
+
build-less control whose packaging is not current is refused before the
|
|
117
|
+
lock with the advice to add `--build`, instead of ending `inconclusive`
|
|
118
|
+
after a full queue.
|
|
119
|
+
|
|
120
|
+
Besides `git diff` output, a control may be a plain unified diff
|
|
121
|
+
(`diff -u`, no `diff --git` lines; the path comes from `---`/`+++`) or a
|
|
122
|
+
`git diff --no-index <engine file> <edited copy>`: when the new side names a
|
|
123
|
+
copy outside `engine/` and `components/`, the control targets the old side.
|
|
124
|
+
|
|
110
125
|
### The restore safety model
|
|
111
126
|
|
|
112
127
|
- **Only under the lock.** Apply, run and restore all happen inside the
|
|
@@ -194,7 +209,11 @@ earlier path whose own inputs and `engine/mozconfig` are unchanged, whatever
|
|
|
194
209
|
moved elsewhere in the engine, including a peer's edits and an engine HEAD
|
|
195
210
|
move that touches none of them. A path whose inputs changed is dropped and
|
|
196
211
|
named, with the inputs that changed. Changed inputs this build restages are
|
|
197
|
-
allowed
|
|
212
|
+
allowed, and a scoped build of one file restages that file's test manifest
|
|
213
|
+
too: a manifest that gained an entry for the new file no longer drops the
|
|
214
|
+
claims of its sibling files. A build-less run's packaging gates also run
|
|
215
|
+
before the lock is requested, so a `coverage-replaced` or `stale-build`
|
|
216
|
+
refusal arrives before the run queues.
|
|
198
217
|
|
|
199
218
|
A scoped build after a full build keeps the claim full while nothing outside
|
|
200
219
|
its scope moved. Otherwise it carries the full build's anchor forward, and a
|
|
@@ -221,6 +240,15 @@ packages `engine/` as it stands, for example for a before-capture, names the
|
|
|
221
240
|
components with undeployed edits it left out, and stamps
|
|
222
241
|
`furnace-apply=skipped`.
|
|
223
242
|
|
|
243
|
+
On a shared engine a peer's default `test --build` deploys every session's
|
|
244
|
+
undeployed component edits. `--furnace-apply reached` (or
|
|
245
|
+
`test.furnaceApply: "reached"`) deploys only the components a requested test
|
|
246
|
+
reaches: the test path, the test file, a `head*.js` beside it, or any test
|
|
247
|
+
file under a requested directory names the component. The rest are named in
|
|
248
|
+
a notice and stamped `furnace-skipped=<names>`. A path-less build reaches
|
|
249
|
+
every component. `--furnace-apply none` is `--no-furnace-apply`; `all` is the
|
|
250
|
+
default.
|
|
251
|
+
|
|
224
252
|
When `patchLint.checkJs` and `patchLint.checkJsTestFiles` are enabled, named
|
|
225
253
|
pre-test builds check the selected test scripts before deployment or mach.
|
|
226
254
|
This includes new scripts not yet owned by an exported patch. The check runs
|
|
@@ -247,7 +275,7 @@ launchd-parented app remains unattributed and is not automatically killed.
|
|
|
247
275
|
`test --wait-browser [seconds]` waits for this objdir's browser to exit;
|
|
248
276
|
`test --wait-port [seconds]` waits for mochitest and Marionette listeners.
|
|
249
277
|
`build --wait-browser [seconds]` queues a full or UI build behind the browser.
|
|
250
|
-
Bare flags wait 60 seconds; explicit values accept 1–
|
|
278
|
+
Bare flags wait 60 seconds; explicit values accept 1–86400 seconds. They are
|
|
251
279
|
independent of the FireForge lock budget, and they are spent BEFORE the
|
|
252
280
|
engine session lock is requested, so a run waiting out a browser or a port
|
|
253
281
|
does not hold every peer's build, test and re-export behind it. The run then
|
|
@@ -433,9 +461,16 @@ group sweep.
|
|
|
433
461
|
Every test run ends with one machine-readable line:
|
|
434
462
|
|
|
435
463
|
```
|
|
436
|
-
FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [started=<n>/<m> first-unstarted=<path>] [runs=<p>/<n>] [control=<outcome>] [shuffle=<seed>] [orphans-reaped=<n>] [furnace-applied=<names>|furnace-apply=skipped] [log=<path>]
|
|
464
|
+
FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [started=<n>/<m> first-unstarted=<path> started-source=<src>] [shards=<p>/<t> [failed-shards=<labels>]] [runs=<p>/<n>] [control=<outcome>] [shuffle=<seed>] [orphans-reaped=<n>] [furnace-applied=<names>|furnace-apply=skipped] [furnace-skipped=<names>] [jobs=<n>] [lock=shared] [results=<path>] [log=<path>]
|
|
437
465
|
```
|
|
438
466
|
|
|
467
|
+
The start count reads every line the harness printed, not the last 2 MB of
|
|
468
|
+
captured output: a suite printing more than that (a large browser directory,
|
|
469
|
+
or any run under `--full-output`) used to report files that ran and passed
|
|
470
|
+
as never started. `started-source=` names the evidence. A sharded run also
|
|
471
|
+
prints a `FIREFORGE-SHARD:` line per shard and names the shards that did not
|
|
472
|
+
pass as `failed-shards=`; see [`machine-output.md`](machine-output.md).
|
|
473
|
+
|
|
439
474
|
A run is never `PASS` when its summary reports unexpected results, when the
|
|
440
475
|
harness printed "Application shut down (without crashing) in the middle of a
|
|
441
476
|
test", or when a requested test file never produced a start (or skip)
|
|
@@ -528,7 +563,41 @@ The two phases handle it differently, on purpose:
|
|
|
528
563
|
|
|
529
564
|
A test run holds the engine-session lock and snapshots the engine git
|
|
530
565
|
generation before and after the harness run, failing the verdict as invalid
|
|
531
|
-
if the tree changed mid-run
|
|
566
|
+
if the tree changed mid-run in a way the running browser can see: a file the
|
|
567
|
+
objdir links to its source, a file staged at dispatch, or a test file or
|
|
568
|
+
staging input of the run. A peer's edit to anything else (a compiled source,
|
|
569
|
+
a copied file, an unrelated test) leaves the verdict standing with a warning
|
|
570
|
+
and `drift-tolerated=<n>`; the next run's stale-build gate judges whether it
|
|
571
|
+
needs a rebuild.
|
|
572
|
+
|
|
573
|
+
`--shared-lock` (or `test.lockMode: "shared"`) holds the lock shared for a
|
|
574
|
+
build-less run that applies no negative control and uses auto ports, so
|
|
575
|
+
several such runs on one objdir overlap. Anything that writes (a build, a
|
|
576
|
+
re-export, a `test --build`) still holds the lock alone: it waits for shared
|
|
577
|
+
holders to finish, and new shared holders queue behind it.
|
|
578
|
+
`status --lock` counts shared holders. Orphan reaping only touches helpers
|
|
579
|
+
whose parent died, so overlapping runs do not reap each other's live
|
|
580
|
+
helpers.
|
|
581
|
+
|
|
582
|
+
`--jobs <n>` runs a request's shards on n harness instances inside one lock
|
|
583
|
+
hold. Each instance has its own profile and its own Marionette port, and
|
|
584
|
+
auto ports (required) move each instance's mochitest server ports; output
|
|
585
|
+
lines carry a `[job <i>]` prefix in the terminal and the run log. With
|
|
586
|
+
`--no-shard`, or a single directory argument, the files are split in order
|
|
587
|
+
into n contiguous chunks. Parallel browsers raise host load, so measure
|
|
588
|
+
before relying on it.
|
|
589
|
+
|
|
590
|
+
`--shard-size <n>` dispatches n files per mach invocation (mochitest restarts
|
|
591
|
+
the browser between files), paying the harness start once per chunk instead
|
|
592
|
+
of once per file, and judges each file from mozlog's structured log:
|
|
593
|
+
`shards=` then counts files and `failed-shards=` names failed files.
|
|
594
|
+
|
|
595
|
+
`--results <path>` writes one JSON record per test file and `--repeat` run
|
|
596
|
+
(status, expected status, duration, unexpected subtests, the shard, and the
|
|
597
|
+
run-log line where the dispatch began) from mozlog's structured log, which
|
|
598
|
+
each dispatch then writes with `--log-raw`, and names it on the verdict as
|
|
599
|
+
`results=<path>`. A `--log-raw <file>` already forwarded with `--mach-arg` is
|
|
600
|
+
read instead. The checks that need no lock run before it is
|
|
532
601
|
requested: the launchable binary, the named-file checkJs pass, and the
|
|
533
602
|
`--wait-browser`/`--wait-port` budgets. The run log is open from the start,
|
|
534
603
|
so a `reason=lock-timeout` line carries `log=` too.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hominis/fireforge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "FireForge — a build tool for customizing Firefox",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
77
77
|
"fast-check": "^4.6.0",
|
|
78
78
|
"husky": "^9.1.7",
|
|
79
|
-
"knip": "6.
|
|
79
|
+
"knip": "6.41.0",
|
|
80
80
|
"lint-staged": "^17.0.4",
|
|
81
|
-
"prettier": "3.9.
|
|
81
|
+
"prettier": "3.9.10",
|
|
82
82
|
"tsx": "^4.7.0",
|
|
83
83
|
"typescript": "~6.0.0",
|
|
84
84
|
"typescript-eslint": "^8.0.0",
|