@hominis/fireforge 0.48.0 → 0.49.1
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 +29 -0
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +16 -28
- package/dist/src/commands/build.js +30 -4
- package/dist/src/commands/doctor-engine-eslint.d.ts +3 -0
- package/dist/src/commands/doctor-engine-eslint.js +12 -0
- package/dist/src/commands/doctor-macos-sdk.js +7 -5
- package/dist/src/commands/doctor-source-pin.js +9 -2
- package/dist/src/commands/doctor.js +2 -0
- package/dist/src/commands/furnace/apply.js +10 -4
- package/dist/src/commands/furnace/create-templates.js +0 -3
- package/dist/src/commands/lint.js +4 -0
- package/dist/src/commands/manifest.d.ts +1 -2
- package/dist/src/commands/patch/delete.js +18 -4
- package/dist/src/commands/re-export-options.js +7 -0
- package/dist/src/commands/re-export-register.js +1 -0
- package/dist/src/commands/re-export-removed.d.ts +4 -0
- package/dist/src/commands/re-export-removed.js +49 -0
- package/dist/src/commands/re-export-single.js +4 -1
- package/dist/src/commands/re-export.js +4 -0
- package/dist/src/commands/test-browser-preflight.d.ts +28 -0
- package/dist/src/commands/test-browser-preflight.js +181 -0
- package/dist/src/commands/test-build-phase.js +30 -7
- package/dist/src/commands/test-checkjs.d.ts +3 -0
- package/dist/src/commands/test-checkjs.js +27 -0
- package/dist/src/commands/test-diagnose.js +3 -0
- package/dist/src/commands/test-harness-env.d.ts +5 -6
- package/dist/src/commands/test-harness-env.js +27 -7
- package/dist/src/commands/test-modes.d.ts +2 -4
- package/dist/src/commands/test-register.js +11 -5
- package/dist/src/commands/test-run.d.ts +2 -0
- package/dist/src/commands/test-run.js +21 -1
- package/dist/src/commands/test-verdict.d.ts +2 -2
- package/dist/src/commands/test.js +83 -211
- package/dist/src/core/build-baseline-types.d.ts +12 -14
- package/dist/src/core/build-baseline-validate.d.ts +3 -0
- package/dist/src/core/build-baseline-validate.js +53 -0
- package/dist/src/core/build-baseline.d.ts +4 -3
- package/dist/src/core/build-baseline.js +23 -11
- package/dist/src/core/component-source-guard.d.ts +20 -0
- package/dist/src/core/component-source-guard.js +68 -0
- package/dist/src/core/coverage-extend.d.ts +5 -34
- package/dist/src/core/coverage-extend.js +26 -37
- package/dist/src/core/engine-write-boundary.d.ts +5 -0
- package/dist/src/core/engine-write-boundary.js +41 -0
- package/dist/src/core/furnace-apply-helpers.js +8 -2
- package/dist/src/core/furnace-apply.js +7 -0
- package/dist/src/core/furnace-validate-accessibility.js +9 -12
- package/dist/src/core/furnace-validate.js +0 -43
- package/dist/src/core/gecko-dom-types.d.ts +2 -0
- package/dist/src/core/gecko-dom-types.js +17 -0
- package/dist/src/core/lit-template-regions.d.ts +4 -0
- package/dist/src/core/lit-template-regions.js +50 -0
- package/dist/src/core/mach-build-artifacts.d.ts +6 -6
- package/dist/src/core/mach-build-artifacts.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +1 -1
- package/dist/src/core/mach-resource-shim.js +2 -0
- package/dist/src/core/marionette-port.d.ts +2 -0
- package/dist/src/core/marionette-port.js +38 -53
- package/dist/src/core/mochitest-server-port.d.ts +1 -1
- package/dist/src/core/mochitest-server-port.js +20 -17
- package/dist/src/core/objdir-maintenance.d.ts +10 -0
- package/dist/src/core/objdir-maintenance.js +167 -0
- package/dist/src/core/patch-lint-checkjs.js +2 -1
- package/dist/src/core/patch-parse.js +8 -6
- package/dist/src/core/preflight-wait.d.ts +2 -0
- package/dist/src/core/preflight-wait.js +24 -0
- package/dist/src/core/process-owner.d.ts +9 -0
- package/dist/src/core/process-owner.js +43 -0
- package/dist/src/core/test-harness-crash.d.ts +1 -1
- package/dist/src/core/test-harness-crash.js +5 -5
- package/dist/src/core/test-host-state.d.ts +14 -0
- package/dist/src/core/test-host-state.js +80 -0
- package/dist/src/core/test-profile-files.d.ts +17 -0
- package/dist/src/core/test-profile-files.js +75 -0
- package/dist/src/core/test-stale-check.d.ts +6 -7
- package/dist/src/core/test-stale-check.js +9 -32
- package/dist/src/core/token-category.d.ts +7 -26
- package/dist/src/core/token-category.js +91 -117
- package/dist/src/core/token-inventory.js +12 -7
- package/dist/src/core/typecheck.js +6 -6
- package/dist/src/types/commands/options.d.ts +14 -3
- package/dist/src/utils/assert.js +2 -7
- package/dist/src/utils/child-env.d.ts +0 -3
- package/dist/src/utils/child-env.js +0 -3
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +15 -4
- package/dist/src/utils/fs.js +11 -1
- package/dist/src/utils/options.d.ts +16 -1
- package/dist/src/utils/options.js +5 -3
- package/dist/src/utils/paths.js +3 -2
- package/dist/src/utils/process-group.d.ts +1 -2
- package/dist/src/utils/process-group.js +1 -2
- package/dist/src/utils/process-input.js +0 -3
- package/dist/src/utils/process.d.ts +3 -2
- package/dist/src/utils/process.js +19 -7
- package/docs/configuration.md +12 -11
- package/docs/lifecycle-invariants.md +9 -5
- package/docs/machine-output.md +36 -19
- package/docs/patch-workflow.md +15 -0
- package/docs/testing.md +77 -12
- package/package.json +6 -5
|
@@ -4,6 +4,7 @@ import { constants as osConstants } from 'node:os';
|
|
|
4
4
|
import { StringDecoder } from 'node:string_decoder';
|
|
5
5
|
import { ExecTimeoutError } from '../errors/base.js';
|
|
6
6
|
import { buildChildEnv } from './child-env.js';
|
|
7
|
+
import { toError } from './errors.js';
|
|
7
8
|
import { dispatchCompleteLines } from './line-dispatch.js';
|
|
8
9
|
import { killProcessTree, sweepProcessGroup } from './process-group.js';
|
|
9
10
|
// 50 MB cap per stream to prevent OOM. Large toolchain builds (e.g. Firefox, Chromium)
|
|
@@ -169,6 +170,7 @@ async function spawnTracked(spec) {
|
|
|
169
170
|
? installGracefulShutdownForwarder(child, spec.graceMs, killTarget)
|
|
170
171
|
: undefined;
|
|
171
172
|
const closure = trackChildClosure();
|
|
173
|
+
let rejection;
|
|
172
174
|
child.on('error', (error) => {
|
|
173
175
|
// Abort/startup failure: make sure a partially-started tree does not
|
|
174
176
|
// outlive the dispatch (a mach dying at startup used to strand
|
|
@@ -176,15 +178,24 @@ async function spawnTracked(spec) {
|
|
|
176
178
|
if (options.processGroup === true) {
|
|
177
179
|
killProcessTree(child, 'SIGKILL', usesProcessGroup);
|
|
178
180
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
// An abort emits error before close. Keep the dispatch tracked until
|
|
182
|
+
// the child closes and both teardown sweeps finish, including on timeout.
|
|
183
|
+
rejection = toExecRejection(error, command, args, options.timeout, spec.rejectionOutput?.());
|
|
182
184
|
});
|
|
183
185
|
child.on('close', (code, signal) => {
|
|
184
186
|
forwarder?.dispose();
|
|
185
187
|
const finish = () => {
|
|
186
188
|
closure.settle();
|
|
187
|
-
|
|
189
|
+
if (rejection)
|
|
190
|
+
reject(rejection);
|
|
191
|
+
else {
|
|
192
|
+
try {
|
|
193
|
+
resolve(spec.result(code, signal));
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
reject(toError(error));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
188
199
|
};
|
|
189
200
|
// Group sweep first (it takes the helpers that stayed in the group),
|
|
190
201
|
// then the caller's own sweep (the ones that did not), then settle.
|
|
@@ -194,7 +205,7 @@ async function spawnTracked(spec) {
|
|
|
194
205
|
finish();
|
|
195
206
|
return;
|
|
196
207
|
}
|
|
197
|
-
|
|
208
|
+
Promise.resolve().then(sweep).then(finish, finish);
|
|
198
209
|
};
|
|
199
210
|
if (groupPid !== undefined) {
|
|
200
211
|
sweepProcessGroup(groupPid).then(callerSweep, callerSweep);
|
|
@@ -265,8 +276,9 @@ const activeChildClosures = new Set();
|
|
|
265
276
|
* Registers a child whose shutdown {@link waitForActiveChildShutdown} must
|
|
266
277
|
* wait for, and returns the handle that deregisters it.
|
|
267
278
|
*
|
|
268
|
-
* @returns `settle()`. Call
|
|
269
|
-
*
|
|
279
|
+
* @returns `settle()`. Call after child closure and required teardown finish.
|
|
280
|
+
* An abort's `error` event does not prove closure; do not settle there.
|
|
281
|
+
* A failed start may settle when no live child or teardown remains.
|
|
270
282
|
*/
|
|
271
283
|
export function trackChildClosure() {
|
|
272
284
|
let resolveClosed;
|
package/docs/configuration.md
CHANGED
|
@@ -149,17 +149,18 @@ When `patchLint.checkJs` is on, the same command also runs the per-patch
|
|
|
149
149
|
checkJs pass that `export` enforces, so a green `typecheck` means
|
|
150
150
|
export-clean types.
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
program
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`
|
|
152
|
+
Project build info is written in `.fireforge/typecheck/`, outside `engine/`,
|
|
153
|
+
with a key covering the shim, TypeScript version, compiler options and
|
|
154
|
+
FireForge version. Diagnostics always use a fresh project
|
|
155
|
+
program: prior incremental diagnostic state is never restored. Cached and
|
|
156
|
+
`--no-cache` runs therefore check the same complete file set. `--no-cache`
|
|
157
|
+
also disables build-info writes. A jsconfig's own `incremental` and
|
|
158
|
+
`tsBuildInfoFile` remain ignored.
|
|
159
|
+
|
|
160
|
+
Both project and per-patch checkJs provide Gecko DOM constructor
|
|
161
|
+
`isInstance(value)` predicates with instance narrowing, plus
|
|
162
|
+
`MouseEvent.MOZ_SOURCE_PEN`. These declarations retain normal DOM member
|
|
163
|
+
checking; they do not turn constructors or instances into `any`.
|
|
163
164
|
|
|
164
165
|
## `patchPolicy`
|
|
165
166
|
|
|
@@ -113,11 +113,15 @@ command, read the decision table at the bottom first.
|
|
|
113
113
|
carry primary shebangs, and mach rebuilds them in-tree), and runs
|
|
114
114
|
`mach configure` inside the tree so the configure-generated root files are
|
|
115
115
|
regenerated against the tree's paths rather than keeping the primary's. It
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
Before configure, relocation rewrites old-source symlinks, `.pp`/`.d`,
|
|
117
|
+
FasterMake and Cargo fingerprint metadata, and removes copied
|
|
118
|
+
`config.statusd/*/config.track` inventories. Those inventories contain
|
|
119
|
+
absolute WRITE destinations and must never be consumed from a clone.
|
|
120
|
+
Aliased objdirs or partial-config directories are refused. Afterwards
|
|
121
|
+
`findObjdirRelocationViolation` verifies config.status, backend.mk,
|
|
122
|
+
Makefile, config/autoconf.mk and every remaining objdir symlink for the
|
|
123
|
+
old source prefix. External toolchain links are allowed; source links
|
|
124
|
+
must no longer consult the old checkout. Finally it
|
|
121
125
|
copies `last-build.json` so the in-tree stale-build gates anchor
|
|
122
126
|
correctly.
|
|
123
127
|
|
package/docs/machine-output.md
CHANGED
|
@@ -86,15 +86,16 @@ moved.
|
|
|
86
86
|
`FIREFORGE-VERDICT: FAIL reason=<reason>` uses a closed set
|
|
87
87
|
(`FireforgeVerdictReason`, `src/commands/test-verdict.ts`):
|
|
88
88
|
|
|
89
|
-
| Reason
|
|
90
|
-
|
|
|
91
|
-
| `crash`
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
89
|
+
| Reason | Meaning |
|
|
90
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
91
|
+
| `crash` | The harness or the browser died, so there is no trustworthy suite result. |
|
|
92
|
+
| `harness-arguments` | Profile or other harness argument setup failed before any tests could run; a rebuild is not the repair. |
|
|
93
|
+
| `no-tests` | The run dispatched but nothing ran. |
|
|
94
|
+
| `test-failures` | The suite ran and reported unexpected results. |
|
|
95
|
+
| `preflight` | The run was refused before the harness was reached. |
|
|
96
|
+
| `inconclusive` | A result exists, but `engine/` moved under it or a perf run changed power source, so the result was discarded. |
|
|
97
|
+
| `lock-timeout` | The run never started: the engine session lock stayed contended. |
|
|
98
|
+
| `killed` | A signal terminated the run, or FireForge ended it because its parent process vanished. Written from the signal handler (or the parent-exit watchdog) so that a log tail always describes itself. A killed run must never be silent, or "killed", "still running" and "never started" all look alike. `signal=` names the cause: a signal name, or `parent-exit`. |
|
|
98
99
|
|
|
99
100
|
### The additive `note=` key
|
|
100
101
|
|
|
@@ -109,20 +110,19 @@ unchanged and still comes from the closed set above, so a consumer that
|
|
|
109
110
|
tokenises `key=value` pairs is unaffected, and a gate that names no class
|
|
110
111
|
emits no `note=` at all. The classes are not a closed set and may grow, so
|
|
111
112
|
consumers should treat an unrecognised one as opaque. Current values:
|
|
112
|
-
`stale-browser`, `stale-browser-kill-failed`, `marionette-port-busy`,
|
|
113
|
+
`browser-busy`, `stale-browser`, `stale-browser-kill-failed`, `marionette-port-busy`, `mochitest-port-busy`,
|
|
113
114
|
`coverage-replaced`, `stale-build`, `stale-components`.
|
|
114
115
|
|
|
115
116
|
### The additive `shuffle=` key
|
|
116
117
|
|
|
117
|
-
A `fireforge test --shuffle [seed]` run
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
shuffle.
|
|
118
|
+
A `fireforge test --shuffle [seed]` run records the seed used to permute
|
|
119
|
+
FireForge's isolated path-argument shards. Repeating the seed and selection
|
|
120
|
+
repeats that shard order. It also forwards native mach `--shuffle`, which
|
|
121
|
+
randomizes files within an invocation without using this seed. `--no-shard`
|
|
122
|
+
disables FireForge's seeded argument permutation. The seed is exported as
|
|
123
|
+
`FIREFORGE_SHUFFLE_SEED` for custom in-file task code and appended as
|
|
124
|
+
`shuffle=<seed>` to every verdict form. This field does not claim replayable
|
|
125
|
+
native harness file order. Absent when shuffle was not requested.
|
|
126
126
|
|
|
127
127
|
### The additive `orphans-reaped=` key
|
|
128
128
|
|
|
@@ -141,3 +141,20 @@ A preflight refusal's own text is written to stdout before the verdict line,
|
|
|
141
141
|
and into the run log, so the verdict stays the last stdout write while the
|
|
142
142
|
reason survives both a redirect and a `tail`. See
|
|
143
143
|
[`run-logs.md`](run-logs.md).
|
|
144
|
+
|
|
145
|
+
### Additive host and perf keys
|
|
146
|
+
|
|
147
|
+
`host-load=<number>` records the one-minute load at suite startup. Each suite
|
|
148
|
+
also samples the highest CPU process before and after dispatch. A contention
|
|
149
|
+
warning appends `host-cpu-warning=true`; the diagnostic names the process
|
|
150
|
+
and measured CPU. These diagnostics annotate a test failure without changing
|
|
151
|
+
its classifier reason.
|
|
152
|
+
|
|
153
|
+
Perf runs append `power-source=ac|battery|unknown`. On macOS the source is
|
|
154
|
+
read from `pmset -g ps`, so charging on AC is correctly `ac`. A known source
|
|
155
|
+
transition appends `power-changed=true` and refuses the run as
|
|
156
|
+
`reason=inconclusive`. The producer's sample JSON retains its fields and
|
|
157
|
+
gains `fireforgeHost: { start, end, powerSourceChanged }`, where each host
|
|
158
|
+
state includes `load`, `power` and an optional `topProcess` with CPU and
|
|
159
|
+
command. Consumers should tolerate this additive object. Unknown power
|
|
160
|
+
state is visible but never treated as a proven transition.
|
package/docs/patch-workflow.md
CHANGED
|
@@ -56,6 +56,21 @@ requested path produces no hunk. That is checked against the full requested
|
|
|
56
56
|
list rather than the subset left after filtering, so nothing dropped upstream
|
|
57
57
|
can pass as a silent success.
|
|
58
58
|
|
|
59
|
+
An absent file originally created by a selected patch can be retired with
|
|
60
|
+
repeatable `--expect-removed <path>` on scan-less re-export:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
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
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The removal must have exactly one selected owner, be absent from disk and
|
|
67
|
+
engine HEAD, and have a `new file mode` section in that owner's patch.
|
|
68
|
+
Every removal is validated before writes, in dry-run too. Other paths keep
|
|
69
|
+
both refusal checks; retirement grants no unmanaged or foreign-drift
|
|
70
|
+
exception. Removing every file would empty the patch and requires `patch
|
|
71
|
+
drop` instead. `--expect-removed` cannot combine with `--scan`, `--files` or
|
|
72
|
+
`--all`.
|
|
73
|
+
|
|
59
74
|
## Queue maintenance
|
|
60
75
|
|
|
61
76
|
Under `fireforge patch`:
|
package/docs/testing.md
CHANGED
|
@@ -34,9 +34,59 @@ build, `test` fails before launching stale artifacts. Use `--build` to
|
|
|
34
34
|
refresh, or `--allow-stale-build` only for intentional out-of-band rebuilds.
|
|
35
35
|
|
|
36
36
|
`--build-only` packages mixed-harness paths once, and then each harness half
|
|
37
|
-
can run without `--build`.
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
can run without `--build`. Scoped builds retain prior coverage automatically
|
|
38
|
+
when engine HEAD, `engine/mozconfig` and recorded staging inputs outside the
|
|
39
|
+
rebuilt scope are unchanged. Changed files explicitly included in this
|
|
40
|
+
build are allowed. The fingerprints include test scripts and support files,
|
|
41
|
+
not only packageable chrome sources. A failed anchor narrows the claim and
|
|
42
|
+
prints the dropped paths; `--extend-coverage` instead refuses. Baselines
|
|
43
|
+
without complete staging-input fingerprints require a new build before they
|
|
44
|
+
can retain prior coverage.
|
|
45
|
+
New dirty inputs outside the rebuilt scope invalidate retention conservatively,
|
|
46
|
+
including shared fixtures outside test directories.
|
|
47
|
+
|
|
48
|
+
When `patchLint.checkJs` and `patchLint.checkJsTestFiles` are enabled, named
|
|
49
|
+
pre-test builds check the selected test scripts before deployment or mach.
|
|
50
|
+
This includes new scripts not yet owned by an exported patch.
|
|
51
|
+
|
|
52
|
+
### Shared browsers, ports and host state
|
|
53
|
+
|
|
54
|
+
Browser ownership is checked before a pre-test deployment and before full
|
|
55
|
+
or UI builds. A live or unreadable parent means busy, with its owner named
|
|
56
|
+
when available. `--kill-stale-marionette` requires a dead parent plus harness
|
|
57
|
+
arguments; a profile argument alone does not prove abandonment. A plain
|
|
58
|
+
launchd-parented app remains unattributed and is not automatically killed.
|
|
59
|
+
|
|
60
|
+
`test --wait-browser [seconds]` waits for this objdir's browser to exit;
|
|
61
|
+
`test --wait-port [seconds]` waits for mochitest and Marionette listeners.
|
|
62
|
+
`build --wait-browser [seconds]` queues a full or UI build behind the browser.
|
|
63
|
+
Bare flags wait 60 seconds; explicit values accept 1–3600 seconds. They are
|
|
64
|
+
independent of the FireForge lock budget. On expiry the normal preflight
|
|
65
|
+
refusal and its remedy are preserved.
|
|
66
|
+
|
|
67
|
+
Every suite samples host load and the highest CPU process before and after
|
|
68
|
+
dispatch. Load at least 4 or a process at least 90% CPU produces a warning;
|
|
69
|
+
verdicts include `host-load` and, when needed, `host-cpu-warning=true`.
|
|
70
|
+
Perf runs include `power-source=ac|battery|unknown`; on macOS this comes from
|
|
71
|
+
`pmset -g ps`, including charging on AC. Sample JSON gains a `fireforgeHost`
|
|
72
|
+
object with start/end states and `powerSourceChanged`. A known power-source
|
|
73
|
+
transition produces `FAIL reason=inconclusive power-changed=true`.
|
|
74
|
+
Unknown power state is reported without inventing a transition.
|
|
75
|
+
|
|
76
|
+
### Profile overlays
|
|
77
|
+
|
|
78
|
+
Use repeatable `--profile-file source=relative/destination` to add files to
|
|
79
|
+
the test profile, for example:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
fireforge test --perf-samples sample.json --profile-file arm.css=chrome/userChrome.css browser/base/content/test/perf/browser_perf.js
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The source resolves from the project root. Destinations must stay relative
|
|
86
|
+
with no traversal. FireForge stages copies and merges only those staged
|
|
87
|
+
directories into the harness profile, preserving existing chrome files.
|
|
88
|
+
A raw `--extra-profile-file` directory collision is classified as
|
|
89
|
+
`reason=harness-arguments` and names this remedy rather than a rebuild.
|
|
40
90
|
|
|
41
91
|
### What a pre-test build costs
|
|
42
92
|
|
|
@@ -183,15 +233,16 @@ redirected run keeps the reason as well as the verdict. See
|
|
|
183
233
|
|
|
184
234
|
## Seeded shuffle
|
|
185
235
|
|
|
186
|
-
`fireforge test --shuffle`
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
236
|
+
`fireforge test --shuffle` deterministically permutes isolated mochitest path
|
|
237
|
+
arguments and prints the seed; `--shuffle=<seed>` replays that shard order for
|
|
238
|
+
the same input selection. A directory remains one invocation. `--no-shard`
|
|
239
|
+
disables this argument permutation. FireForge also forwards native mach
|
|
240
|
+
`--shuffle` within each invocation, whose file order remains unseeded and is
|
|
241
|
+
not replayed by the FireForge seed. `FIREFORGE_SHUFFLE_SEED=<seed>` is available
|
|
242
|
+
to custom harness `head.js` code for in-file task ordering, and `shuffle=<seed>`
|
|
243
|
+
is recorded on the verdict. The option is mochitest-only. Write
|
|
244
|
+
`--shuffle=<seed>` or place it after the paths because a bare
|
|
245
|
+
`--shuffle <path>` consumes the path as its optional seed.
|
|
195
246
|
|
|
196
247
|
Exit code 14 (`INCONCLUSIVE`) is not red: it means `engine/` moved while the
|
|
197
248
|
harness ran and the result was thrown away. Exit 15 (`LOCK_TIMEOUT`) means
|
|
@@ -256,3 +307,17 @@ instead, use a [verification tree](verification-trees.md).
|
|
|
256
307
|
In dev builds, files under `obj-*/dist/bin` may be symlinks back into the
|
|
257
308
|
source tree (prefs especially), so edit source prefs directly and keep a
|
|
258
309
|
backup before bisection experiments.
|
|
310
|
+
|
|
311
|
+
## Repository release gate
|
|
312
|
+
|
|
313
|
+
Run `npm run release:check` with the exact Node version in `.nvmrc` and npm
|
|
314
|
+
version in `package.json`'s `packageManager`. The gate verifies these pins
|
|
315
|
+
before formatting, whitespace, zero-warning lint, strict typecheck, development
|
|
316
|
+
and production dead-code checks, import cycles, coverage floors, and installed
|
|
317
|
+
package smoke tests. `prepublishOnly` and the CI quality job run the same gate.
|
|
318
|
+
Supported Node-version and OS matrices continue to run ordinary tests separately.
|
|
319
|
+
|
|
320
|
+
The full-Firefox integration runner is opt-in. It snapshots project files,
|
|
321
|
+
engine changes and the index before arming recovery; a refusal cannot erase an
|
|
322
|
+
existing workspace. Failed recovery fails the run, preserves affected paths and
|
|
323
|
+
writes recovery evidence for manual repair.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hominis/fireforge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.1",
|
|
4
4
|
"description": "FireForge — a build tool for customizing Firefox",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"format:check": "prettier --check --ignore-unknown \"src/**/*.ts\" \"bin/**/*.ts\" \"scripts/**/*.mjs\" \"eslint-rules/**/*.js\" \"package.json\" \"eslint.config.js\" \"vitest.config.ts\" \"vitest.pack.config.ts\" \"tsconfig.json\" \"tsconfig.build.json\" \".lintstagedrc.json\" \".prettierignore\" \".prettierrc\" \".gitignore\" \"README.md\" \"CHANGELOG.md\" \"docs/**/*.md\" \"knip.json\" \"knip.production.json\"",
|
|
40
40
|
"prepare": "node -e \"import('./scripts/prepare.mjs').catch((error) => { if (error && typeof error === 'object' && 'code' in error && error.code === 'ERR_MODULE_NOT_FOUND') process.exit(0); throw error; })\"",
|
|
41
41
|
"prepack": "npm run build && node ./scripts/generate-build-info.mjs --loud",
|
|
42
|
-
"release:check": "npm run format:check && npm run whitespace:check && npm run lint:ci && npm run typecheck && npm run deadcode:check && npm run deadcode:check:production && npm run cycles:check && npm run test:coverage && npm run pack:verify",
|
|
43
|
-
"prepublishOnly": "npm run release:check"
|
|
42
|
+
"release:check": "npm run toolchain:check && npm run format:check && npm run whitespace:check && npm run lint:ci && npm run typecheck && npm run deadcode:check && npm run deadcode:check:production && npm run cycles:check && npm run test:coverage && npm run pack:verify",
|
|
43
|
+
"prepublishOnly": "npm run release:check",
|
|
44
|
+
"toolchain:check": "node ./scripts/check-release-toolchain.mjs"
|
|
44
45
|
},
|
|
45
46
|
"files": [
|
|
46
47
|
"dist/",
|
|
@@ -75,9 +76,9 @@
|
|
|
75
76
|
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
76
77
|
"fast-check": "^4.6.0",
|
|
77
78
|
"husky": "^9.1.7",
|
|
78
|
-
"knip": "6.
|
|
79
|
+
"knip": "6.39.0",
|
|
79
80
|
"lint-staged": "^17.0.4",
|
|
80
|
-
"prettier": "3.9.
|
|
81
|
+
"prettier": "3.9.9",
|
|
81
82
|
"tsx": "^4.7.0",
|
|
82
83
|
"typescript": "~6.0.0",
|
|
83
84
|
"typescript-eslint": "^8.0.0",
|