@hominis/fireforge 0.45.0 → 0.46.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 +80 -0
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +5 -1
- package/dist/src/cli.js +20 -21
- package/dist/src/commands/bootstrap.js +1 -2
- package/dist/src/commands/build.js +15 -6
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/doctor-check-core.d.ts +0 -6
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-orphaned-harness.d.ts +0 -6
- package/dist/src/commands/doctor-orphaned-harness.js +4 -12
- package/dist/src/commands/doctor-post-rebase-audit.js +1 -1
- package/dist/src/commands/doctor.d.ts +2 -0
- package/dist/src/commands/doctor.js +7 -8
- package/dist/src/commands/download.js +35 -24
- package/dist/src/commands/export-all.js +21 -4
- package/dist/src/commands/export-flow.js +15 -45
- package/dist/src/commands/export-placement-conflicts.js +3 -3
- package/dist/src/commands/export-placement-gate.js +2 -8
- package/dist/src/commands/export-placement-policy.js +3 -5
- package/dist/src/commands/export-shared.d.ts +42 -23
- package/dist/src/commands/export-shared.js +4 -19
- package/dist/src/commands/export.js +10 -1
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.js +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +3 -8
- package/dist/src/commands/furnace/create-dry-run.js +2 -5
- package/dist/src/commands/furnace/create-templates.d.ts +17 -1
- package/dist/src/commands/furnace/create-templates.js +2 -1
- package/dist/src/commands/furnace/create.js +25 -19
- package/dist/src/commands/furnace/deploy.js +11 -2
- package/dist/src/commands/furnace/init.js +2 -1
- package/dist/src/commands/furnace/override.js +28 -19
- package/dist/src/commands/furnace/refresh.js +9 -1
- package/dist/src/commands/furnace/remove-mutations.d.ts +6 -7
- package/dist/src/commands/furnace/remove-mutations.js +0 -1
- package/dist/src/commands/furnace/remove.js +2 -6
- package/dist/src/commands/furnace/rename-browser-test.js +1 -7
- package/dist/src/commands/furnace/rename.js +29 -29
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +2 -9
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +19 -4
- package/dist/src/commands/lint-per-run-checkjs.d.ts +2 -2
- package/dist/src/commands/lint.d.ts +2 -1
- package/dist/src/commands/lint.js +1 -1
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +2 -4
- package/dist/src/commands/patch/compact.js +14 -15
- package/dist/src/commands/patch/delete.js +15 -25
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +0 -8
- package/dist/src/commands/patch/lint-ignore.js +19 -29
- package/dist/src/commands/patch/move-files-create.js +24 -10
- package/dist/src/commands/patch/move-files-into.js +38 -34
- package/dist/src/commands/patch/move-files.js +4 -13
- package/dist/src/commands/patch/rename.js +27 -41
- package/dist/src/commands/patch/reorder.js +25 -38
- package/dist/src/commands/patch/split-plan.d.ts +4 -5
- package/dist/src/commands/patch/split-plan.js +4 -8
- package/dist/src/commands/patch/split.js +45 -43
- package/dist/src/commands/patch/staged-dependency.js +16 -22
- package/dist/src/commands/patch/tier.js +15 -25
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +24 -2
- package/dist/src/commands/re-export-adjacent.js +32 -16
- package/dist/src/commands/re-export-bulk-scan.js +6 -10
- package/dist/src/commands/re-export-drift.js +4 -4
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +38 -29
- package/dist/src/commands/re-export-lint.d.ts +3 -4
- package/dist/src/commands/re-export-lint.js +9 -2
- package/dist/src/commands/re-export-scan.js +5 -2
- package/dist/src/commands/re-export-single.d.ts +22 -3
- package/dist/src/commands/re-export-single.js +19 -11
- package/dist/src/commands/re-export.js +28 -11
- package/dist/src/commands/rebase/abort.js +3 -8
- package/dist/src/commands/rebase/continue.js +12 -12
- package/dist/src/commands/rebase/index.js +2 -2
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +2 -7
- package/dist/src/commands/resolve.js +18 -10
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +12 -25
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +16 -16
- package/dist/src/commands/setup.js +3 -9
- package/dist/src/commands/source.js +8 -1
- package/dist/src/commands/status-check.js +2 -2
- package/dist/src/commands/status-output.js +2 -2
- package/dist/src/commands/status.js +3 -4
- package/dist/src/commands/test-build-phase.d.ts +2 -2
- package/dist/src/commands/test-build-phase.js +31 -7
- package/dist/src/commands/test-modes.d.ts +2 -2
- package/dist/src/commands/test-modes.js +0 -1
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.js +25 -18
- package/dist/src/commands/test-stale-gate.js +4 -4
- package/dist/src/commands/test-verdict.d.ts +16 -2
- package/dist/src/commands/test-verdict.js +18 -3
- package/dist/src/commands/test.js +42 -5
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +17 -1
- package/dist/src/commands/tree.js +7 -2
- package/dist/src/commands/typecheck.js +9 -9
- package/dist/src/commands/wire.js +4 -3
- package/dist/src/core/branding.d.ts +0 -7
- package/dist/src/core/branding.js +3 -2
- package/dist/src/core/browser-wire.js +6 -3
- package/dist/src/core/build-audit-platform.d.ts +29 -0
- package/dist/src/core/build-audit-platform.js +140 -0
- package/dist/src/core/build-audit-registration.js +3 -2
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit.d.ts +15 -2
- package/dist/src/core/build-audit.js +110 -10
- package/dist/src/core/build-baseline.d.ts +45 -28
- package/dist/src/core/build-baseline.js +6 -29
- package/dist/src/core/build-jar-escalation.js +3 -2
- package/dist/src/core/build-overwrite-guard.js +1 -1
- package/dist/src/core/build-prepare.d.ts +0 -8
- package/dist/src/core/build-prepare.js +7 -12
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +1 -19
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.js +1 -1
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +14 -3
- package/dist/src/core/config.d.ts +2 -2
- package/dist/src/core/config.js +11 -15
- package/dist/src/core/coverage-extend.js +4 -4
- package/dist/src/core/discard-baseline.js +7 -7
- package/dist/src/core/engine-precondition.d.ts +1 -9
- package/dist/src/core/engine-precondition.js +3 -8
- package/dist/src/core/engine-session-lock.js +13 -17
- package/dist/src/core/export-moved-code-shape.js +2 -2
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +2 -7
- package/dist/src/core/file-lock.js +40 -91
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +59 -34
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +37 -21
- package/dist/src/core/firefox-extract.d.ts +6 -5
- package/dist/src/core/firefox-extract.js +36 -18
- package/dist/src/core/firefox.d.ts +30 -32
- package/dist/src/core/firefox.js +5 -36
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +1 -7
- package/dist/src/core/furnace-apply-helpers.d.ts +0 -11
- package/dist/src/core/furnace-apply-helpers.js +8 -19
- package/dist/src/core/furnace-apply-overwrite-warn.js +4 -2
- package/dist/src/core/furnace-apply.d.ts +1 -1
- package/dist/src/core/furnace-apply.js +30 -10
- package/dist/src/core/furnace-config.d.ts +1 -1
- package/dist/src/core/furnace-config.js +23 -36
- package/dist/src/core/furnace-constants.js +3 -2
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-operation.d.ts +2 -0
- package/dist/src/core/furnace-operation.js +3 -1
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +3 -6
- package/dist/src/core/furnace-registration-ast.d.ts +0 -1
- package/dist/src/core/furnace-registration-ast.js +0 -3
- package/dist/src/core/furnace-registration.d.ts +2 -1
- package/dist/src/core/furnace-registration.js +22 -29
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-state-persist.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +5 -7
- package/dist/src/core/git-base.d.ts +3 -1
- package/dist/src/core/git-base.js +25 -3
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +9 -9
- package/dist/src/core/git-diff.js +88 -157
- package/dist/src/core/git-file-ops.d.ts +0 -7
- package/dist/src/core/git-file-ops.js +4 -28
- package/dist/src/core/git-readonly-index.d.ts +0 -2
- package/dist/src/core/git-readonly-index.js +0 -4
- package/dist/src/core/git-status.d.ts +7 -0
- package/dist/src/core/git-status.js +21 -9
- package/dist/src/core/git.d.ts +0 -6
- package/dist/src/core/git.js +14 -43
- package/dist/src/core/harness-orphans.js +8 -7
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/mach-error-hints.d.ts +0 -5
- package/dist/src/core/mach-error-hints.js +1 -1
- package/dist/src/core/mach-known-noise-filter.d.ts +4 -3
- package/dist/src/core/mach-known-noise-filter.js +7 -9
- package/dist/src/core/mach-mozconfig.js +2 -1
- package/dist/src/core/mach-python.d.ts +2 -0
- package/dist/src/core/mach-python.js +12 -7
- package/dist/src/core/mach-resource-shim.d.ts +13 -1
- package/dist/src/core/mach-resource-shim.js +112 -9
- package/dist/src/core/mach.d.ts +39 -53
- package/dist/src/core/mach.js +13 -81
- package/dist/src/core/marionette-port.d.ts +0 -17
- package/dist/src/core/marionette-port.js +12 -58
- package/dist/src/core/marionette-preflight.js +9 -27
- package/dist/src/core/mochitest-server-port.js +3 -3
- package/dist/src/core/moz-manifest-rules.js +37 -33
- package/dist/src/core/patch-apply-fuzz.js +4 -4
- package/dist/src/core/patch-apply.d.ts +4 -5
- package/dist/src/core/patch-apply.js +6 -12
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +18 -1
- package/dist/src/core/patch-export-update.js +4 -3
- package/dist/src/core/patch-export.d.ts +11 -21
- package/dist/src/core/patch-export.js +44 -66
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-lint-binary.d.ts +6 -12
- package/dist/src/core/patch-lint-cache.d.ts +17 -1
- package/dist/src/core/patch-lint-cache.js +3 -6
- package/dist/src/core/patch-lint-checkjs.d.ts +33 -16
- package/dist/src/core/patch-lint-checkjs.js +37 -24
- package/dist/src/core/patch-lint-creators.d.ts +2 -6
- package/dist/src/core/patch-lint-cross.d.ts +16 -8
- package/dist/src/core/patch-lint-cross.js +49 -92
- package/dist/src/core/patch-lint-css.js +10 -6
- package/dist/src/core/patch-lint-file-size.js +3 -3
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.js +36 -36
- package/dist/src/core/patch-lint-module-registration.d.ts +2 -8
- package/dist/src/core/patch-lint-prettier.js +1 -1
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint.d.ts +14 -9
- package/dist/src/core/patch-lint.js +4 -3
- package/dist/src/core/patch-lock.js +3 -3
- package/dist/src/core/patch-manifest-io.js +8 -7
- package/dist/src/core/patch-parse.d.ts +19 -8
- package/dist/src/core/patch-parse.js +25 -0
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +0 -8
- package/dist/src/core/patch-transform.js +0 -10
- package/dist/src/core/process-cpu-time.js +1 -1
- package/dist/src/core/rebase-session.d.ts +2 -8
- package/dist/src/core/rebase-session.js +5 -17
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-scaffold.js +5 -4
- package/dist/src/core/register-shared-css.js +2 -1
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +13 -2
- package/dist/src/core/run-log.js +67 -18
- package/dist/src/core/signal-critical.js +2 -4
- package/dist/src/core/smoke-patterns.d.ts +0 -1
- package/dist/src/core/smoke-patterns.js +6 -11
- package/dist/src/core/state-file.d.ts +12 -1
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-classify.js +2 -1
- package/dist/src/core/test-changed-prefs.js +26 -11
- package/dist/src/core/test-harness-crash.js +2 -2
- package/dist/src/core/test-stale-check.d.ts +0 -2
- package/dist/src/core/test-stale-check.js +2 -2
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +33 -0
- package/dist/src/core/token-category.js +56 -48
- package/dist/src/core/token-dark-mode.js +2 -14
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +1 -1
- package/dist/src/core/token-manager.js +1 -1
- package/dist/src/core/token-variant.js +21 -22
- package/dist/src/core/toolchain-preflight.js +1 -1
- package/dist/src/core/tree-cow.d.ts +0 -2
- package/dist/src/core/tree-cow.js +2 -2
- package/dist/src/core/tree-store.js +4 -5
- package/dist/src/core/typecheck.js +2 -2
- package/dist/src/core/wire-dom-fragment.js +6 -17
- package/dist/src/core/wire-utils.js +5 -17
- package/dist/src/core/xpcshell-appdir.js +2 -4
- package/dist/src/errors/base.d.ts +53 -1
- package/dist/src/errors/base.js +79 -11
- package/dist/src/errors/build.js +20 -28
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +8 -8
- package/dist/src/errors/git.js +20 -30
- package/dist/src/errors/patch.js +8 -10
- package/dist/src/errors/rebase.js +7 -7
- package/dist/src/types/commands/options.d.ts +77 -123
- package/dist/src/types/config.d.ts +34 -2
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/utils/assert.d.ts +3 -15
- package/dist/src/utils/assert.js +1 -18
- package/dist/src/utils/build-info.d.ts +1 -1
- package/dist/src/utils/child-env.d.ts +2 -1
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/fs.js +8 -13
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/options.d.ts +1 -7
- package/dist/src/utils/options.js +6 -7
- package/dist/src/utils/package-root.js +3 -12
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +2 -1
- package/dist/src/utils/process-group.js +20 -19
- package/dist/src/utils/process.d.ts +40 -26
- package/dist/src/utils/process.js +115 -166
- package/dist/src/utils/ps-duration.js +3 -3
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/validation.d.ts +2 -38
- package/dist/src/utils/validation.js +7 -16
- package/docs/configuration.md +89 -1
- package/docs/exit-codes.md +31 -19
- package/docs/lifecycle-invariants.md +18 -12
- package/docs/machine-output.md +31 -8
- package/docs/patch-workflow.md +2 -1
- package/docs/run-logs.md +44 -4
- package/docs/testing.md +8 -1
- package/package.json +8 -7
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -8,7 +8,7 @@ import { ConfigError } from '../errors/config.js';
|
|
|
8
8
|
import { cancel, intro, isCancel, note, outro, spinner } from '../utils/logger.js';
|
|
9
9
|
import { pickDefined } from '../utils/options.js';
|
|
10
10
|
import { FIREFOX_PRODUCTS, PROJECT_LICENSES } from '../utils/validation.js';
|
|
11
|
-
import { buildSetupConfig,
|
|
11
|
+
import { buildSetupConfig, resolveFirefoxProduct, resolveProjectLicense, resolveSetupInputs, validateSetupOptions, writeSetupProjectFiles, } from './setup-support.js';
|
|
12
12
|
/**
|
|
13
13
|
* Runs the setup command.
|
|
14
14
|
* @param projectRoot - Root directory for the project
|
|
@@ -83,16 +83,10 @@ export function registerSetup(program, { withErrorHandling }) {
|
|
|
83
83
|
if (yes === true)
|
|
84
84
|
setupOptions.force = true;
|
|
85
85
|
if (product !== undefined) {
|
|
86
|
-
|
|
87
|
-
if (parsedProduct !== undefined) {
|
|
88
|
-
setupOptions.product = parsedProduct;
|
|
89
|
-
}
|
|
86
|
+
setupOptions.product = resolveFirefoxProduct(product, '--product');
|
|
90
87
|
}
|
|
91
88
|
if (license !== undefined) {
|
|
92
|
-
|
|
93
|
-
if (parsedLicense !== undefined) {
|
|
94
|
-
setupOptions.license = parsedLicense;
|
|
95
|
-
}
|
|
89
|
+
setupOptions.license = resolveProjectLicense(license, '--license');
|
|
96
90
|
}
|
|
97
91
|
await setupCommand(resolve(process.cwd()), setupOptions);
|
|
98
92
|
}));
|
|
@@ -87,7 +87,14 @@ export async function sourceSetCommand(projectRoot, options) {
|
|
|
87
87
|
}
|
|
88
88
|
/** Registers the source command on the CLI program. */
|
|
89
89
|
export function registerSource(program, { getProjectRoot, withErrorHandling }) {
|
|
90
|
-
const source = program
|
|
90
|
+
const source = program
|
|
91
|
+
.command('source')
|
|
92
|
+
.description('Manage Firefox source configuration')
|
|
93
|
+
// No-subcommand contract shared with `patch`/`token`/`furnace`: help on
|
|
94
|
+
// stdout, exit 0 (see `handleParseError` for the groups without an action).
|
|
95
|
+
.action(() => {
|
|
96
|
+
source.outputHelp();
|
|
97
|
+
});
|
|
91
98
|
source
|
|
92
99
|
.command('set')
|
|
93
100
|
.description('Atomically set Firefox source version, product, and optional checksum')
|
|
@@ -95,9 +95,9 @@ export function runStatusCheck(classified, policy) {
|
|
|
95
95
|
const offending = collectStatusCheckOffenders(classified, policy).map((offender) => {
|
|
96
96
|
const preview = offender.files.slice(0, CHECK_FILE_PREVIEW_MAX).join(', ');
|
|
97
97
|
const more = offender.count > CHECK_FILE_PREVIEW_MAX
|
|
98
|
-
? `, +${
|
|
98
|
+
? `, +${offender.count - CHECK_FILE_PREVIEW_MAX} more`
|
|
99
99
|
: '';
|
|
100
|
-
return `${
|
|
100
|
+
return `${offender.count} ${offender.classification} (${preview}${more})`;
|
|
101
101
|
});
|
|
102
102
|
if (offending.length === 0)
|
|
103
103
|
return;
|
|
@@ -219,7 +219,7 @@ export function renderTestCoverageStatus(baseline) {
|
|
|
219
219
|
return;
|
|
220
220
|
}
|
|
221
221
|
const list = coverage.map((path) => ` - ${path}`).join('\n');
|
|
222
|
-
info(`Test packaging coverage: scoped to ${
|
|
222
|
+
info(`Test packaging coverage: scoped to ${coverage.length} path(s):\n${list}\n` +
|
|
223
223
|
'A "fireforge test" over paths outside this list will be refused as uncovered.');
|
|
224
|
-
outro(`Coverage: scoped (${
|
|
224
|
+
outro(`Coverage: scoped (${coverage.length} paths)`);
|
|
225
225
|
}
|
|
@@ -15,7 +15,7 @@ import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
|
15
15
|
import { FIREFORGE_TMP_PATH_PATTERN, pathExists } from '../utils/fs.js';
|
|
16
16
|
import { info, intro, isMachineOutputMode, outro, setMachineOutputMode, warn, } from '../utils/logger.js';
|
|
17
17
|
import { emitMachineError } from '../utils/machine-output.js';
|
|
18
|
-
import { resolveStatusCheckPolicy, runStatusCheck } from './status-check.js';
|
|
18
|
+
import { resolveStatusCheckPolicy, runStatusCheck, } from './status-check.js';
|
|
19
19
|
import { renderJsonStatus, renderJsonSummaryStatus } from './status-json.js';
|
|
20
20
|
import { renderDefaultStatus, renderTestCoverageStatus, renderUnmanagedOnly, } from './status-output.js';
|
|
21
21
|
import { buildOwnershipJsonBlock, collectOwnershipRows, summarizeOwnership, } from './status-ownership.js';
|
|
@@ -253,7 +253,6 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
253
253
|
const config = await loadConfig(projectRoot);
|
|
254
254
|
// Shared envelope: see src/utils/machine-output.ts and
|
|
255
255
|
// docs/machine-output.md. `status` was the only command that had one.
|
|
256
|
-
const emitJsonError = emitMachineError;
|
|
257
256
|
// Ownership mode is a flat file→patch table; sources are the manifest's
|
|
258
257
|
// filesAffected, any worktree drift, and the cross-patch
|
|
259
258
|
// duplicate-new-file-creation map produced by walking each patch body. The
|
|
@@ -292,14 +291,14 @@ async function runStatusCommandBody(projectRoot, options) {
|
|
|
292
291
|
// message is kept identical to the helper's on purpose.
|
|
293
292
|
if (!(await pathExists(paths.engine))) {
|
|
294
293
|
if (options.json) {
|
|
295
|
-
|
|
294
|
+
emitMachineError('engine-missing', 'Firefox source not found. Run "fireforge download" first.');
|
|
296
295
|
}
|
|
297
296
|
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
298
297
|
}
|
|
299
298
|
// Check if it's a git repository
|
|
300
299
|
if (!(await isGitRepository(paths.engine))) {
|
|
301
300
|
if (options.json) {
|
|
302
|
-
|
|
301
|
+
emitMachineError('engine-not-git', 'Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
303
302
|
}
|
|
304
303
|
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
305
304
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* the per-file line budget): the incremental protected mach build with
|
|
4
4
|
* its baseline write, and the `--build-only` union-build shape.
|
|
5
5
|
*/
|
|
6
|
-
import type { getProjectPaths, loadConfig } from '../core/config.js';
|
|
7
6
|
import type { TestOptions } from '../types/commands/index.js';
|
|
7
|
+
import type { FireForgeConfig, ProjectPaths } from '../types/config.js';
|
|
8
8
|
import type { HarnessClassification } from './test-modes.js';
|
|
9
9
|
/**
|
|
10
10
|
* Runs the pre-test build (or the stale-build gate when no build was
|
|
@@ -13,7 +13,7 @@ import type { HarnessClassification } from './test-modes.js';
|
|
|
13
13
|
* (mixed harnesses legal, nothing dispatches), prints the per-harness
|
|
14
14
|
* next steps, and emits the run's single `PASS` verdict.
|
|
15
15
|
*/
|
|
16
|
-
export declare function runTestBuildPhase(projectRoot: string, paths:
|
|
16
|
+
export declare function runTestBuildPhase(projectRoot: string, paths: ProjectPaths, projectConfig: FireForgeConfig, harnessRetries: number, options: TestOptions, request: {
|
|
17
17
|
classification: HarnessClassification;
|
|
18
18
|
normalizedPaths: string[];
|
|
19
19
|
}): Promise<boolean>;
|
|
@@ -16,7 +16,14 @@ import { info, notice, spinner, verbose } from '../utils/logger.js';
|
|
|
16
16
|
import { reportBuildOnlyCompletion } from './test-modes.js';
|
|
17
17
|
import { enforceStaleBuildGate, enforceStaticComponentsGate } from './test-stale-gate.js';
|
|
18
18
|
import { emitPassVerdict } from './test-verdict.js';
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Runs the incremental pre-test build under the build lock and records the
|
|
21
|
+
* baseline it produced.
|
|
22
|
+
*
|
|
23
|
+
* @param options - See {@link RunPreTestBuildOptions}
|
|
24
|
+
*/
|
|
25
|
+
async function runPreTestBuild(options) {
|
|
26
|
+
const { projectRoot, paths, projectConfig, harnessRetries, testPackagingCoverage, refuseUnexportedDrift, extend, } = options;
|
|
20
27
|
await withBuildLock(projectRoot, async () => {
|
|
21
28
|
// Pass the previous baseline exactly like `fireforge build` does, so
|
|
22
29
|
// auto-configure runs under the same conditions on both paths. The
|
|
@@ -81,11 +88,20 @@ async function runPreTestBuild(projectRoot, paths, projectConfig, harnessRetries
|
|
|
81
88
|
const recordedCoverage = extend !== undefined
|
|
82
89
|
? unionTestPackagingCoverage(previousBaseline?.testPackagingCoverage, extend.requestedPaths)
|
|
83
90
|
: testPackagingCoverage;
|
|
84
|
-
await writeBuildBaseline(
|
|
85
|
-
|
|
86
|
-
:
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
await writeBuildBaseline({
|
|
92
|
+
projectRoot,
|
|
93
|
+
engineDir: paths.engine,
|
|
94
|
+
binaryName: projectConfig.binaryName,
|
|
95
|
+
testPackagingCoverage: recordedCoverage,
|
|
96
|
+
previousBaseline,
|
|
97
|
+
recordedBy: describeBuildInvocation(extend !== undefined, testPackagingCoverage),
|
|
98
|
+
staticComponentsHandling: preparation.fullBuildRequired
|
|
99
|
+
? 'refresh'
|
|
100
|
+
: extend !== undefined
|
|
101
|
+
? 'carry-forward'
|
|
102
|
+
: 'auto',
|
|
103
|
+
buildKind,
|
|
104
|
+
});
|
|
89
105
|
}
|
|
90
106
|
catch (baselineError) {
|
|
91
107
|
verbose(`Could not persist build baseline: ${toError(baselineError).message}`);
|
|
@@ -166,7 +182,15 @@ export async function runTestBuildPhase(projectRoot, paths, projectConfig, harne
|
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
184
|
}
|
|
169
|
-
await runPreTestBuild(
|
|
185
|
+
await runPreTestBuild({
|
|
186
|
+
projectRoot,
|
|
187
|
+
paths,
|
|
188
|
+
projectConfig,
|
|
189
|
+
harnessRetries,
|
|
190
|
+
testPackagingCoverage: coverage,
|
|
191
|
+
refuseUnexportedDrift: options.refuseUnexportedDrift === true,
|
|
192
|
+
extend: extending ? { requestedPaths: normalizedPaths } : undefined,
|
|
193
|
+
});
|
|
170
194
|
info('');
|
|
171
195
|
if (options.buildOnly) {
|
|
172
196
|
// Union build for mixed harnesses: the coverage claim
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { loadConfig } from '../core/config.js';
|
|
2
1
|
import type { TestOptions } from '../types/commands/index.js';
|
|
2
|
+
import type { FireForgeConfig } from '../types/config.js';
|
|
3
3
|
import type { TestRunOutcome } from './test-run.js';
|
|
4
|
-
type ProjectConfig =
|
|
4
|
+
type ProjectConfig = FireForgeConfig;
|
|
5
5
|
/** Rejects pathless `fireforge test` unless the operator selected a pathless mode. */
|
|
6
6
|
export declare function assertPathlessTestMode(testPaths: readonly string[], options: TestOptions): void;
|
|
7
7
|
/** Rejects invalid combinations for mode-like `fireforge test` options. */
|
|
@@ -28,7 +28,7 @@ const TEST_HELP_TEXT = [
|
|
|
28
28
|
'Machine-readable verdict: every run (single, sharded, --canary,',
|
|
29
29
|
'--doctor) ends with exactly one raw stdout line',
|
|
30
30
|
' FIREFORGE-VERDICT: PASS|FAIL [reason=crash|test-failures|',
|
|
31
|
-
' no-tests|preflight|inconclusive|lock-timeout] [checks=<n>]',
|
|
31
|
+
' no-tests|preflight|inconclusive|lock-timeout|killed] [checks=<n>]',
|
|
32
32
|
' [unexpected=<n>] [shards=<p>/<t>] [(<note>)] [log=<path>]',
|
|
33
33
|
"log=<path> names this run's complete output, written to",
|
|
34
34
|
'.fireforge/logs/ as the run streams, so a piped or truncated run',
|
|
@@ -41,7 +41,9 @@ const TEST_HELP_TEXT = [
|
|
|
41
41
|
'errors); reason=inconclusive means engine/ changed while the',
|
|
42
42
|
'tests ran, so the harness result cannot be trusted;',
|
|
43
43
|
'reason=lock-timeout means the run never started because another',
|
|
44
|
-
'engine-mutating command held the lock past the wait budget
|
|
44
|
+
'engine-mutating command held the lock past the wait budget;',
|
|
45
|
+
'reason=killed means a signal terminated the run before it reached',
|
|
46
|
+
'any other outcome (written from the signal handler). A sharded',
|
|
45
47
|
'aggregate reason is the most structural failing shard (crash,',
|
|
46
48
|
'then no-tests, then test-failures). Count keys are omitted when',
|
|
47
49
|
'the embedded summary did not print them. A trailing parenthetical',
|
|
@@ -71,7 +73,7 @@ export function registerTest(program, { getProjectRoot, withErrorHandling }) {
|
|
|
71
73
|
.option('--canary [path]', 'Run one short browser-chrome harness canary. Uses test.canaryPath from fireforge.json when no path is supplied.')
|
|
72
74
|
.option('--doctor', 'Run a marionette handshake preflight before tests (exit 1 on FAIL). With no paths, runs the preflight only.')
|
|
73
75
|
.option('--mach-arg <arg>', 'Forward this argument verbatim to `mach test` (repeatable). Escape valve for upstream xpcshell/mochitest flags FireForge does not model.', ...stringListOption())
|
|
74
|
-
.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: ${
|
|
76
|
+
.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: ${DEFAULT_HARNESS_RETRIES}.`, commanderArgParser((raw) => {
|
|
75
77
|
const n = Number.parseInt(raw, 10);
|
|
76
78
|
if (!Number.isFinite(n) || n < 0 || n > 10) {
|
|
77
79
|
throw new GeneralError(`--harness-retries must be an integer in 0..10 (got "${raw}")`);
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* stays available via `--no-shard`.
|
|
12
12
|
*/
|
|
13
13
|
import { probeDisplaySleepState } from '../core/display-state.js';
|
|
14
|
-
import {
|
|
14
|
+
import { runMachTestSuite } from '../core/mach.js';
|
|
15
15
|
import { getActiveRunLogPath } from '../core/run-log.js';
|
|
16
16
|
import { changedPrefNoiseVerdictNote } from '../core/test-changed-prefs.js';
|
|
17
17
|
import { buildHarnessCrashMessage, classifyHarnessRun, headedDisplayAsleepVerdictNote, headedNoOutputTimeoutHint, } from '../core/test-harness-crash.js';
|
|
@@ -24,13 +24,13 @@ import { maybeInjectAppdirArg } from './test-appdir.js';
|
|
|
24
24
|
import { emitHarnessVerdict } from './test-verdict.js';
|
|
25
25
|
/** Default bounded retry budget for recognized harness crashes. */
|
|
26
26
|
export const DEFAULT_HARNESS_RETRIES = 2;
|
|
27
|
-
/** Resolves the
|
|
28
|
-
function
|
|
27
|
+
/** Resolves the mach test command a suite dispatches to. */
|
|
28
|
+
function machKindForSuite(suite) {
|
|
29
29
|
if (suite === 'xpcshell')
|
|
30
|
-
return
|
|
30
|
+
return 'xpcshell-test';
|
|
31
31
|
if (suite === 'mochitest')
|
|
32
|
-
return
|
|
33
|
-
return
|
|
32
|
+
return 'mochitest';
|
|
33
|
+
return 'test';
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Runs one mach test invocation for `paths`, retrying recognized harness
|
|
@@ -54,24 +54,31 @@ export async function runTestsWithRetries(ctx, paths) {
|
|
|
54
54
|
async function runTestsWithRetriesInner(ctx, paths, env) {
|
|
55
55
|
const extraArgs = [...ctx.baseExtraArgs];
|
|
56
56
|
const appdirInjectionAttempted = await maybeInjectAppdirArg(ctx.engineDir, paths, ctx.objDir, extraArgs);
|
|
57
|
-
const
|
|
57
|
+
const kind = machKindForSuite(ctx.suite);
|
|
58
58
|
const maxAttempts = Math.max(1, ctx.harnessRetries + 1);
|
|
59
59
|
let attempts = 0;
|
|
60
60
|
let result;
|
|
61
61
|
let verdict;
|
|
62
62
|
for (;;) {
|
|
63
63
|
attempts += 1;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
ctx.fullOutput
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
result = await runMachTestSuite(kind, {
|
|
65
|
+
engineDir: ctx.engineDir,
|
|
66
|
+
testPaths: paths,
|
|
67
|
+
args: extraArgs,
|
|
68
|
+
env,
|
|
69
|
+
fullOutput: ctx.fullOutput,
|
|
70
|
+
});
|
|
71
|
+
result = await retryAfterXpcshellSymlinkRepair({
|
|
72
|
+
engineDir: ctx.engineDir,
|
|
73
|
+
objDir: ctx.objDir,
|
|
74
|
+
result,
|
|
75
|
+
classification: ctx.classification,
|
|
76
|
+
normalizedPaths: paths,
|
|
77
|
+
extraArgs,
|
|
78
|
+
env,
|
|
79
|
+
kind,
|
|
80
|
+
fullOutput: ctx.fullOutput,
|
|
81
|
+
});
|
|
75
82
|
const combined = `${result.stdout}\n${result.stderr}`;
|
|
76
83
|
verdict = classifyHarnessRun(result.exitCode, combined, paths);
|
|
77
84
|
if (verdict.kind !== 'harness-crash' || attempts >= maxAttempts)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* `src/core/test-stale-check.ts`.
|
|
9
9
|
*/
|
|
10
10
|
import { checkStaleBuildForTest, checkStaticComponentsStale, findChangedTestManifestsForPaths, findUncoveredRequestPaths, formatStaleBuildWarning, formatStaticComponentsRefusal, formatTestCoverageRefusal, } from '../core/test-stale-check.js';
|
|
11
|
-
import {
|
|
11
|
+
import { PreflightRefusalError } from '../errors/base.js';
|
|
12
12
|
import { warn } from '../utils/logger.js';
|
|
13
13
|
/**
|
|
14
14
|
* Stale-build preflight — when `--build` was NOT requested, detect packageable
|
|
@@ -40,7 +40,7 @@ export async function enforceStaleBuildGate(projectRoot, engineDir, options, nor
|
|
|
40
40
|
// The refusal is correct on its own; naming the manifest that gained
|
|
41
41
|
// an entry is the triage step it otherwise leaves to the reader.
|
|
42
42
|
const changedManifests = await findChangedTestManifestsForPaths(engineDir, stale.baseline, uncovered);
|
|
43
|
-
throw new
|
|
43
|
+
throw new PreflightRefusalError(formatTestCoverageRefusal(uncovered, Array.isArray(recordedCoverage) ? recordedCoverage : [], changedManifests), 'coverage-replaced');
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
await enforceStaticComponentsGate(engineDir, stale.baseline, options);
|
|
@@ -59,7 +59,7 @@ export async function enforceStaleBuildGate(projectRoot, engineDir, options, nor
|
|
|
59
59
|
warn(staleMessage);
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
throw new
|
|
62
|
+
throw new PreflightRefusalError(staleMessage, 'stale-build');
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -84,5 +84,5 @@ export async function enforceStaticComponentsGate(engineDir, baseline, options)
|
|
|
84
84
|
warn(message);
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
-
throw new
|
|
87
|
+
throw new PreflightRefusalError(message, 'stale-components');
|
|
88
88
|
}
|
|
@@ -30,8 +30,22 @@ export declare function emitHarnessVerdict(verdict: HarnessRunVerdict, shards?:
|
|
|
30
30
|
}): void;
|
|
31
31
|
/** Emits the pathless `--doctor` PASS verdict. */
|
|
32
32
|
export declare function emitPassVerdict(): void;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Emits a FAIL verdict carrying an emission-layer reason code, and
|
|
35
|
+
* optionally the refusal class that produced it.
|
|
36
|
+
*
|
|
37
|
+
* `note=` is ADDITIVE, like the `log=`, `signal=` and `shards=` keys already
|
|
38
|
+
* on this line: `reason=` is unchanged and still comes from the closed set
|
|
39
|
+
* in `docs/machine-output.md`, so a consumer that tokenises `key=value`
|
|
40
|
+
* pairs is unaffected. It exists because `reason=preflight` covers every
|
|
41
|
+
* gate before the harness — a missing build, a peer's packaging record, a
|
|
42
|
+
* developer browser holding the objdir — and an unattended reader whose
|
|
43
|
+
* pipe kept only the verdict line could not tell those apart.
|
|
44
|
+
*
|
|
45
|
+
* @param reason - Closed-set verdict reason
|
|
46
|
+
* @param note - Stable refusal class, when the thrower named one
|
|
47
|
+
*/
|
|
48
|
+
export declare function emitFailVerdict(reason: FireforgeVerdictReason, note?: string): void;
|
|
35
49
|
/**
|
|
36
50
|
* Emits the terminal verdict for a run killed by a signal.
|
|
37
51
|
*
|
|
@@ -61,9 +61,24 @@ export function emitHarnessVerdict(verdict, shards) {
|
|
|
61
61
|
export function emitPassVerdict() {
|
|
62
62
|
writeVerdictLine('FIREFORGE-VERDICT: PASS');
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Emits a FAIL verdict carrying an emission-layer reason code, and
|
|
66
|
+
* optionally the refusal class that produced it.
|
|
67
|
+
*
|
|
68
|
+
* `note=` is ADDITIVE, like the `log=`, `signal=` and `shards=` keys already
|
|
69
|
+
* on this line: `reason=` is unchanged and still comes from the closed set
|
|
70
|
+
* in `docs/machine-output.md`, so a consumer that tokenises `key=value`
|
|
71
|
+
* pairs is unaffected. It exists because `reason=preflight` covers every
|
|
72
|
+
* gate before the harness — a missing build, a peer's packaging record, a
|
|
73
|
+
* developer browser holding the objdir — and an unattended reader whose
|
|
74
|
+
* pipe kept only the verdict line could not tell those apart.
|
|
75
|
+
*
|
|
76
|
+
* @param reason - Closed-set verdict reason
|
|
77
|
+
* @param note - Stable refusal class, when the thrower named one
|
|
78
|
+
*/
|
|
79
|
+
export function emitFailVerdict(reason, note) {
|
|
80
|
+
const suffix = note === undefined ? '' : ` note=${note}`;
|
|
81
|
+
writeVerdictLine(`FIREFORGE-VERDICT: FAIL reason=${reason}${suffix}`);
|
|
67
82
|
}
|
|
68
83
|
/**
|
|
69
84
|
* Emits the terminal verdict for a run killed by a signal.
|
|
@@ -9,12 +9,13 @@ import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
|
|
|
9
9
|
import { assertMarionettePortAvailable, ensureLaunchableBrowserNotRunning, ensureMarionettePortAvailable, extractForwardedMarionettePort, forwardedMachArgsIncludeMarionetteClient, shouldAutoForwardMarionettePortToMach, } from '../core/marionette-port.js';
|
|
10
10
|
import { formatMarionettePreflightLine, reportMarionettePreflight, runMarionettePreflight, } from '../core/marionette-preflight.js';
|
|
11
11
|
import { ensureMochitestServerPortAvailable } from '../core/mochitest-server-port.js';
|
|
12
|
-
import { closeActiveRunLog, openRunLog, setActiveRunLog } from '../core/run-log.js';
|
|
12
|
+
import { closeActiveRunLog, openRunLog, setActiveRunLog, writeToActiveRunLog, } from '../core/run-log.js';
|
|
13
13
|
import { createPostRebuildFailureContext } from '../core/test-harness-output.js';
|
|
14
14
|
import { analyzeTestPathScopes, formatScopeNotice, } from '../core/test-path-scope.js';
|
|
15
15
|
import { assertObjdirMatchesTreeMarker } from '../core/tree-store.js';
|
|
16
|
-
import { GeneralError } from '../errors/base.js';
|
|
16
|
+
import { FireForgeError, GeneralError, PreflightRefusalError } from '../errors/base.js';
|
|
17
17
|
import { BuildError } from '../errors/build.js';
|
|
18
|
+
import { toError } from '../utils/errors.js';
|
|
18
19
|
import { pathExists } from '../utils/fs.js';
|
|
19
20
|
import { info, intro, notice, outro, verbose } from '../utils/logger.js';
|
|
20
21
|
import { stripEnginePrefix } from '../utils/paths.js';
|
|
@@ -292,14 +293,50 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
|
|
|
292
293
|
await runTestCommandBody(projectRoot, testPaths, options);
|
|
293
294
|
}
|
|
294
295
|
catch (error) {
|
|
295
|
-
if (!verdictEmitted())
|
|
296
|
-
|
|
296
|
+
if (!verdictEmitted()) {
|
|
297
|
+
renderPreflightRefusal(error);
|
|
298
|
+
emitFailVerdict('preflight', refusalNote(error));
|
|
299
|
+
}
|
|
297
300
|
throw error;
|
|
298
301
|
}
|
|
299
302
|
finally {
|
|
300
303
|
await closeActiveRunLog();
|
|
301
304
|
}
|
|
302
305
|
}
|
|
306
|
+
/** The refusal class a preflight gate named, when it named one. */
|
|
307
|
+
function refusalNote(error) {
|
|
308
|
+
return error instanceof PreflightRefusalError ? error.note : undefined;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Puts a preflight refusal's own text on the operator's channel BEFORE the
|
|
312
|
+
* verdict line, and into the run log.
|
|
313
|
+
*
|
|
314
|
+
* Both halves are load-bearing, and neither happened before:
|
|
315
|
+
*
|
|
316
|
+
* - `withErrorHandling` renders `error.userMessage` back in `cli.ts`, but
|
|
317
|
+
* by then `emitFailVerdict` has called `setStdoutSealed(true)` — the seal
|
|
318
|
+
* that keeps the verdict the LAST stdout write — so `logError` routes to
|
|
319
|
+
* stderr. A run captured with `> file` therefore kept the verdict and
|
|
320
|
+
* dropped the reason.
|
|
321
|
+
* - That same rendering happens after this function's caller returns, and
|
|
322
|
+
* the `finally` below has already closed the run log. So the artifact the
|
|
323
|
+
* verdict's own `log=` key points at did not contain the refusal either,
|
|
324
|
+
* which is what left `.fireforge/logs/test-*.log` holding only the
|
|
325
|
+
* pre-test build.
|
|
326
|
+
*
|
|
327
|
+
* Writing here, before the seal, fixes both without trading away the
|
|
328
|
+
* contract: the refusal lands on stdout and in the log, and the verdict
|
|
329
|
+
* line still comes last.
|
|
330
|
+
*/
|
|
331
|
+
function renderPreflightRefusal(error) {
|
|
332
|
+
const text = error instanceof FireForgeError ? error.userMessage : toError(error).message;
|
|
333
|
+
const block = `Preflight refused:\n${text}\n`;
|
|
334
|
+
// Raw stdout rather than the clack logger: this must land on the captured
|
|
335
|
+
// stream verbatim, and clack's renderer can drop output under non-TTY
|
|
336
|
+
// capture — the same reason the verdict line is written this way.
|
|
337
|
+
process.stdout.write(block);
|
|
338
|
+
writeToActiveRunLog(block);
|
|
339
|
+
}
|
|
303
340
|
/**
|
|
304
341
|
* Verifies `engine/` did not change under the run before any PASS verdict
|
|
305
342
|
* may print. On failure the run's verdict is `FAIL reason=inconclusive` —
|
|
@@ -392,7 +429,7 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
392
429
|
extraArgs.push('--auto');
|
|
393
430
|
}
|
|
394
431
|
if (canaryPath !== undefined) {
|
|
395
|
-
extraArgs.push(`--timeout=${
|
|
432
|
+
extraArgs.push(`--timeout=${canaryTimeoutSeconds(projectConfig)}`);
|
|
396
433
|
}
|
|
397
434
|
// --mach-arg is a verbatim passthrough for upstream mach/xpcshell/mochitest
|
|
398
435
|
// flags FireForge does not model directly (see the xpcshell appdir hint
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Options accepted by {@link tokenListCommand}. */
|
|
2
|
+
export interface TokenListOptions {
|
|
3
|
+
/** Restrict the report to one category. */
|
|
4
|
+
category?: string;
|
|
5
|
+
/** Emit the machine-readable envelope instead of the human report. */
|
|
6
|
+
json?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Lists the categories declared in the tokens CSS with their token names,
|
|
10
|
+
* in file order.
|
|
11
|
+
*
|
|
12
|
+
* @param projectRoot - Root directory of the project
|
|
13
|
+
* @param options - Filter and output-mode options
|
|
14
|
+
*/
|
|
15
|
+
export declare function tokenListCommand(projectRoot: string, options?: TokenListOptions): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Reports one token: the category that owns it and the value it takes in
|
|
18
|
+
* every block that declares it.
|
|
19
|
+
*
|
|
20
|
+
* @param projectRoot - Root directory of the project
|
|
21
|
+
* @param tokenName - Custom-property name, with or without the leading `--`
|
|
22
|
+
* @param options - Output-mode options
|
|
23
|
+
*/
|
|
24
|
+
export declare function tokenShowCommand(projectRoot: string, tokenName: string, options?: {
|
|
25
|
+
json?: boolean;
|
|
26
|
+
}): Promise<void>;
|