@hominis/fireforge 0.34.2 → 0.36.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 +48 -0
- package/README.md +43 -5
- package/dist/bin/fireforge.d.ts +4 -0
- package/dist/bin/fireforge.js +25 -6
- package/dist/src/cli.js +22 -5
- package/dist/src/commands/bootstrap-checks.js +0 -1
- package/dist/src/commands/bootstrap.d.ts +2 -1
- package/dist/src/commands/bootstrap.js +16 -7
- package/dist/src/commands/build.js +17 -3
- package/dist/src/commands/config.js +30 -10
- package/dist/src/commands/discard.js +24 -5
- package/dist/src/commands/doctor/post-rebase-audit.js +0 -1
- package/dist/src/commands/doctor-check-core.js +0 -1
- package/dist/src/commands/doctor-external-toolchains.d.ts +3 -0
- package/dist/src/commands/doctor-external-toolchains.js +54 -0
- package/dist/src/commands/doctor-furnace-jar.js +0 -1
- package/dist/src/commands/doctor-furnace-manifest-sync.js +0 -1
- package/dist/src/commands/doctor-furnace.js +2 -2
- package/dist/src/commands/doctor-working-tree.js +0 -1
- package/dist/src/commands/doctor.js +4 -1
- package/dist/src/commands/download.js +51 -15
- package/dist/src/commands/export-all.js +5 -3
- package/dist/src/commands/export-flow.js +12 -7
- package/dist/src/commands/export-placement-gate.js +0 -1
- package/dist/src/commands/export-placement-policy.js +0 -1
- package/dist/src/commands/export-shared.d.ts +5 -1
- package/dist/src/commands/export-shared.js +18 -6
- package/dist/src/commands/export.js +15 -10
- package/dist/src/commands/furnace/apply.js +22 -6
- package/dist/src/commands/furnace/chrome-doc-remove.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-templates.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-tests.js +0 -1
- package/dist/src/commands/furnace/chrome-doc.js +0 -1
- package/dist/src/commands/furnace/create-browser-test.js +0 -1
- package/dist/src/commands/furnace/create-dry-run.js +0 -1
- package/dist/src/commands/furnace/create-features.js +0 -1
- package/dist/src/commands/furnace/create-mochikit.js +0 -1
- package/dist/src/commands/furnace/create-readback.js +0 -1
- package/dist/src/commands/furnace/create-templates.js +0 -1
- package/dist/src/commands/furnace/create-validation.js +0 -1
- package/dist/src/commands/furnace/create-xpcshell.js +0 -1
- package/dist/src/commands/furnace/create.js +0 -1
- package/dist/src/commands/furnace/deploy.js +7 -83
- package/dist/src/commands/furnace/diff.js +0 -1
- package/dist/src/commands/furnace/index.js +59 -25
- package/dist/src/commands/furnace/init.js +0 -1
- package/dist/src/commands/furnace/list.js +0 -1
- package/dist/src/commands/furnace/override.js +0 -1
- package/dist/src/commands/furnace/preview.js +3 -3
- package/dist/src/commands/furnace/refresh.js +0 -1
- package/dist/src/commands/furnace/remove-state.d.ts +15 -0
- package/dist/src/commands/furnace/remove-state.js +47 -1
- package/dist/src/commands/furnace/remove.js +3 -9
- package/dist/src/commands/furnace/rename-browser-test.js +1 -5
- package/dist/src/commands/furnace/rename-helpers.d.ts +6 -0
- package/dist/src/commands/furnace/rename-helpers.js +30 -1
- package/dist/src/commands/furnace/rename-xpcshell.js +7 -6
- package/dist/src/commands/furnace/rename.js +15 -36
- package/dist/src/commands/furnace/scan.js +0 -1
- package/dist/src/commands/furnace/status.js +0 -1
- package/dist/src/commands/furnace/sync.js +76 -4
- package/dist/src/commands/furnace/validate.js +0 -1
- package/dist/src/commands/furnace/validation-output.js +0 -1
- package/dist/src/commands/import.js +35 -9
- package/dist/src/commands/lint-per-patch.js +19 -7
- package/dist/src/commands/lint.js +13 -3
- package/dist/src/commands/manifest.js +1 -2
- package/dist/src/commands/package.js +2 -1
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +1 -1
- package/dist/src/commands/patch/index.js +1 -1
- package/dist/src/commands/patch/lint-ignore.js +21 -6
- package/dist/src/commands/patch/move-files.js +1 -1
- package/dist/src/commands/patch/patch-context.js +0 -1
- package/dist/src/commands/patch/rename.js +4 -4
- package/dist/src/commands/patch/reorder.js +3 -4
- package/dist/src/commands/patch/split-plan.js +2 -1
- package/dist/src/commands/patch/split.js +4 -4
- package/dist/src/commands/patch/staged-dependency.js +1 -1
- package/dist/src/commands/patch/tier.js +18 -5
- package/dist/src/commands/re-export-bulk-scan.js +0 -1
- package/dist/src/commands/re-export-files.js +1 -1
- package/dist/src/commands/re-export-options.js +0 -1
- package/dist/src/commands/re-export-scan.js +0 -1
- package/dist/src/commands/re-export.js +6 -4
- package/dist/src/commands/rebase/abort.js +2 -9
- package/dist/src/commands/rebase/confirm.js +0 -1
- package/dist/src/commands/rebase/conflict-summary.js +0 -1
- package/dist/src/commands/rebase/continue.js +0 -1
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +10 -15
- package/dist/src/commands/rebase/patch-loop.js +38 -7
- package/dist/src/commands/rebase/summary.js +2 -3
- package/dist/src/commands/rebase.js +0 -1
- package/dist/src/commands/register.js +1 -1
- package/dist/src/commands/reset.js +16 -9
- package/dist/src/commands/resolve.js +2 -2
- package/dist/src/commands/run.js +18 -6
- package/dist/src/commands/setup-support.js +0 -1
- package/dist/src/commands/setup.js +1 -2
- package/dist/src/commands/source.js +1 -2
- package/dist/src/commands/status-output.js +1 -12
- package/dist/src/commands/status.js +147 -133
- package/dist/src/commands/test-appdir.js +0 -1
- package/dist/src/commands/test-diagnose.js +18 -2
- package/dist/src/commands/test-modes.d.ts +15 -0
- package/dist/src/commands/test-modes.js +61 -0
- package/dist/src/commands/test-register.d.ts +4 -0
- package/dist/src/commands/test-register.js +64 -0
- package/dist/src/commands/test-run.d.ts +23 -7
- package/dist/src/commands/test-run.js +15 -14
- package/dist/src/commands/test.d.ts +0 -4
- package/dist/src/commands/test.js +95 -56
- package/dist/src/commands/token-coverage.js +0 -1
- package/dist/src/commands/token.js +1 -2
- package/dist/src/commands/typecheck.js +1 -1
- package/dist/src/commands/verify.js +3 -9
- package/dist/src/commands/watch.js +5 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/ast-utils.js +0 -1
- package/dist/src/core/brand-validation.js +0 -1
- package/dist/src/core/branding.js +0 -1
- package/dist/src/core/browser-wire.js +0 -1
- package/dist/src/core/build-audit-platform.js +0 -1
- package/dist/src/core/build-audit-registration.js +0 -1
- package/dist/src/core/build-audit-resolve.js +0 -1
- package/dist/src/core/build-audit-transforms.js +0 -1
- package/dist/src/core/build-audit.js +0 -1
- package/dist/src/core/build-baseline-types.js +0 -1
- package/dist/src/core/build-baseline.js +0 -1
- package/dist/src/core/build-prepare.js +21 -7
- package/dist/src/core/config-mutate.js +0 -1
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +6 -1
- package/dist/src/core/config-state.js +0 -1
- package/dist/src/core/config-validate-patch-policy.js +0 -1
- package/dist/src/core/config-validate-test-toolchains.d.ts +8 -0
- package/dist/src/core/config-validate-test-toolchains.js +105 -0
- package/dist/src/core/config-validate.js +3 -1
- package/dist/src/core/config.js +0 -1
- package/dist/src/core/destructive.js +0 -1
- package/dist/src/core/diff-hunks.js +13 -7
- package/dist/src/core/engine-changes.js +0 -1
- package/dist/src/core/engine-session-lock.d.ts +12 -0
- package/dist/src/core/engine-session-lock.js +45 -0
- package/dist/src/core/file-lock.d.ts +8 -0
- package/dist/src/core/file-lock.js +157 -48
- package/dist/src/core/firefox-archive.d.ts +4 -0
- package/dist/src/core/firefox-archive.js +6 -1
- package/dist/src/core/firefox-cache.js +67 -8
- package/dist/src/core/firefox-download.js +0 -1
- package/dist/src/core/firefox-extract.d.ts +21 -1
- package/dist/src/core/firefox-extract.js +178 -9
- package/dist/src/core/firefox-ignorefile.js +0 -1
- package/dist/src/core/firefox.d.ts +12 -0
- package/dist/src/core/firefox.js +64 -2
- package/dist/src/core/furnace-apply-dry-run.js +0 -1
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -3
- package/dist/src/core/furnace-apply-ftl.js +10 -5
- package/dist/src/core/furnace-apply-helpers.js +0 -1
- package/dist/src/core/furnace-apply-output.js +2 -2
- package/dist/src/core/furnace-apply.d.ts +7 -1
- package/dist/src/core/furnace-apply.js +47 -13
- package/dist/src/core/furnace-checksum-utils.js +0 -1
- package/dist/src/core/furnace-config-array-utils.js +0 -1
- package/dist/src/core/furnace-config-custom.js +0 -1
- package/dist/src/core/furnace-config-order.js +0 -1
- package/dist/src/core/furnace-config-tokens.js +0 -1
- package/dist/src/core/furnace-config-validate.js +0 -1
- package/dist/src/core/furnace-config.d.ts +11 -0
- package/dist/src/core/furnace-config.js +37 -1
- package/dist/src/core/furnace-constants.js +0 -1
- package/dist/src/core/furnace-css-fragments.js +0 -1
- package/dist/src/core/furnace-graph-utils.js +0 -1
- package/dist/src/core/furnace-jsconfig.d.ts +2 -3
- package/dist/src/core/furnace-jsconfig.js +25 -18
- package/dist/src/core/furnace-marker.js +0 -1
- package/dist/src/core/furnace-operation.js +0 -1
- package/dist/src/core/furnace-refresh.js +0 -1
- package/dist/src/core/furnace-registration-ast.d.ts +14 -0
- package/dist/src/core/furnace-registration-ast.js +1 -2
- package/dist/src/core/furnace-registration-remove.js +0 -1
- package/dist/src/core/furnace-registration-validate.js +1 -5
- package/dist/src/core/furnace-registration.js +0 -1
- package/dist/src/core/furnace-rollback.js +0 -1
- package/dist/src/core/furnace-scanner.js +0 -1
- package/dist/src/core/furnace-staleness.js +0 -1
- package/dist/src/core/furnace-state-persist.d.ts +72 -0
- package/dist/src/core/furnace-state-persist.js +118 -0
- package/dist/src/core/furnace-step-errors.d.ts +23 -0
- package/dist/src/core/furnace-step-errors.js +25 -0
- package/dist/src/core/furnace-stories.js +0 -1
- package/dist/src/core/furnace-validate-accessibility.js +0 -1
- package/dist/src/core/furnace-validate-checks.js +0 -1
- package/dist/src/core/furnace-validate-compatibility.js +0 -1
- package/dist/src/core/furnace-validate-helpers.js +0 -1
- package/dist/src/core/furnace-validate-registration.js +7 -7
- package/dist/src/core/furnace-validate-structure.d.ts +8 -0
- package/dist/src/core/furnace-validate-structure.js +11 -2
- package/dist/src/core/furnace-validate.js +0 -1
- package/dist/src/core/furnace-version-drift.d.ts +6 -3
- package/dist/src/core/furnace-version-drift.js +6 -4
- package/dist/src/core/git-base.js +0 -1
- package/dist/src/core/git-diff.js +0 -1
- package/dist/src/core/git-file-ops.js +0 -1
- package/dist/src/core/git-status.d.ts +13 -0
- package/dist/src/core/git-status.js +32 -2
- package/dist/src/core/git.d.ts +10 -1
- package/dist/src/core/git.js +65 -8
- package/dist/src/core/license-headers.d.ts +16 -0
- package/dist/src/core/license-headers.js +19 -1
- package/dist/src/core/lint-cache.js +0 -1
- package/dist/src/core/lint-projection.js +0 -1
- package/dist/src/core/mach-build-artifacts.js +0 -1
- package/dist/src/core/mach-error-hints.js +27 -1
- package/dist/src/core/mach-mozconfig.js +0 -1
- package/dist/src/core/mach-python.js +0 -1
- package/dist/src/core/mach-resource-shim.js +0 -1
- package/dist/src/core/mach.js +0 -1
- package/dist/src/core/manifest-helpers.js +0 -1
- package/dist/src/core/manifest-register.js +0 -1
- package/dist/src/core/manifest-rules.js +0 -1
- package/dist/src/core/manifest-tokenizers.js +0 -1
- package/dist/src/core/marionette-port.d.ts +8 -0
- package/dist/src/core/marionette-port.js +34 -3
- package/dist/src/core/marionette-preflight.js +0 -1
- package/dist/src/core/markdown-table.js +0 -1
- package/dist/src/core/ownership-table.js +2 -9
- package/dist/src/core/parser-fallback.js +0 -1
- package/dist/src/core/patch-apply-fuzz.d.ts +27 -9
- package/dist/src/core/patch-apply-fuzz.js +71 -34
- package/dist/src/core/patch-apply.d.ts +30 -0
- package/dist/src/core/patch-apply.js +152 -39
- package/dist/src/core/patch-artifact-normalize.d.ts +18 -5
- package/dist/src/core/patch-artifact-normalize.js +19 -15
- package/dist/src/core/patch-export-coverage.js +0 -1
- package/dist/src/core/patch-export-metadata.js +0 -1
- package/dist/src/core/patch-export-update.js +2 -3
- package/dist/src/core/patch-export.d.ts +2 -6
- package/dist/src/core/patch-export.js +24 -48
- package/dist/src/core/patch-files.js +0 -1
- package/dist/src/core/patch-identifier-suggest.js +0 -1
- package/dist/src/core/patch-lint-checkjs.js +0 -1
- package/dist/src/core/patch-lint-chrome-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-cross.js +0 -1
- package/dist/src/core/patch-lint-css.js +0 -1
- package/dist/src/core/patch-lint-diff-tag.js +0 -1
- package/dist/src/core/patch-lint-diff.d.ts +2 -1
- package/dist/src/core/patch-lint-diff.js +17 -32
- package/dist/src/core/patch-lint-imports.js +0 -1
- package/dist/src/core/patch-lint-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-observer.js +0 -1
- package/dist/src/core/patch-lint-ownership.js +0 -1
- package/dist/src/core/patch-lint-reexports.js +0 -1
- package/dist/src/core/patch-lint.d.ts +37 -2
- package/dist/src/core/patch-lint.js +48 -24
- package/dist/src/core/patch-lock.js +0 -1
- package/dist/src/core/patch-manifest-consistency.js +9 -1
- package/dist/src/core/patch-manifest-io.d.ts +16 -0
- package/dist/src/core/patch-manifest-io.js +37 -12
- package/dist/src/core/patch-manifest-query.d.ts +6 -0
- package/dist/src/core/patch-manifest-query.js +27 -12
- package/dist/src/core/patch-manifest-resolve.js +0 -1
- package/dist/src/core/patch-manifest-validate.js +0 -1
- package/dist/src/core/patch-manifest.d.ts +1 -1
- package/dist/src/core/patch-manifest.js +1 -2
- package/dist/src/core/patch-parse.d.ts +59 -0
- package/dist/src/core/patch-parse.js +209 -92
- package/dist/src/core/patch-policy.js +0 -1
- package/dist/src/core/patch-registration-refs.js +16 -26
- package/dist/src/core/patch-source-metadata.js +0 -1
- package/dist/src/core/patch-transform.d.ts +4 -0
- package/dist/src/core/patch-transform.js +30 -38
- package/dist/src/core/rebase-session.js +0 -1
- package/dist/src/core/register-browser-content.js +0 -1
- package/dist/src/core/register-module.js +0 -1
- package/dist/src/core/register-result.js +0 -1
- package/dist/src/core/register-scaffold.js +0 -1
- package/dist/src/core/register-shared-css.js +0 -1
- package/dist/src/core/register-test-manifest.js +0 -1
- package/dist/src/core/register-xpcshell-test.js +0 -1
- package/dist/src/core/shared-ftl.js +0 -1
- package/dist/src/core/signal-critical.js +0 -1
- package/dist/src/core/smoke-patterns.js +0 -1
- package/dist/src/core/state-file.js +0 -1
- package/dist/src/core/status-classify.d.ts +16 -0
- package/dist/src/core/status-classify.js +24 -16
- package/dist/src/core/test-harness-crash.d.ts +64 -7
- package/dist/src/core/test-harness-crash.js +196 -15
- package/dist/src/core/test-harness-output.js +0 -1
- package/dist/src/core/test-path-scope.d.ts +62 -0
- package/dist/src/core/test-path-scope.js +148 -0
- package/dist/src/core/test-stale-check.js +0 -1
- package/dist/src/core/test-stale-symlink.js +0 -1
- package/dist/src/core/test-xpcshell-retry.js +0 -1
- package/dist/src/core/token-coverage.js +0 -1
- package/dist/src/core/token-dark-mode.js +0 -1
- package/dist/src/core/token-docs.js +0 -1
- package/dist/src/core/token-manager.js +0 -1
- package/dist/src/core/token-scaffold.js +0 -1
- package/dist/src/core/token-variant.js +0 -1
- package/dist/src/core/toolchain-preflight.d.ts +85 -0
- package/dist/src/core/toolchain-preflight.js +256 -0
- package/dist/src/core/typecheck-shim.d.ts +4 -1
- package/dist/src/core/typecheck-shim.js +61 -18
- package/dist/src/core/typecheck.js +0 -1
- package/dist/src/core/wire-destroy.js +0 -1
- package/dist/src/core/wire-dom-fragment.js +0 -1
- package/dist/src/core/wire-init.js +0 -1
- package/dist/src/core/wire-subscript.js +0 -1
- package/dist/src/core/wire-targets.js +0 -1
- package/dist/src/core/wire-utils.js +0 -1
- package/dist/src/core/xpcshell-appdir.js +1 -4
- package/dist/src/errors/base.d.ts +29 -0
- package/dist/src/errors/base.js +35 -1
- package/dist/src/errors/build.js +0 -1
- package/dist/src/errors/codes.d.ts +6 -0
- package/dist/src/errors/codes.js +6 -1
- package/dist/src/errors/config.js +0 -1
- package/dist/src/errors/download.js +2 -1
- package/dist/src/errors/furnace.d.ts +11 -1
- package/dist/src/errors/furnace.js +6 -5
- package/dist/src/errors/git.js +0 -1
- package/dist/src/errors/patch.d.ts +17 -0
- package/dist/src/errors/patch.js +29 -1
- package/dist/src/errors/rebase.js +0 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/types/cli.js +0 -1
- package/dist/src/types/commands/index.js +0 -1
- package/dist/src/types/commands/options.d.ts +20 -5
- package/dist/src/types/commands/options.js +0 -1
- package/dist/src/types/commands/patches.d.ts +8 -0
- package/dist/src/types/commands/patches.js +0 -1
- package/dist/src/types/commands/project.d.ts +11 -2
- package/dist/src/types/commands/project.js +0 -1
- package/dist/src/types/config.d.ts +32 -0
- package/dist/src/types/config.js +0 -1
- package/dist/src/types/furnace.d.ts +10 -0
- package/dist/src/types/furnace.js +0 -1
- package/dist/src/types/index.js +0 -1
- package/dist/src/types/typecheck.js +0 -1
- package/dist/src/utils/elapsed.js +0 -1
- package/dist/src/utils/errors.js +0 -1
- package/dist/src/utils/fs.js +37 -5
- package/dist/src/utils/logger.d.ts +7 -0
- package/dist/src/utils/logger.js +85 -3
- package/dist/src/utils/options.d.ts +15 -0
- package/dist/src/utils/options.js +25 -1
- package/dist/src/utils/package-root.js +11 -4
- package/dist/src/utils/parse.js +0 -1
- package/dist/src/utils/paths.js +0 -1
- package/dist/src/utils/platform.js +0 -1
- package/dist/src/utils/process.d.ts +33 -4
- package/dist/src/utils/process.js +183 -28
- package/dist/src/utils/regex.d.ts +13 -3
- package/dist/src/utils/regex.js +53 -4
- package/dist/src/utils/validation.d.ts +0 -12
- package/dist/src/utils/validation.js +13 -26
- package/package.json +8 -7
|
@@ -63,35 +63,36 @@ const SHARD_STATUS_LABEL = {
|
|
|
63
63
|
'no-tests': 'NO-TESTS',
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
|
-
* Runs each requested path as its own sequential harness
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
66
|
+
* Runs each requested path argument as its own sequential harness
|
|
67
|
+
* invocation (a directory argument's enumerated files stay together in
|
|
68
|
+
* one invocation — see {@link ShardGroup}) and prints an aggregate
|
|
69
|
+
* report. Per-shard failures are diagnosed via `diagnoseShardFailure`
|
|
70
|
+
* (which receives the throwing diagnosis chain from the command layer)
|
|
71
|
+
* but downgraded to warnings so every shard runs; a single aggregate
|
|
72
|
+
* error is thrown at the end when any shard did not pass.
|
|
71
73
|
*/
|
|
72
|
-
export async function runShardedTests(ctx,
|
|
74
|
+
export async function runShardedTests(ctx, groups, diagnoseShardFailure) {
|
|
73
75
|
const shards = [];
|
|
74
|
-
for (const [index,
|
|
75
|
-
info(`— Shard ${index + 1}/${
|
|
76
|
-
const outcome = await runTestsWithRetries(ctx,
|
|
77
|
-
shards.push({
|
|
76
|
+
for (const [index, group] of groups.entries()) {
|
|
77
|
+
info(`— Shard ${index + 1}/${groups.length}: ${group.label}`);
|
|
78
|
+
const outcome = await runTestsWithRetries(ctx, group.paths);
|
|
79
|
+
shards.push({ label: group.label, outcome });
|
|
78
80
|
if (outcome.verdict.kind === 'harness-crash' && outcome.verdict.signature) {
|
|
79
81
|
warn(buildHarnessCrashMessage(outcome.verdict.signature, outcome.attempts));
|
|
80
82
|
}
|
|
81
83
|
else if (outcome.verdict.kind !== 'tests-ran-ok') {
|
|
82
|
-
const diagnosis = diagnoseShardFailure(outcome,
|
|
84
|
+
const diagnosis = diagnoseShardFailure(outcome, group.label);
|
|
83
85
|
if (diagnosis)
|
|
84
86
|
warn(diagnosis);
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
|
-
const lines = shards.map(({
|
|
89
|
+
const lines = shards.map(({ label, outcome }) => `${SHARD_STATUS_LABEL[outcome.verdict.kind].padEnd(8)} ${label}` +
|
|
88
90
|
(outcome.attempts > 1 ? ` (${outcome.attempts} attempts)` : ''));
|
|
89
91
|
const failing = shards.filter(({ outcome }) => outcome.verdict.kind !== 'tests-ran-ok');
|
|
90
92
|
note(`${lines.join('\n')}\n\n${shards.length - failing.length}/${shards.length} shard(s) passed`, 'Sharded Test Summary');
|
|
91
93
|
if (failing.length > 0) {
|
|
92
94
|
throw new BuildError(`${failing.length} of ${shards.length} sharded test run(s) did not pass: ` +
|
|
93
|
-
`${failing.map(({
|
|
95
|
+
`${failing.map(({ label }) => label).join(', ')}. ` +
|
|
94
96
|
'See the per-shard diagnosis above. Use --no-shard to reproduce the combined single-invocation behaviour.', 'mach test');
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
|
-
//# sourceMappingURL=test-run.js.map
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import type { CommandContext } from '../types/cli.js';
|
|
3
1
|
import type { TestOptions } from '../types/commands/index.js';
|
|
4
2
|
/**
|
|
5
3
|
* Runs the test command to execute mach tests.
|
|
@@ -8,5 +6,3 @@ import type { TestOptions } from '../types/commands/index.js';
|
|
|
8
6
|
* @param options - Test options
|
|
9
7
|
*/
|
|
10
8
|
export declare function testCommand(projectRoot: string, testPaths: string[], options?: TestOptions): Promise<void>;
|
|
11
|
-
/** Registers the test command on the CLI program. */
|
|
12
|
-
export declare function registerTest(program: Command, { getProjectRoot, withErrorHandling }: CommandContext): void;
|
|
@@ -3,20 +3,22 @@ import { join, resolve } from 'node:path';
|
|
|
3
3
|
import { readBuildBaseline } from '../core/build-baseline.js';
|
|
4
4
|
import { prepareBuildEnvironment } from '../core/build-prepare.js';
|
|
5
5
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
6
|
+
import { assertEngineGenerationUnchanged, snapshotEngineGeneration, } from '../core/engine-session-lock.js';
|
|
6
7
|
import { buildArtifactMismatchMessage, hasBuildArtifacts, hasRunnableBundle, runProtectedMachBuild, withBuildLock, } from '../core/mach.js';
|
|
7
|
-
import { assertMarionettePortAvailable, extractForwardedMarionettePort, forwardedMachArgsIncludeMarionetteClient, shouldAutoForwardMarionettePortToMach, } from '../core/marionette-port.js';
|
|
8
|
+
import { assertMarionettePortAvailable, ensureMarionettePortAvailable, extractForwardedMarionettePort, forwardedMachArgsIncludeMarionetteClient, shouldAutoForwardMarionettePortToMach, } from '../core/marionette-port.js';
|
|
8
9
|
import { formatMarionettePreflightLine, reportMarionettePreflight, runMarionettePreflight, } from '../core/marionette-preflight.js';
|
|
9
10
|
import { buildHarnessCrashMessage } from '../core/test-harness-crash.js';
|
|
10
11
|
import { createPostRebuildFailureContext } from '../core/test-harness-output.js';
|
|
12
|
+
import { analyzeTestPathScopes, formatScopeNotice, } from '../core/test-path-scope.js';
|
|
11
13
|
import { checkStaleBuildForTest, formatStaleBuildWarning } from '../core/test-stale-check.js';
|
|
12
14
|
import { findNearestXpcshellManifest } from '../core/xpcshell-appdir.js';
|
|
13
15
|
import { GeneralError } from '../errors/base.js';
|
|
14
16
|
import { AmbiguousBuildArtifactsError, BuildError } from '../errors/build.js';
|
|
15
17
|
import { pathExists } from '../utils/fs.js';
|
|
16
18
|
import { info, intro, outro, spinner, success, warn } from '../utils/logger.js';
|
|
17
|
-
import { pickDefined } from '../utils/options.js';
|
|
18
19
|
import { stripEnginePrefix } from '../utils/paths.js';
|
|
19
20
|
import { diagnoseShardOutcome, finalizeSingleRunOutcome } from './test-diagnose.js';
|
|
21
|
+
import { assertPathlessTestMode, assertTestModeCombinations, canaryTimeoutSeconds, reportCanaryOutcome, resolveCanaryPath, } from './test-modes.js';
|
|
20
22
|
import { DEFAULT_HARNESS_RETRIES, runShardedTests, runTestsWithRetries, } from './test-run.js';
|
|
21
23
|
async function assertTestPathsExist(engineDir, testPaths) {
|
|
22
24
|
const missingPaths = [];
|
|
@@ -134,9 +136,12 @@ async function runPreTestBuild(projectRoot, paths, projectConfig, harnessRetries
|
|
|
134
136
|
: 'Pre-test build failed', 'mach build faster');
|
|
135
137
|
});
|
|
136
138
|
}
|
|
137
|
-
function logTestSelection(
|
|
138
|
-
if (
|
|
139
|
-
|
|
139
|
+
function logTestSelection(scopes) {
|
|
140
|
+
if (scopes.length > 0) {
|
|
141
|
+
const labels = scopes.map((scope) => scope.isDirectory && scope.testFileCount > 0
|
|
142
|
+
? `${scope.requestedPath} (${scope.testFileCount} test file${scope.testFileCount === 1 ? '' : 's'}, passed explicitly)`
|
|
143
|
+
: scope.requestedPath);
|
|
144
|
+
info(`Running tests: ${labels.join(', ')}`);
|
|
140
145
|
}
|
|
141
146
|
else {
|
|
142
147
|
info('Running all tests...');
|
|
@@ -254,6 +259,13 @@ function appendMarionetteForwardingArgs(extraArgs, options, forwardedPort) {
|
|
|
254
259
|
}
|
|
255
260
|
}
|
|
256
261
|
}
|
|
262
|
+
async function ensureTestMarionettePortAvailable(port, binaryName, killStaleBrowser) {
|
|
263
|
+
if (killStaleBrowser) {
|
|
264
|
+
await ensureMarionettePortAvailable(port, { binaryName, killStaleBrowser: true });
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
await assertMarionettePortAvailable(port, { binaryName });
|
|
268
|
+
}
|
|
257
269
|
/**
|
|
258
270
|
* Runs the test command to execute mach tests.
|
|
259
271
|
* @param projectRoot - Root directory of the project
|
|
@@ -267,11 +279,14 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
267
279
|
if (!(await pathExists(paths.engine))) {
|
|
268
280
|
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
269
281
|
}
|
|
282
|
+
assertPathlessTestMode(testPaths, options);
|
|
270
283
|
const buildCheck = await assertTestBuildArtifacts(paths.engine);
|
|
271
284
|
// Load the project config once so both the build and the port
|
|
272
285
|
// probe have access to `binaryName` (the port probe uses it to
|
|
273
286
|
// recognise a fork-branded browser holding the Marionette port).
|
|
274
287
|
const projectConfig = await loadConfig(projectRoot);
|
|
288
|
+
const canaryPath = resolveCanaryPath(options, projectConfig);
|
|
289
|
+
assertTestModeCombinations(testPaths, options, canaryPath);
|
|
275
290
|
// `hasBuildArtifacts` only confirms `obj-*/dist/` exists; a partial
|
|
276
291
|
// build (linker failed, packaging step interrupted, etc.) can satisfy
|
|
277
292
|
// that check without ever writing the launchable binary the marionette
|
|
@@ -290,15 +305,19 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
290
305
|
else {
|
|
291
306
|
// Stale-build preflight — when --build was NOT requested, detect
|
|
292
307
|
// packageable engine edits since the last successful `fireforge build`
|
|
293
|
-
// and
|
|
294
|
-
//
|
|
295
|
-
// after mach test has already launched (see motivating case in
|
|
296
|
-
// `core/test-stale-check.ts`). The check is warn-only so a fork that
|
|
297
|
-
// rebuilt out-of-band (no FireForge-recorded baseline update) is not
|
|
298
|
-
// blocked from running tests.
|
|
308
|
+
// and fail UP-FRONT unless the operator explicitly accepts the stale
|
|
309
|
+
// package risk.
|
|
299
310
|
const stale = await checkStaleBuildForTest(projectRoot, paths.engine);
|
|
300
311
|
if (stale.stale) {
|
|
301
|
-
|
|
312
|
+
const message = `${formatStaleBuildWarning(stale)}\n\n` +
|
|
313
|
+
'Run `fireforge test --build` to refresh the packaged runtime first, or pass ' +
|
|
314
|
+
'`--allow-stale-build` if you intentionally rebuilt out-of-band and accept the risk.';
|
|
315
|
+
if (options.allowStaleBuild === true) {
|
|
316
|
+
warn(message);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
throw new GeneralError(message);
|
|
320
|
+
}
|
|
302
321
|
}
|
|
303
322
|
}
|
|
304
323
|
// Resolve the effective Marionette port. Operator precedence:
|
|
@@ -323,7 +342,7 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
323
342
|
// generic bind failure. 2026-04-21 eval (Finding #20): a stale
|
|
324
343
|
// `-marionette` process from `fresh/` poisoned a later test run in
|
|
325
344
|
// the sibling `mybrowser/` workspace.
|
|
326
|
-
await
|
|
345
|
+
await ensureTestMarionettePortAvailable(effectivePort, projectConfig.binaryName, options.killStaleMarionette === true);
|
|
327
346
|
if (options.doctor) {
|
|
328
347
|
const doctorOutcome = await runDoctorPreflight({
|
|
329
348
|
engineDir: paths.engine,
|
|
@@ -336,7 +355,8 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
336
355
|
if (doctorOutcome === 'stop')
|
|
337
356
|
return;
|
|
338
357
|
}
|
|
339
|
-
const
|
|
358
|
+
const requestedPaths = canaryPath !== undefined ? [canaryPath] : testPaths;
|
|
359
|
+
const normalizedPaths = requestedPaths.map((p) => stripEnginePrefix(p).trim());
|
|
340
360
|
await assertTestPathsExist(paths.engine, normalizedPaths);
|
|
341
361
|
const classification = await classifyTestHarnesses(paths.engine, normalizedPaths);
|
|
342
362
|
if (classification.xpcshell.length > 0 && classification.nonXpcshell.length > 0) {
|
|
@@ -350,6 +370,12 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
350
370
|
if (options.headless) {
|
|
351
371
|
extraArgs.push('--headless');
|
|
352
372
|
}
|
|
373
|
+
if (options.auto === true) {
|
|
374
|
+
extraArgs.push('--auto');
|
|
375
|
+
}
|
|
376
|
+
if (canaryPath !== undefined) {
|
|
377
|
+
extraArgs.push(`--timeout=${String(canaryTimeoutSeconds(projectConfig))}`);
|
|
378
|
+
}
|
|
353
379
|
// --mach-arg is a verbatim passthrough for upstream mach/xpcshell/mochitest
|
|
354
380
|
// flags FireForge does not model directly (see the xpcshell appdir hint
|
|
355
381
|
// above for the motivating case). Appended AFTER --headless so mach sees
|
|
@@ -359,11 +385,33 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
359
385
|
extraArgs.push(...forwardedMachArgs);
|
|
360
386
|
}
|
|
361
387
|
appendMarionetteForwardingArgs(extraArgs, options, forwardedPort);
|
|
388
|
+
// Directory arguments mean EXACTLY that directory: mozbuild's test
|
|
389
|
+
// resolver matches paths by string prefix, so a bare directory arg
|
|
390
|
+
// silently swept in prefix-named siblings (152.0b7 → 153.0b8 drill:
|
|
391
|
+
// `…/test/hominis` also ran `…/test/hominis-tiles`, 1224 tests instead
|
|
392
|
+
// of ~200, with no indication the scope widened). Each directory
|
|
393
|
+
// argument dispatches as its enumerated explicit test-file list — a
|
|
394
|
+
// file list cannot prefix-match a sibling (0.35.0's trailing-`/`
|
|
395
|
+
// normalization turned out to be cosmetic on Firefox 153's mach; field
|
|
396
|
+
// verification showed the sibling still ran while the echo claimed it
|
|
397
|
+
// was excluded). Any prefix-siblings are echoed so the narrowed scope
|
|
398
|
+
// is visible. Classification above intentionally used the raw
|
|
399
|
+
// argument forms; only the mach dispatch needs the exact-match shape.
|
|
400
|
+
const scopes = await analyzeTestPathScopes(paths.engine, normalizedPaths);
|
|
401
|
+
const dispatchGroups = scopes.map((scope) => ({
|
|
402
|
+
label: scope.requestedPath,
|
|
403
|
+
paths: scope.dispatchPaths,
|
|
404
|
+
}));
|
|
405
|
+
for (const scope of scopes) {
|
|
406
|
+
const notice = formatScopeNotice(scope);
|
|
407
|
+
if (notice)
|
|
408
|
+
info(notice);
|
|
409
|
+
}
|
|
362
410
|
// xpcshell appdir auto-injection happens per harness invocation inside
|
|
363
411
|
// `runTestsWithRetries` (src/commands/test-run.ts) so sharded runs probe
|
|
364
412
|
// the manifest for each file individually. See src/core/xpcshell-appdir.ts
|
|
365
413
|
// for the full motivation.
|
|
366
|
-
logTestSelection(
|
|
414
|
+
logTestSelection(scopes);
|
|
367
415
|
const perfSampleEnv = buildPerfSampleEnv(projectRoot, projectConfig.binaryName, options.perfSamples);
|
|
368
416
|
const runCtx = {
|
|
369
417
|
engineDir: paths.engine,
|
|
@@ -377,21 +425,46 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
377
425
|
const postRebuildContext = options.build
|
|
378
426
|
? createPostRebuildFailureContext('fireforge test --build', normalizedPaths)
|
|
379
427
|
: undefined;
|
|
380
|
-
// Multi-
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
|
|
385
|
-
|
|
428
|
+
// Multi-argument requests shard into sequential harness runs by default
|
|
429
|
+
// (field report C3): one shared mochitest profile across files bleeds
|
|
430
|
+
// pref/media-query state into later files. Sharding is per path
|
|
431
|
+
// ARGUMENT — a directory argument keeps its enumerated files together
|
|
432
|
+
// in one invocation, preserving the one-browser-instance semantics of
|
|
433
|
+
// a directory run. --no-shard restores the combined invocation. The
|
|
434
|
+
// default must not be SILENT (drill finding: a two-file cross-file
|
|
435
|
+
// pollution repro "passed" because the headed comparison run was
|
|
436
|
+
// sharded without saying so, briefly misattributing a suite-context
|
|
437
|
+
// bug to an upstream headless regression), so a one-line notice states
|
|
438
|
+
// what sharding does and does not exercise.
|
|
439
|
+
if (canaryPath === undefined && dispatchGroups.length > 1 && options.shard !== false) {
|
|
440
|
+
info(`Sharding: running ${dispatchGroups.length} test path arguments in isolated browser instances ` +
|
|
441
|
+
'(one mach invocation per argument; a directory argument keeps its files in one instance). ' +
|
|
442
|
+
'Cross-argument state is NOT exercised — pass --no-shard for a combined single-instance run.');
|
|
443
|
+
const generationBefore = await snapshotEngineGeneration(paths.engine);
|
|
444
|
+
try {
|
|
445
|
+
await runShardedTests(runCtx, dispatchGroups, (outcome, label) => diagnoseShardOutcome(outcome, label, projectConfig.binaryName, postRebuildContext));
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
await assertEngineGenerationUnchanged(paths.engine, generationBefore);
|
|
449
|
+
}
|
|
386
450
|
return;
|
|
387
451
|
}
|
|
452
|
+
const combinedDispatchPaths = dispatchGroups.flatMap((group) => group.paths);
|
|
388
453
|
let outcome;
|
|
454
|
+
const generationBefore = await snapshotEngineGeneration(paths.engine);
|
|
389
455
|
try {
|
|
390
|
-
outcome = await runTestsWithRetries(runCtx,
|
|
456
|
+
outcome = await runTestsWithRetries(runCtx, combinedDispatchPaths);
|
|
391
457
|
}
|
|
392
458
|
catch (error) {
|
|
393
459
|
throw new BuildError('Test process failed to start', 'mach test', error instanceof Error ? error : undefined);
|
|
394
460
|
}
|
|
461
|
+
finally {
|
|
462
|
+
await assertEngineGenerationUnchanged(paths.engine, generationBefore);
|
|
463
|
+
}
|
|
464
|
+
if (canaryPath !== undefined) {
|
|
465
|
+
reportCanaryOutcome(outcome);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
395
468
|
finalizeSingleRunOutcome(outcome, normalizedPaths, projectConfig.binaryName, postRebuildContext);
|
|
396
469
|
}
|
|
397
470
|
/**
|
|
@@ -407,37 +480,3 @@ function buildPerfSampleEnv(projectRoot, binaryName, perfSamples) {
|
|
|
407
480
|
info(`Perf sample contract: ${envName}=${artifactPath}`);
|
|
408
481
|
return { [envName]: artifactPath };
|
|
409
482
|
}
|
|
410
|
-
/** Registers the test command on the CLI program. */
|
|
411
|
-
export function registerTest(program, { getProjectRoot, withErrorHandling }) {
|
|
412
|
-
program
|
|
413
|
-
.command('test [paths...]')
|
|
414
|
-
.description('Run tests via mach test')
|
|
415
|
-
.option('--headless', 'Run tests in headless mode')
|
|
416
|
-
.option('--build', 'Run incremental UI build before testing')
|
|
417
|
-
.option('--doctor', 'Run a marionette handshake preflight before tests (exit 1 on FAIL). With no paths, runs the preflight only.')
|
|
418
|
-
.option('--mach-arg <arg>', 'Forward this argument verbatim to `mach test` (repeatable). Escape valve for upstream xpcshell/mochitest flags FireForge does not model.', (value, acc) => {
|
|
419
|
-
acc.push(value);
|
|
420
|
-
return acc;
|
|
421
|
-
}, [])
|
|
422
|
-
.option('--harness-retries <n>', `Retry budget for recognized harness crashes (resource-monitor tracebacks, pre-test hangs, post-green shutdown re-entry). 0 disables retries. Default: ${String(DEFAULT_HARNESS_RETRIES)}.`, (raw) => {
|
|
423
|
-
const n = Number.parseInt(raw, 10);
|
|
424
|
-
if (!Number.isFinite(n) || n < 0 || n > 10) {
|
|
425
|
-
throw new GeneralError(`--harness-retries must be an integer in 0..10 (got "${raw}")`);
|
|
426
|
-
}
|
|
427
|
-
return n;
|
|
428
|
-
})
|
|
429
|
-
.option('--generic-mach-test', 'Force dispatch through generic `mach test` instead of the suite-specific `mach xpcshell-test` / `mach mochitest` a single-suite run auto-selects (the suite-specific commands skip the mozlog resource monitor that crashes `mach test` on some hosts).')
|
|
430
|
-
.option('--no-shard', 'Run multiple test paths in one combined mach invocation instead of sequential per-file shards')
|
|
431
|
-
.option('--perf-samples <path>', 'Publish a perf-sample artifact path to the harness via <BINARYNAME>_PERF_SAMPLE_JSON (resolved against the project root)')
|
|
432
|
-
.option('--marionette-port <port>', 'Override the Marionette control port (default 2828) for the stale-browser probe, the --doctor preflight, and (unless --mach-arg includes --flavor=xpcshell) auto-forwarded mach args: --setpref=marionette.port=<n> (browser listener) and --marionette=127.0.0.1:<n> (mochitest client). Omits the client flag when --mach-arg already sets --marionette. Use when 2828 is busy or CI assigns another port.', (raw) => {
|
|
433
|
-
const n = Number.parseInt(raw, 10);
|
|
434
|
-
if (!Number.isFinite(n) || n < 1 || n > 65535) {
|
|
435
|
-
throw new GeneralError(`--marionette-port must be an integer in 1..65535 (got "${raw}")`);
|
|
436
|
-
}
|
|
437
|
-
return n;
|
|
438
|
-
})
|
|
439
|
-
.action(withErrorHandling(async (paths, options) => {
|
|
440
|
-
await testCommand(getProjectRoot(), paths, pickDefined(options));
|
|
441
|
-
}));
|
|
442
|
-
}
|
|
443
|
-
//# sourceMappingURL=test.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { Option } from 'commander';
|
|
2
|
+
import { Command, Option } from 'commander';
|
|
3
3
|
import { loadConfig } from '../core/config.js';
|
|
4
4
|
import { furnaceConfigExists, loadFurnaceConfig } from '../core/furnace-config.js';
|
|
5
5
|
import { addToken, getTokensCssPath, validateTokenAdd, } from '../core/token-manager.js';
|
|
@@ -183,4 +183,3 @@ export function registerToken(program, { getProjectRoot, withErrorHandling }) {
|
|
|
183
183
|
await tokenCoverageCommand(getProjectRoot());
|
|
184
184
|
}));
|
|
185
185
|
}
|
|
186
|
-
//# sourceMappingURL=token.js.map
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* Exits non-zero on any error-severity diagnostic. Warnings print
|
|
16
16
|
* but do not fail. Designed for CI use.
|
|
17
17
|
*/
|
|
18
|
+
import { Command } from 'commander';
|
|
18
19
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
19
20
|
import { furnaceConfigExists, loadFurnaceConfig } from '../core/furnace-config.js';
|
|
20
21
|
import { findJsconfigPathsDrift, syncFurnaceJsconfigPaths } from '../core/furnace-jsconfig.js';
|
|
@@ -147,4 +148,3 @@ export function registerTypecheck(program, { getProjectRoot, withErrorHandling }
|
|
|
147
148
|
await typecheckCommand(getProjectRoot(), opts);
|
|
148
149
|
}));
|
|
149
150
|
}
|
|
150
|
-
//# sourceMappingURL=typecheck.js.map
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* treat the output as pass/fail.
|
|
16
16
|
*/
|
|
17
17
|
import { join } from 'node:path';
|
|
18
|
+
import { Command } from 'commander';
|
|
18
19
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
19
20
|
import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
|
|
20
21
|
import { isGitRepository } from '../core/git.js';
|
|
@@ -23,6 +24,7 @@ import { buildPatchQueueContext, lintPatchQueue } from '../core/patch-lint.js';
|
|
|
23
24
|
import { loadPatchesManifest, validatePatchesManifestConsistency } from '../core/patch-manifest.js';
|
|
24
25
|
import { evaluatePatchPolicy } from '../core/patch-policy.js';
|
|
25
26
|
import { collectPatchRegistrationReferences } from '../core/patch-registration-refs.js';
|
|
27
|
+
import { buildPatchClaims } from '../core/status-classify.js';
|
|
26
28
|
import { classifyFiles } from '../core/status-classify.js';
|
|
27
29
|
import { GeneralError } from '../errors/base.js';
|
|
28
30
|
import { pathExists, readText } from '../utils/fs.js';
|
|
@@ -88,14 +90,7 @@ async function detectDanglingRegistrations(patchesDir, engineDir, patches) {
|
|
|
88
90
|
return issues;
|
|
89
91
|
}
|
|
90
92
|
function detectCrossPatchFileClaims(manifestPatches) {
|
|
91
|
-
const claims =
|
|
92
|
-
for (const patch of manifestPatches) {
|
|
93
|
-
for (const file of patch.filesAffected) {
|
|
94
|
-
const existing = claims.get(file) ?? [];
|
|
95
|
-
existing.push(patch.filename);
|
|
96
|
-
claims.set(file, existing);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
93
|
+
const claims = buildPatchClaims(manifestPatches);
|
|
99
94
|
const results = [];
|
|
100
95
|
for (const [path, filenames] of claims) {
|
|
101
96
|
if (filenames.length > 1) {
|
|
@@ -284,4 +279,3 @@ export function registerVerify(program, { getProjectRoot, withErrorHandling }) {
|
|
|
284
279
|
await verifyCommand(getProjectRoot());
|
|
285
280
|
}));
|
|
286
281
|
}
|
|
287
|
-
//# sourceMappingURL=verify.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { delimiter, dirname } from 'node:path';
|
|
3
|
+
import { Command } from 'commander';
|
|
3
4
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
4
5
|
import { warnIfFurnaceStale } from '../core/furnace-staleness.js';
|
|
5
6
|
import { buildArtifactMismatchMessage, generateMozconfig, hasBuildArtifacts, hasRunnableBundle, watchWithOutput, } from '../core/mach.js';
|
|
@@ -195,6 +196,10 @@ export async function watchCommand(projectRoot) {
|
|
|
195
196
|
catch (error) {
|
|
196
197
|
throw new BuildError('Watch process failed to start', 'mach watch', error instanceof Error ? error : undefined);
|
|
197
198
|
}
|
|
199
|
+
// On Ctrl+C the bin signal handler now waits for the mach child to shut
|
|
200
|
+
// down (waitForActiveChildShutdown) before exiting, so this continuation
|
|
201
|
+
// can run and whitelist the SIGINT exit code — though the bin may still
|
|
202
|
+
// win the race and terminate first; both outcomes are acceptable.
|
|
198
203
|
if (result.exitCode !== 0 && result.exitCode !== 130) {
|
|
199
204
|
const combinedOutput = `${result.stdout}\n${result.stderr}`;
|
|
200
205
|
if (hasConfigureTimeWatchmanFailure(combinedOutput)) {
|
|
@@ -214,4 +219,3 @@ export function registerWatch(program, { getProjectRoot, withErrorHandling }) {
|
|
|
214
219
|
await watchCommand(getProjectRoot());
|
|
215
220
|
}));
|
|
216
221
|
}
|
|
217
|
-
//# sourceMappingURL=watch.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join, relative } from 'node:path';
|
|
3
|
+
import { Command } from 'commander';
|
|
3
4
|
import { DEFAULT_BROWSER_SUBSCRIPT_DIR, wireSubscript } from '../core/browser-wire.js';
|
|
4
5
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
5
6
|
import { furnaceConfigExists as checkFurnaceConfigExists, loadFurnaceConfig, } from '../core/furnace-config.js';
|
|
@@ -356,4 +357,3 @@ export function registerWire(program, { getProjectRoot, withErrorHandling }) {
|
|
|
356
357
|
await wireCommand(getProjectRoot(), name, pickDefined(options));
|
|
357
358
|
}));
|
|
358
359
|
}
|
|
359
|
-
//# sourceMappingURL=wire.js.map
|
|
@@ -12,4 +12,3 @@ export function validateBrandOverride(configuredBrand, requestedBrand) {
|
|
|
12
12
|
}
|
|
13
13
|
throw new InvalidArgumentError(`Brand override "${requestedBrand}" is not supported yet. FireForge currently operates only on the configured brand "${configuredBrand}".`, 'brand');
|
|
14
14
|
}
|
|
15
|
-
//# sourceMappingURL=brand-validation.js.map
|
|
@@ -475,4 +475,3 @@ export async function auditBuildArtifacts(projectRoot, engineDir, baseline) {
|
|
|
475
475
|
info(`Packaged: ${summary.updated} updated, ${summary.stale} stale, ${summary.missing} missing, ${summary.skipped} skipped`);
|
|
476
476
|
return summary;
|
|
477
477
|
}
|
|
478
|
-
//# sourceMappingURL=build-audit.js.map
|
|
@@ -13,8 +13,10 @@ import { collectChangedEnginePaths } from './engine-changes.js';
|
|
|
13
13
|
import { applyAllComponents } from './furnace-apply.js';
|
|
14
14
|
import { furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, loadFurnaceState, } from './furnace-config.js';
|
|
15
15
|
import { runFurnaceMutation } from './furnace-operation.js';
|
|
16
|
+
import { countEntriesWithBlockingStepErrors } from './furnace-step-errors.js';
|
|
16
17
|
import { cleanStories } from './furnace-stories.js';
|
|
17
18
|
import { generateMozconfig, runMachCapture } from './mach.js';
|
|
19
|
+
import { explainMachError } from './mach-error-hints.js';
|
|
18
20
|
/** Path fragments of files whose edits invalidate the recursive-make backend. */
|
|
19
21
|
const BACKEND_INVALIDATING_SUFFIXES = ['moz.build', 'moz.configure', 'Makefile.in'];
|
|
20
22
|
/**
|
|
@@ -31,6 +33,21 @@ function extractMachConfigureError(result) {
|
|
|
31
33
|
return '';
|
|
32
34
|
return combined.split('\n').slice(-40).join('\n').trim();
|
|
33
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Builds the `BuildError` for a non-zero auto-configure exit: the output
|
|
38
|
+
* tail (so the underlying mozbuild failure survives), any matched
|
|
39
|
+
* mach-error hints (so e.g. a toolchain minimum that moved with a source
|
|
40
|
+
* hop names `fireforge bootstrap` on this path too, exactly like the
|
|
41
|
+
* protected build dispatch), and the stop rationale.
|
|
42
|
+
*/
|
|
43
|
+
function buildConfigureFailureError(captured) {
|
|
44
|
+
const detail = extractMachConfigureError(captured);
|
|
45
|
+
const hints = explainMachError(`${captured.stderr}\n${captured.stdout}`);
|
|
46
|
+
return new BuildError(`Backend regeneration failed: mach configure exited with code ${captured.exitCode}.` +
|
|
47
|
+
(detail ? `\n\nmach configure output (tail):\n${detail}` : '') +
|
|
48
|
+
(hints.length > 0 ? `\n\n${hints.map((hint) => `Hint: ${hint}`).join('\n')}` : '') +
|
|
49
|
+
'\n\nBuild stopped because continuing would hide the real configure failure.', 'mach configure');
|
|
50
|
+
}
|
|
34
51
|
/**
|
|
35
52
|
* Returns true when the file path matches a pattern that forces
|
|
36
53
|
* `mach configure` to regenerate the backend. Exported for testing.
|
|
@@ -84,11 +101,9 @@ export async function prepareBuildEnvironment(projectRoot, paths, config, option
|
|
|
84
101
|
if (exitCode !== 0) {
|
|
85
102
|
configureSpinner.error(`mach configure failed with exit code ${exitCode}`);
|
|
86
103
|
// Surface the underlying mozbuild error (e.g. UnsortedError) instead
|
|
87
|
-
// of a bare exit code — the generic message hid the actual cause
|
|
88
|
-
|
|
89
|
-
throw
|
|
90
|
-
(detail ? `\n\nmach configure output (tail):\n${detail}` : '') +
|
|
91
|
-
'\n\nBuild stopped because continuing would hide the real configure failure.', 'mach configure');
|
|
104
|
+
// of a bare exit code — the generic message hid the actual cause —
|
|
105
|
+
// plus any matched mach-error hints (see the helper).
|
|
106
|
+
throw buildConfigureFailureError(captured);
|
|
92
107
|
}
|
|
93
108
|
else {
|
|
94
109
|
configureSpinner.stop('Backend regenerated successfully (mach configure exit code 0)');
|
|
@@ -155,7 +170,7 @@ export async function prepareBuildEnvironment(projectRoot, paths, config, option
|
|
|
155
170
|
// These are distinct from `result.errors`, which captures
|
|
156
171
|
// components that failed before reaching the applied list at all.
|
|
157
172
|
// The sum of the two is the total count of failed components.
|
|
158
|
-
const appliedWithStepErrorsCount = result.applied
|
|
173
|
+
const appliedWithStepErrorsCount = countEntriesWithBlockingStepErrors(result.applied);
|
|
159
174
|
const totalApplyFailures = result.errors.length + appliedWithStepErrorsCount;
|
|
160
175
|
if (totalApplyFailures > 0) {
|
|
161
176
|
furnaceSpinner.error('Failed to apply Furnace components');
|
|
@@ -196,4 +211,3 @@ export async function prepareBuildEnvironment(projectRoot, paths, config, option
|
|
|
196
211
|
}
|
|
197
212
|
return { furnaceApplied, reconfigured };
|
|
198
213
|
}
|
|
199
|
-
//# sourceMappingURL=build-prepare.js.map
|
|
@@ -9,9 +9,9 @@ export declare const FIREFORGE_DIR = ".fireforge";
|
|
|
9
9
|
/** Name of the state file */
|
|
10
10
|
export declare const STATE_FILENAME = "state.json";
|
|
11
11
|
/** Supported top-level fireforge.json keys backed by the current schema. */
|
|
12
|
-
export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment"];
|
|
12
|
+
export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "test", "externalToolchains", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment"];
|
|
13
13
|
/** Supported config paths that can be read or set without --force. */
|
|
14
|
-
export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "build", "build.jobs", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment"];
|
|
14
|
+
export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "build", "build.jobs", "test", "test.canaryPath", "test.canaryTimeoutSeconds", "externalToolchains", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment"];
|
|
15
15
|
/**
|
|
16
16
|
* Gets all project paths based on a root directory.
|
|
17
17
|
* @param root - Root directory of the project
|
|
@@ -25,6 +25,8 @@ export const SUPPORTED_CONFIG_ROOT_KEYS = [
|
|
|
25
25
|
'binaryName',
|
|
26
26
|
'firefox',
|
|
27
27
|
'build',
|
|
28
|
+
'test',
|
|
29
|
+
'externalToolchains',
|
|
28
30
|
'license',
|
|
29
31
|
'wire',
|
|
30
32
|
'patchLint',
|
|
@@ -45,6 +47,10 @@ export const SUPPORTED_CONFIG_PATHS = [
|
|
|
45
47
|
'firefox.sha256',
|
|
46
48
|
'build',
|
|
47
49
|
'build.jobs',
|
|
50
|
+
'test',
|
|
51
|
+
'test.canaryPath',
|
|
52
|
+
'test.canaryTimeoutSeconds',
|
|
53
|
+
'externalToolchains',
|
|
48
54
|
'wire',
|
|
49
55
|
'wire.subscriptDir',
|
|
50
56
|
'patchLint',
|
|
@@ -81,4 +87,3 @@ export function getProjectPaths(root) {
|
|
|
81
87
|
componentsDir: join(root, 'components'),
|
|
82
88
|
};
|
|
83
89
|
}
|
|
84
|
-
//# sourceMappingURL=config-paths.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FireForgeConfig } from '../types/config.js';
|
|
2
|
+
import { parseObject } from '../utils/parse.js';
|
|
3
|
+
type ConfigRecord = ReturnType<typeof parseObject>;
|
|
4
|
+
/** Parses the optional `test` block. */
|
|
5
|
+
export declare function parseTestBlock(rec: ConfigRecord, config: FireForgeConfig): void;
|
|
6
|
+
/** Parses optional project-specific external toolchain doctor probes. */
|
|
7
|
+
export declare function parseExternalToolchainsBlock(rec: ConfigRecord, config: FireForgeConfig): void;
|
|
8
|
+
export {};
|