@hominis/fireforge 0.49.1 → 0.50.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 +41 -0
- package/README.md +1 -1
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/build-prelock.d.ts +20 -0
- package/dist/src/commands/build-prelock.js +50 -0
- package/dist/src/commands/build.d.ts +3 -1
- package/dist/src/commands/build.js +13 -6
- package/dist/src/commands/check-report.d.ts +28 -0
- package/dist/src/commands/check-report.js +78 -0
- package/dist/src/commands/check-run.d.ts +28 -0
- package/dist/src/commands/check-run.js +104 -0
- package/dist/src/commands/check-steps.d.ts +67 -0
- package/dist/src/commands/check-steps.js +175 -0
- package/dist/src/commands/check.d.ts +32 -0
- package/dist/src/commands/check.js +160 -0
- package/dist/src/commands/config.js +5 -6
- package/dist/src/commands/doctor-engine-eslint.js +6 -1
- package/dist/src/commands/doctor-source-pin.js +4 -1
- package/dist/src/commands/export-adopt-check.d.ts +38 -0
- package/dist/src/commands/export-adopt-check.js +98 -0
- package/dist/src/commands/export-flow.js +29 -14
- package/dist/src/commands/export-placement-gate.d.ts +6 -2
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-staged-registration.d.ts +46 -0
- package/dist/src/commands/export-staged-registration.js +91 -0
- package/dist/src/commands/forward-import-remedy.d.ts +32 -0
- package/dist/src/commands/forward-import-remedy.js +63 -0
- package/dist/src/commands/furnace/apply.js +3 -3
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc.js +2 -2
- package/dist/src/commands/furnace/create-templates.d.ts +8 -3
- package/dist/src/commands/furnace/create-templates.js +8 -23
- package/dist/src/commands/furnace/create.js +2 -2
- package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
- package/dist/src/commands/furnace/deploy-named.js +107 -0
- package/dist/src/commands/furnace/deploy.d.ts +3 -2
- package/dist/src/commands/furnace/deploy.js +50 -86
- package/dist/src/commands/furnace/diff.js +26 -3
- package/dist/src/commands/furnace/index.js +66 -41
- package/dist/src/commands/furnace/init.js +13 -6
- package/dist/src/commands/furnace/override.js +4 -2
- package/dist/src/commands/furnace/preview.js +4 -3
- package/dist/src/commands/furnace/refresh.js +2 -2
- package/dist/src/commands/furnace/remove.js +4 -3
- package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
- package/dist/src/commands/furnace/rename-dry-run.js +127 -0
- package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
- package/dist/src/commands/furnace/rename-helpers.js +15 -1
- package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
- package/dist/src/commands/furnace/rename-registrations.js +93 -0
- package/dist/src/commands/furnace/rename.d.ts +2 -1
- package/dist/src/commands/furnace/rename.js +28 -66
- package/dist/src/commands/furnace/scan.d.ts +9 -4
- package/dist/src/commands/furnace/scan.js +11 -9
- package/dist/src/commands/furnace/sync.js +3 -2
- package/dist/src/commands/furnace/validate-report.d.ts +45 -0
- package/dist/src/commands/furnace/validate-report.js +91 -0
- package/dist/src/commands/furnace/validate.d.ts +1 -1
- package/dist/src/commands/furnace/validate.js +127 -114
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +31 -60
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +15 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +2 -0
- package/dist/src/commands/patch/delete-gap-notice.js +3 -1
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +13 -98
- package/dist/src/commands/patch/index.d.ts +1 -1
- package/dist/src/commands/patch/index.js +4 -2
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +65 -28
- package/dist/src/commands/patch/move-files-create.js +26 -17
- package/dist/src/commands/patch/move-files-into.js +5 -3
- package/dist/src/commands/patch/move-files.js +3 -1
- package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
- package/dist/src/commands/patch/removal-dependents.js +133 -0
- package/dist/src/commands/patch/rename.js +7 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +128 -0
- package/dist/src/commands/patch/split-plan.d.ts +7 -7
- package/dist/src/commands/patch/split-plan.js +45 -28
- package/dist/src/commands/patch/split-staged.d.ts +108 -0
- package/dist/src/commands/patch/split-staged.js +202 -0
- package/dist/src/commands/patch/split.d.ts +5 -0
- package/dist/src/commands/patch/split.js +51 -15
- package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
- package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
- package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
- package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
- package/dist/src/commands/patch/staged-dependency-from.js +108 -0
- package/dist/src/commands/patch/staged-dependency.js +14 -41
- package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
- package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
- package/dist/src/commands/re-export-adjacent.d.ts +45 -2
- package/dist/src/commands/re-export-adjacent.js +156 -37
- package/dist/src/commands/re-export-drift.d.ts +36 -8
- package/dist/src/commands/re-export-drift.js +73 -49
- package/dist/src/commands/re-export-files.js +11 -8
- package/dist/src/commands/re-export-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +45 -4
- package/dist/src/commands/re-export-preflight.d.ts +23 -0
- package/dist/src/commands/re-export-preflight.js +160 -0
- package/dist/src/commands/re-export-register.js +42 -17
- package/dist/src/commands/re-export-removed.d.ts +12 -1
- package/dist/src/commands/re-export-removed.js +41 -11
- package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
- package/dist/src/commands/re-export-scan-owner.js +116 -0
- package/dist/src/commands/re-export-scan.d.ts +17 -9
- package/dist/src/commands/re-export-scan.js +56 -23
- package/dist/src/commands/re-export-single.js +22 -6
- package/dist/src/commands/re-export-summary.d.ts +28 -0
- package/dist/src/commands/re-export-summary.js +36 -0
- package/dist/src/commands/re-export.js +37 -24
- package/dist/src/commands/rebase/index.js +17 -17
- package/dist/src/commands/run.js +16 -2
- package/dist/src/commands/status-check.d.ts +55 -16
- package/dist/src/commands/status-check.js +92 -37
- package/dist/src/commands/status-json.d.ts +22 -9
- package/dist/src/commands/status-json.js +47 -32
- package/dist/src/commands/status-output.js +3 -1
- package/dist/src/commands/status-scope.d.ts +37 -0
- package/dist/src/commands/status-scope.js +54 -0
- package/dist/src/commands/status.js +66 -23
- package/dist/src/commands/test-browser-preflight.js +19 -3
- package/dist/src/commands/test-build-furnace.d.ts +21 -0
- package/dist/src/commands/test-build-furnace.js +48 -0
- package/dist/src/commands/test-build-phase.js +47 -41
- package/dist/src/commands/test-checkjs.js +7 -0
- package/dist/src/commands/test-diagnose.js +7 -0
- package/dist/src/commands/test-modes.d.ts +16 -1
- package/dist/src/commands/test-modes.js +24 -1
- package/dist/src/commands/test-multi-verdict.d.ts +61 -0
- package/dist/src/commands/test-multi-verdict.js +111 -0
- package/dist/src/commands/test-orchestrate.d.ts +43 -0
- package/dist/src/commands/test-orchestrate.js +222 -0
- package/dist/src/commands/test-perf-scope.d.ts +29 -0
- package/dist/src/commands/test-perf-scope.js +83 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +177 -0
- package/dist/src/commands/test-register.js +54 -10
- package/dist/src/commands/test-run.js +4 -1
- package/dist/src/commands/test-stale-gate.js +57 -27
- package/dist/src/commands/test-verdict.d.ts +10 -1
- package/dist/src/commands/test-verdict.js +28 -1
- package/dist/src/commands/test.d.ts +6 -1
- package/dist/src/commands/test.js +66 -60
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +111 -0
- package/dist/src/commands/token.js +10 -0
- package/dist/src/commands/verify-scope.d.ts +28 -0
- package/dist/src/commands/verify-scope.js +67 -0
- package/dist/src/commands/verify.d.ts +10 -2
- package/dist/src/commands/verify.js +59 -35
- package/dist/src/core/build-baseline-types.d.ts +46 -0
- package/dist/src/core/build-baseline-validate.js +19 -0
- package/dist/src/core/build-baseline.d.ts +5 -1
- package/dist/src/core/build-baseline.js +3 -1
- package/dist/src/core/build-overwrite-guard.d.ts +50 -0
- package/dist/src/core/build-overwrite-guard.js +84 -4
- package/dist/src/core/build-prepare.d.ts +7 -0
- package/dist/src/core/build-prepare.js +14 -8
- package/dist/src/core/build-run-record.d.ts +74 -0
- package/dist/src/core/build-run-record.js +136 -0
- package/dist/src/core/checkjs-support-heads.d.ts +41 -0
- package/dist/src/core/checkjs-support-heads.js +104 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +8 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +143 -0
- package/dist/src/core/config-validate-file-size.d.ts +9 -6
- package/dist/src/core/config-validate-file-size.js +91 -2
- package/dist/src/core/config-validate-history.d.ts +11 -0
- package/dist/src/core/config-validate-history.js +38 -0
- package/dist/src/core/config-validate-patch-policy.js +100 -0
- package/dist/src/core/config-validate-test-toolchains.js +7 -0
- package/dist/src/core/config-validate-token-scales.d.ts +6 -0
- package/dist/src/core/config-validate-token-scales.js +50 -0
- package/dist/src/core/config-validate.js +14 -5
- package/dist/src/core/config.d.ts +5 -0
- package/dist/src/core/config.js +16 -0
- package/dist/src/core/coverage-dispatch.d.ts +24 -0
- package/dist/src/core/coverage-dispatch.js +44 -0
- package/dist/src/core/coverage-extend.d.ts +70 -45
- package/dist/src/core/coverage-extend.js +199 -144
- package/dist/src/core/coverage-records.d.ts +97 -0
- package/dist/src/core/coverage-records.js +350 -0
- package/dist/src/core/destructive.d.ts +7 -4
- package/dist/src/core/destructive.js +10 -10
- package/dist/src/core/engine-session-lock.d.ts +10 -1
- package/dist/src/core/engine-session-lock.js +28 -8
- package/dist/src/core/export-moved-code-shape.d.ts +49 -11
- package/dist/src/core/export-moved-code-shape.js +135 -44
- package/dist/src/core/file-lock-queue.d.ts +67 -0
- package/dist/src/core/file-lock-queue.js +221 -0
- package/dist/src/core/file-lock.d.ts +4 -25
- package/dist/src/core/file-lock.js +105 -138
- package/dist/src/core/furnace-apply-output.d.ts +10 -0
- package/dist/src/core/furnace-apply-output.js +31 -1
- package/dist/src/core/furnace-apply.js +12 -2
- package/dist/src/core/furnace-composed-source.d.ts +76 -0
- package/dist/src/core/furnace-composed-source.js +167 -0
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +9 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +71 -0
- package/dist/src/core/furnace-config-validate.js +8 -0
- package/dist/src/core/furnace-css-fragments.d.ts +10 -0
- package/dist/src/core/furnace-css-fragments.js +26 -0
- package/dist/src/core/furnace-operation.d.ts +3 -3
- package/dist/src/core/furnace-registration-remove.d.ts +22 -1
- package/dist/src/core/furnace-registration-remove.js +53 -17
- package/dist/src/core/furnace-registration-rename.d.ts +26 -0
- package/dist/src/core/furnace-registration-rename.js +77 -0
- package/dist/src/core/furnace-registration.d.ts +14 -4
- package/dist/src/core/furnace-registration.js +44 -10
- package/dist/src/core/furnace-staleness.d.ts +7 -0
- package/dist/src/core/furnace-staleness.js +34 -24
- package/dist/src/core/furnace-validate-accessibility.d.ts +4 -2
- package/dist/src/core/furnace-validate-accessibility.js +10 -1
- package/dist/src/core/furnace-validate-exceptions.d.ts +40 -0
- package/dist/src/core/furnace-validate-exceptions.js +43 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +49 -0
- package/dist/src/core/furnace-validate.js +1 -1
- package/dist/src/core/harness-port-fallback.d.ts +60 -0
- package/dist/src/core/harness-port-fallback.js +96 -0
- package/dist/src/core/history-log-file.d.ts +61 -0
- package/dist/src/core/history-log-file.js +157 -0
- package/dist/src/core/history-log.d.ts +2 -1
- package/dist/src/core/history-log.js +2 -1
- package/dist/src/core/json-preserving-edit.d.ts +22 -0
- package/dist/src/core/json-preserving-edit.js +199 -0
- package/dist/src/core/mach.js +8 -1
- package/dist/src/core/negative-control-diff.d.ts +39 -0
- package/dist/src/core/negative-control-diff.js +136 -0
- package/dist/src/core/negative-control.d.ts +138 -0
- package/dist/src/core/negative-control.js +356 -0
- package/dist/src/core/objdir-install-manifests.d.ts +73 -0
- package/dist/src/core/objdir-install-manifests.js +226 -0
- package/dist/src/core/patch-export-update.d.ts +2 -0
- package/dist/src/core/patch-export-update.js +1 -0
- package/dist/src/core/patch-export.js +3 -4
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +37 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +61 -0
- package/dist/src/core/patch-lint-checkjs.js +8 -11
- package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
- package/dist/src/core/patch-lint-code-lines.js +105 -0
- package/dist/src/core/patch-lint-cross.js +12 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +10 -4
- package/dist/src/core/patch-lint-file-size.d.ts +12 -5
- package/dist/src/core/patch-lint-file-size.js +22 -11
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +18 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +35 -10
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +152 -0
- package/dist/src/core/patch-lint-ignore.js +299 -0
- package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
- package/dist/src/core/patch-lint-size-thresholds.js +110 -0
- package/dist/src/core/patch-lint-size.d.ts +117 -0
- package/dist/src/core/patch-lint-size.js +323 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
- package/dist/src/core/patch-lint-staged-registration.js +20 -0
- package/dist/src/core/patch-lint-token-scale.d.ts +39 -0
- package/dist/src/core/patch-lint-token-scale.js +109 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +64 -286
- package/dist/src/core/patch-lock.js +7 -6
- package/dist/src/core/patch-manifest-consistency.js +7 -6
- package/dist/src/core/patch-manifest-io.d.ts +6 -3
- package/dist/src/core/patch-manifest-io.js +19 -8
- package/dist/src/core/patch-manifest-validate.js +34 -2
- package/dist/src/core/patch-order-legal.d.ts +25 -0
- package/dist/src/core/patch-order-legal.js +83 -0
- package/dist/src/core/patch-policy-content.d.ts +40 -0
- package/dist/src/core/patch-policy-content.js +216 -0
- package/dist/src/core/patch-policy.d.ts +16 -3
- package/dist/src/core/patch-policy.js +16 -9
- package/dist/src/core/patch-retired.d.ts +35 -0
- package/dist/src/core/patch-retired.js +54 -0
- package/dist/src/core/patch-subset.d.ts +16 -0
- package/dist/src/core/patch-subset.js +66 -0
- package/dist/src/core/preflight-wait.d.ts +20 -0
- package/dist/src/core/preflight-wait.js +38 -0
- package/dist/src/core/rebase-from-version.d.ts +46 -0
- package/dist/src/core/rebase-from-version.js +71 -0
- package/dist/src/core/run-log.d.ts +20 -0
- package/dist/src/core/run-log.js +89 -3
- package/dist/src/core/run-profile.d.ts +7 -0
- package/dist/src/core/run-profile.js +7 -1
- package/dist/src/core/smoke-patterns.d.ts +5 -0
- package/dist/src/core/smoke-patterns.js +13 -0
- package/dist/src/core/test-harness-crash.d.ts +18 -1
- package/dist/src/core/test-harness-crash.js +6 -4
- package/dist/src/core/test-harness-signature.d.ts +17 -0
- package/dist/src/core/test-harness-signature.js +4 -0
- package/dist/src/core/test-run-completeness.d.ts +57 -0
- package/dist/src/core/test-run-completeness.js +144 -0
- package/dist/src/core/test-stale-check.d.ts +27 -1
- package/dist/src/core/test-stale-check.js +39 -49
- package/dist/src/core/test-stale-exempt.d.ts +40 -0
- package/dist/src/core/test-stale-exempt.js +70 -0
- package/dist/src/core/token-lint.d.ts +50 -0
- package/dist/src/core/token-lint.js +126 -0
- package/dist/src/core/tree-guard.js +3 -0
- package/dist/src/core/typecheck-shim.d.ts +1 -1
- package/dist/src/core/typecheck-shim.js +90 -2
- package/dist/src/index.d.ts +8 -3
- package/dist/src/index.js +3 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +148 -21
- package/dist/src/types/commands/patches.d.ts +75 -1
- package/dist/src/types/config.d.ts +192 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +43 -1
- package/dist/src/types/furnace.js +7 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +34 -6
- package/dist/src/utils/options.js +86 -5
- package/dist/src/utils/path-glob.d.ts +15 -0
- package/dist/src/utils/path-glob.js +47 -0
- package/dist/src/utils/regex.d.ts +15 -3
- package/dist/src/utils/regex.js +37 -16
- package/docs/configuration.md +282 -9
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +97 -3
- package/docs/lifecycle-invariants.md +52 -19
- package/docs/machine-output.md +74 -12
- package/docs/patch-workflow.md +297 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +276 -20
- package/package.json +2 -2
package/docs/testing.md
CHANGED
|
@@ -19,6 +19,134 @@ FireForge announces this with a notice, since isolated instances do not
|
|
|
19
19
|
exercise cross-argument state. `--no-shard` restores one combined
|
|
20
20
|
invocation.
|
|
21
21
|
|
|
22
|
+
## Several runs under one lock hold
|
|
23
|
+
|
|
24
|
+
Every `fireforge test` holds the engine-session lock for its whole run. Three
|
|
25
|
+
request shapes run more than one mach invocation inside that one hold, so a
|
|
26
|
+
peer cannot take the lock, build, or replace the packaging record between
|
|
27
|
+
them:
|
|
28
|
+
|
|
29
|
+
- **Mixed harnesses.** xpcshell and browser/mochitest paths in one request
|
|
30
|
+
run as two consecutive mach invocations, the xpcshell half first. With
|
|
31
|
+
`--build`, one pre-test build packages both halves (its coverage claim is
|
|
32
|
+
the union), and the second half runs build-less against it. Before 0.50.0
|
|
33
|
+
a mixed request was refused, and the documented split lost its coverage
|
|
34
|
+
claim to peers' scoped builds between the steps.
|
|
35
|
+
- **`--repeat <n>`** runs the same selection n times. A `--build` builds
|
|
36
|
+
once, and `--doctor` probes once. Every run is reported, so a flaky suite's
|
|
37
|
+
rate is visible from one invocation.
|
|
38
|
+
- **`--negative-control <diff>`**, below.
|
|
39
|
+
|
|
40
|
+
Each sub-run prints the verdict it would have printed alone as a
|
|
41
|
+
`FIREFORGE-RUN:` line (its own status, reason and counts, plus
|
|
42
|
+
`run=<i>/<n>` and, for a mixed request, `harness=xpcshell|mochitest`). The
|
|
43
|
+
invocation still ends with exactly one `FIREFORGE-VERDICT:` line:
|
|
44
|
+
`PASS runs=<n>/<n>`, or `FAIL reason=<most structural failing run>
|
|
45
|
+
[note=…] runs=<passed>/<planned>`. Runs continue after a red or a crash; a
|
|
46
|
+
preflight refusal or an inconclusive run stops the invocation, since the
|
|
47
|
+
runs after it would not be comparable. `--mach-arg` and every other option
|
|
48
|
+
apply to each sub-run. `--repeat` and `--negative-control` need explicit
|
|
49
|
+
paths and cannot be combined with `--build-only`, `--canary` or `--auto`.
|
|
50
|
+
|
|
51
|
+
## Negative controls
|
|
52
|
+
|
|
53
|
+
A negative control proves a test can fail: neuter the code under test, run
|
|
54
|
+
the test, and expect red. Done by hand on a shared engine it is dangerous.
|
|
55
|
+
The objdir's chrome and widget files are symlinks into `engine/`, so the
|
|
56
|
+
browser reads the sources when it loads them, after the build step. A
|
|
57
|
+
mutation is therefore live for every build and suite that touches the file
|
|
58
|
+
while it is in place: a peer's `test --build` can build and test the
|
|
59
|
+
neuter, a `--build` run re-deploys `components/` over an engine-side
|
|
60
|
+
control, and a neuter restored at `Build complete` (or after the first
|
|
61
|
+
`TEST_START`) is already gone for the later shards of the same run.
|
|
62
|
+
|
|
63
|
+
`fireforge test --negative-control <diff> <paths…>` makes the control part
|
|
64
|
+
of the run:
|
|
65
|
+
|
|
66
|
+
1. The diff is read (resolved against the project root), parsed, and every
|
|
67
|
+
hunk is checked against the current file before anything else, so a
|
|
68
|
+
stale control is refused (`note=negative-control`) before the build. A
|
|
69
|
+
`components/` target is checked after the build instead, because the
|
|
70
|
+
build redeploys it.
|
|
71
|
+
2. With `--build`, the pre-test build (including the Furnace deploy)
|
|
72
|
+
runs first and packages the clean sources.
|
|
73
|
+
3. After every gate has passed and right before the harness spawns, the
|
|
74
|
+
control is applied. It stays in place until the run, every shard of it,
|
|
75
|
+
has finished.
|
|
76
|
+
4. The files are restored byte-exact. Then the next repetition (if any)
|
|
77
|
+
re-applies it, and only after the last restore is the lock released.
|
|
78
|
+
|
|
79
|
+
The diff is `git diff` output (a `diff --git` header per file). Paths may be
|
|
80
|
+
project-relative (`engine/…`, `components/…`) or engine-relative, so both
|
|
81
|
+
`git diff` at the project root and `git -C engine diff` work. A
|
|
82
|
+
`components/custom/<name>/<file>.mjs|.css` or
|
|
83
|
+
`components/overrides/<name>/<file>` path is applied to the engine copy
|
|
84
|
+
Furnace deployed it to, since that is what the run reads; the component
|
|
85
|
+
source itself is never touched. Only modifications of existing text files
|
|
86
|
+
are accepted: a created, deleted, renamed or binary file, or a symlinked
|
|
87
|
+
target, is refused. Hunks must match exactly; the only tolerance is a line
|
|
88
|
+
offset, as in `git apply`, never fuzz.
|
|
89
|
+
|
|
90
|
+
The verdict says how the control came out with `control=`:
|
|
91
|
+
|
|
92
|
+
- `caught`: every repetition went red with `reason=test-failures`, which is
|
|
93
|
+
what a control is for. The invocation exits 0.
|
|
94
|
+
- `missed`: a repetition stayed green with the mutation in place, so the
|
|
95
|
+
selected tests do not detect it. Exit 5, like a red suite.
|
|
96
|
+
- `inconclusive`: a run crashed, found no tests, was refused, or did not
|
|
97
|
+
run. The exit code is that failure's.
|
|
98
|
+
|
|
99
|
+
The status word keeps describing what the harness saw, so a caught control
|
|
100
|
+
reads `FIREFORGE-VERDICT: FAIL reason=test-failures … control=caught` and
|
|
101
|
+
exits 0. Key a control's success on `control=caught`, not on `PASS`.
|
|
102
|
+
|
|
103
|
+
A one-run control keeps its own counts on the verdict line; a repeated or
|
|
104
|
+
mixed one aggregates them as above. The mutation targets what the objdir
|
|
105
|
+
symlinks. A file the build preprocesses or copies (rather than links) is
|
|
106
|
+
read from the objdir, not from `engine/`, so a control on it stays green
|
|
107
|
+
and reports `missed`: that result is the signal to target the file the
|
|
108
|
+
browser actually loads.
|
|
109
|
+
|
|
110
|
+
### The restore safety model
|
|
111
|
+
|
|
112
|
+
- **Only under the lock.** Apply, run and restore all happen inside the
|
|
113
|
+
engine-session lock hold of the `fireforge test` invocation, and the
|
|
114
|
+
control is applied after the pre-test build. No peer build or test
|
|
115
|
+
observes it, and the build cannot overwrite it or trip `stale-build`
|
|
116
|
+
over it.
|
|
117
|
+
- **Journal first.** Before the first mutated byte is written, the
|
|
118
|
+
original bytes of every target go to `.fireforge/negative-control/`
|
|
119
|
+
with a journal of each file's original and mutated SHA-256, mode and
|
|
120
|
+
timestamps. Every write (originals, journal, mutation, restore) is an
|
|
121
|
+
atomic temp-file-and-rename. A failure while writing the mutation puts
|
|
122
|
+
back whatever was written before the run can start.
|
|
123
|
+
- **Byte-exact restore, verified.** Restore writes the original bytes back,
|
|
124
|
+
re-applies the original mode and timestamps (so make-based tooling sees
|
|
125
|
+
no change either), and reads the file back to prove the bytes match. The
|
|
126
|
+
stale-build gate hashes content, so a repeated control's next run is not
|
|
127
|
+
refused.
|
|
128
|
+
- **Never clobber.** A file is only restored while it still holds exactly
|
|
129
|
+
the bytes the control wrote. A file someone edited while the control ran
|
|
130
|
+
(an agent working outside the lock, say) keeps that edit. Its original
|
|
131
|
+
stays in the journal directory, and the run ends
|
|
132
|
+
`FAIL reason=inconclusive note=negative-control-restore` with the paths
|
|
133
|
+
named. Reconcile by hand, then delete the directory.
|
|
134
|
+
- **Every exit path.** Pass, red, crash and a refusal after the apply all
|
|
135
|
+
restore in the run's own control flow. SIGINT and SIGTERM restore in the
|
|
136
|
+
signal pipeline after the harness has shut down and before the held
|
|
137
|
+
locks are released. A restore already in flight is awaited, not
|
|
138
|
+
repeated.
|
|
139
|
+
- **Even after SIGKILL.** A SIGKILLed FireForge cannot restore, but the
|
|
140
|
+
journal survives it. Every later `fireforge test` checks for it first,
|
|
141
|
+
under the lock, before any gate or build: a file still holding the
|
|
142
|
+
control's bytes is restored, with a notice; any other state refuses with
|
|
143
|
+
`note=negative-control-pending` rather than guess.
|
|
144
|
+
|
|
145
|
+
The shorthand `--mutate <file> <old> <new>` that was proposed alongside this
|
|
146
|
+
was not added. Commander options take one value, so a three-value option
|
|
147
|
+
would have to swallow the positional test paths. A one-hunk diff expresses
|
|
148
|
+
the same edit and can be reviewed before it runs.
|
|
149
|
+
|
|
22
150
|
## Pathless runs must choose a mode
|
|
23
151
|
|
|
24
152
|
- `--auto` forwards mach's own auto-selection.
|
|
@@ -32,22 +160,81 @@ invocation.
|
|
|
32
160
|
When packageable engine files changed since the last successful FireForge
|
|
33
161
|
build, `test` fails before launching stale artifacts. Use `--build` to
|
|
34
162
|
refresh, or `--allow-stale-build` only for intentional out-of-band rebuilds.
|
|
163
|
+
The refusal prints the one-line repackaging command for the requested paths
|
|
164
|
+
(`fireforge test --build-only <paths>`), so a build-less sitting can
|
|
165
|
+
repackage without dispatching anything.
|
|
166
|
+
|
|
167
|
+
Two kinds of edit do not count as stale, because the packaged runtime
|
|
168
|
+
already serves them. FireForge reads the objdir's install manifests
|
|
169
|
+
(`obj-*/_build_manifests/install/*`, `obj-*/faster/install_*`) to decide:
|
|
170
|
+
|
|
171
|
+
- a file whose every objdir copy is a symlink resolving to the edited source
|
|
172
|
+
(the usual dev-build shape on macOS and Linux for chrome scripts and test
|
|
173
|
+
files);
|
|
174
|
+
- a test file the build does not package: one installed only by `mach test`
|
|
175
|
+
itself at dispatch (`_test_files`), or a test-tree file no manifest installs.
|
|
176
|
+
|
|
177
|
+
A copy, a preprocessed file, a symlink that does not resolve to the source,
|
|
178
|
+
or an unreadable objdir keeps the edit stale. Exempted edits are named on
|
|
179
|
+
the run (and in the refusal, when other edits are stale). On a
|
|
180
|
+
`--perf-samples` run the refusal also says which stale files are staging
|
|
181
|
+
inputs of the sampled test and which lie elsewhere, so a sample whose fixture
|
|
182
|
+
is unaffected can proceed knowingly under `--allow-stale-build`.
|
|
183
|
+
|
|
184
|
+
### Packaging coverage
|
|
35
185
|
|
|
36
186
|
`--build-only` packages mixed-harness paths once, and then each harness half
|
|
37
|
-
can run without `--build`.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
187
|
+
can run without `--build`. A plain mixed `test --build` now does both in one
|
|
188
|
+
invocation (see [Several runs under one lock hold](#several-runs-under-one-lock-hold)). Coverage is kept per staged path. Each path of a
|
|
189
|
+
scoped build records its own staging inputs: its manifest directory (the
|
|
190
|
+
nearest directory at or above it with a test manifest) plus whatever a
|
|
191
|
+
manifest there names outside it (`support-files`, `head`, `!/` shared
|
|
192
|
+
fixtures), with their content at that build. A later scoped build keeps every
|
|
193
|
+
earlier path whose own inputs and `engine/mozconfig` are unchanged, whatever
|
|
194
|
+
moved elsewhere in the engine, including a peer's edits and an engine HEAD
|
|
195
|
+
move that touches none of them. A path whose inputs changed is dropped and
|
|
196
|
+
named, with the inputs that changed. Changed inputs this build restages are
|
|
197
|
+
allowed.
|
|
198
|
+
|
|
199
|
+
A scoped build after a full build keeps the claim full while nothing outside
|
|
200
|
+
its scope moved. Otherwise it carries the full build's anchor forward, and a
|
|
201
|
+
later build-less run over any path stays covered while that path's own
|
|
202
|
+
staging inputs are unchanged since the full build. A refusal names the inputs
|
|
203
|
+
that did change.
|
|
204
|
+
|
|
205
|
+
`--extend-coverage` remains accepted. Retention is now the default, so the
|
|
206
|
+
flag only turns a drop into a refusal before the build. Before 0.50.0 a
|
|
207
|
+
scoped build without the flag replaced the claim whenever anything outside
|
|
208
|
+
its scope had changed, and the flag refused unless engine HEAD, the
|
|
209
|
+
mozconfig and every staging input recorded by the previous build were
|
|
210
|
+
unchanged. Baselines without complete staging-input fingerprints (older than
|
|
211
|
+
0.49.0) cannot prove anything unchanged and are dropped once.
|
|
212
|
+
|
|
213
|
+
### Furnace components in a pre-test build
|
|
214
|
+
|
|
215
|
+
`test --build` and `--build-only` run `furnace apply` first, like
|
|
216
|
+
`fireforge build`, and that apply deploys every component whose
|
|
217
|
+
`components/` source changed since its last deploy, another session's
|
|
218
|
+
undeployed edits included. The run names those components in a notice and
|
|
219
|
+
on the verdict line (`furnace-applied=<names>`). `--no-furnace-apply`
|
|
220
|
+
packages `engine/` as it stands, for example for a before-capture, names the
|
|
221
|
+
components with undeployed edits it left out, and stamps
|
|
222
|
+
`furnace-apply=skipped`.
|
|
47
223
|
|
|
48
224
|
When `patchLint.checkJs` and `patchLint.checkJsTestFiles` are enabled, named
|
|
49
225
|
pre-test builds check the selected test scripts before deployment or mach.
|
|
50
|
-
This includes new scripts not yet owned by an exported patch.
|
|
226
|
+
This includes new scripts not yet owned by an exported patch. The check runs
|
|
227
|
+
before the engine lock is requested, so a type error refuses at once instead
|
|
228
|
+
of after a place in the lock queue. An unowned `head*.js` in a named test's
|
|
229
|
+
directory joins the check when that test loads it with `loadSubScript` or a
|
|
230
|
+
manifest beside it lists it in `support-files`, so a suite moved onto a new
|
|
231
|
+
support head can be proven before the head is exported. A notice names each
|
|
232
|
+
such head and the `re-export --scan --scan-file` command that adopts it.
|
|
233
|
+
|
|
234
|
+
`--restart-between-tests` forwards mochitest's flag of the same name, which
|
|
235
|
+
restarts the browser between test files (the run shape a manifest's
|
|
236
|
+
`standalone` key asks for). It is refused for an xpcshell or generic
|
|
237
|
+
dispatch, like `--shuffle`.
|
|
51
238
|
|
|
52
239
|
### Shared browsers, ports and host state
|
|
53
240
|
|
|
@@ -61,8 +248,39 @@ launchd-parented app remains unattributed and is not automatically killed.
|
|
|
61
248
|
`test --wait-port [seconds]` waits for mochitest and Marionette listeners.
|
|
62
249
|
`build --wait-browser [seconds]` queues a full or UI build behind the browser.
|
|
63
250
|
Bare flags wait 60 seconds; explicit values accept 1–3600 seconds. They are
|
|
64
|
-
independent of the FireForge lock budget
|
|
65
|
-
|
|
251
|
+
independent of the FireForge lock budget, and they are spent BEFORE the
|
|
252
|
+
engine session lock is requested, so a run waiting out a browser or a port
|
|
253
|
+
does not hold every peer's build, test and re-export behind it. The run then
|
|
254
|
+
joins the lock queue and re-checks once under the lock; the normal preflight
|
|
255
|
+
refusal and its remedy apply if the resource is busy again (or still busy)
|
|
256
|
+
there. With `--kill-stale-marionette` a reapable stale browser counts as
|
|
257
|
+
clear before the lock, and the port waits stay under the lock, where the
|
|
258
|
+
stale listener can be reaped.
|
|
259
|
+
|
|
260
|
+
A path-shaped argument right after `--wait-lock`, `--wait-browser`,
|
|
261
|
+
`--wait-port` or `--shuffle` (it has a `/`, a file extension, or is `.`) is
|
|
262
|
+
a test path, not the flag's value, and the flag takes its default:
|
|
263
|
+
`fireforge test --wait-lock browser_x.js` waits 60 seconds and runs
|
|
264
|
+
`browser_x.js`. A bare word (`--wait-lock soon`) is still a usage error.
|
|
265
|
+
|
|
266
|
+
`--wait-port` makes sibling checkouts take turns. `--auto-ports` (or
|
|
267
|
+
`test.mochitestPorts: "auto"` in `fireforge.json`) lets them run browser
|
|
268
|
+
suites at the same time. Desktop `mach mochitest` has no `--http-port` or
|
|
269
|
+
`--ssl-port` option; those exist only for Android and iOS. Recent engines
|
|
270
|
+
do something better instead: `testing/mochitest/runtests.py` bind-probes
|
|
271
|
+
the HTTP server, ssltunnel and WebSocket ports before starting its servers,
|
|
272
|
+
and the Marionette port before launching the browser, moves each busy one to
|
|
273
|
+
a free port, and routes `mochi.test:8888` to wherever the server landed.
|
|
274
|
+
FireForge's own refusal used to fire before that fallback could. In auto
|
|
275
|
+
mode the mochitest-server and Marionette gates step aside, with a notice
|
|
276
|
+
naming the holder, when the holder is not this checkout's own (a sibling
|
|
277
|
+
checkout's live suite or an unrelated listener). This checkout's own
|
|
278
|
+
leftovers are refused exactly as before, and `--kill-stale-marionette`
|
|
279
|
+
still applies to them. Auto mode takes effect only when the engine's
|
|
280
|
+
`runtests.py` carries the fallback; otherwise a notice says so and the
|
|
281
|
+
default refusal stays. It never applies to `--doctor`'s Marionette probe,
|
|
282
|
+
which launches its own browser on that port. The default (`"fixed"`) is
|
|
283
|
+
unchanged.
|
|
66
284
|
|
|
67
285
|
Every suite samples host load and the highest CPU process before and after
|
|
68
286
|
dispatch. Load at least 4 or a process at least 90% CPU produces a warning;
|
|
@@ -215,9 +433,20 @@ group sweep.
|
|
|
215
433
|
Every test run ends with one machine-readable line:
|
|
216
434
|
|
|
217
435
|
```
|
|
218
|
-
FIREFORGE-VERDICT: PASS|FAIL reason=… [note=<class>] [shuffle=<seed>] [orphans-reaped=<n>] [log=<path>]
|
|
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>]
|
|
219
437
|
```
|
|
220
438
|
|
|
439
|
+
A run is never `PASS` when its summary reports unexpected results, when the
|
|
440
|
+
harness printed "Application shut down (without crashing) in the middle of a
|
|
441
|
+
test", or when a requested test file never produced a start (or skip)
|
|
442
|
+
marker, even if mach exited 0. A browser that quits cleanly mid-suite does
|
|
443
|
+
exactly that: the counts then cover only the files that ran. Such a run is
|
|
444
|
+
`FAIL reason=test-failures`, and a short start count adds
|
|
445
|
+
`started=<n>/<m> first-unstarted=<path>`: how many requested files started,
|
|
446
|
+
and the first, in dispatch order, that never did. The file count is only
|
|
447
|
+
taken when the output's start lines name the requested files; an xpcshell
|
|
448
|
+
dispatch that proves execution with a result summary alone is not counted.
|
|
449
|
+
|
|
221
450
|
Automation should branch on this line rather than on the raw process code,
|
|
222
451
|
and has to treat a missing verdict as a failure. The closed set of `reason=`
|
|
223
452
|
values and the stdout rules around the line are in
|
|
@@ -240,9 +469,9 @@ disables this argument permutation. FireForge also forwards native mach
|
|
|
240
469
|
`--shuffle` within each invocation, whose file order remains unseeded and is
|
|
241
470
|
not replayed by the FireForge seed. `FIREFORGE_SHUFFLE_SEED=<seed>` is available
|
|
242
471
|
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.
|
|
244
|
-
`--shuffle
|
|
245
|
-
|
|
472
|
+
is recorded on the verdict. The option is mochitest-only. A path-shaped
|
|
473
|
+
argument right after a bare `--shuffle` is a test path, not a seed (see
|
|
474
|
+
"Shared browsers, ports and host state" above).
|
|
246
475
|
|
|
247
476
|
Exit code 14 (`INCONCLUSIVE`) is not red: it means `engine/` moved while the
|
|
248
477
|
harness ran and the result was thrown away. Exit 15 (`LOCK_TIMEOUT`) means
|
|
@@ -299,14 +528,41 @@ The two phases handle it differently, on purpose:
|
|
|
299
528
|
|
|
300
529
|
A test run holds the engine-session lock and snapshots the engine git
|
|
301
530
|
generation before and after the harness run, failing the verdict as invalid
|
|
302
|
-
if the tree changed mid-run.
|
|
531
|
+
if the tree changed mid-run. The checks that need no lock run before it is
|
|
532
|
+
requested: the launchable binary, the named-file checkJs pass, and the
|
|
533
|
+
`--wait-browser`/`--wait-port` budgets. The run log is open from the start,
|
|
534
|
+
so a `reason=lock-timeout` line carries `log=` too.
|
|
535
|
+
A `--perf-samples` run fails only when HEAD
|
|
536
|
+
moved or a changed path is packaged by the running build (an install-manifest
|
|
537
|
+
source or a test file); an edit no manifest installs, such as a compiled
|
|
538
|
+
source, leaves the sample standing with a warning. To verify beside a busy primary checkout
|
|
303
539
|
instead, use a [verification tree](verification-trees.md).
|
|
304
540
|
|
|
305
541
|
## Dev-build gotcha
|
|
306
542
|
|
|
307
543
|
In dev builds, files under `obj-*/dist/bin` may be symlinks back into the
|
|
308
|
-
source tree (prefs
|
|
309
|
-
backup before bisection experiments.
|
|
544
|
+
source tree (prefs, chrome JS and CSS, deployed widgets), so edit source
|
|
545
|
+
prefs directly and keep a backup before bisection experiments. The same
|
|
546
|
+
symlinks mean a running suite reads `engine/` when its browser loads a file,
|
|
547
|
+
after any `--build` step: `Build complete` is not a snapshot. An edit to
|
|
548
|
+
`engine/`, yours or a peer session's, made before the `FIREFORGE-VERDICT`
|
|
549
|
+
line can reach the running suite, so keep a temporary edit, such as a
|
|
550
|
+
hand-made neuter, in place until the verdict line, or use
|
|
551
|
+
`--negative-control` for deliberate mutations. `fireforge test --help` says
|
|
552
|
+
so too.
|
|
553
|
+
|
|
554
|
+
## Missing launchable binary
|
|
555
|
+
|
|
556
|
+
`test` checks for the launchable binary before it requests the engine lock,
|
|
557
|
+
and names the cause when the bundle is incomplete. Every protected mach
|
|
558
|
+
build (`build`, `build --ui`, `test --build`) records itself in
|
|
559
|
+
`.fireforge/build-run.json` while it runs. A successful build removes the
|
|
560
|
+
record, a failed one keeps it with its exit code, and a build whose process
|
|
561
|
+
died part-way leaves it marked running with a PID that no longer exists. The
|
|
562
|
+
refusal (`note=no-launchable-binary`) then says, in any session, that the
|
|
563
|
+
last build was interrupted or failed, by which command and when. A missing
|
|
564
|
+
binary while a build is still running is not refused early: the run queues
|
|
565
|
+
behind that build, which relinks the bundle before it releases the lock.
|
|
310
566
|
|
|
311
567
|
## Repository release gate
|
|
312
568
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hominis/fireforge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"description": "FireForge — a build tool for customizing Firefox",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"dpdm": "4.3.0",
|
|
73
73
|
"eslint": "^10.0.0",
|
|
74
74
|
"eslint-config-prettier": "^10.1.8",
|
|
75
|
-
"eslint-plugin-jsdoc": "^
|
|
75
|
+
"eslint-plugin-jsdoc": "^65.0.1",
|
|
76
76
|
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
77
77
|
"fast-check": "^4.6.0",
|
|
78
78
|
"husky": "^9.1.7",
|