@hominis/fireforge 0.49.2 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -1
- package/README.md +1 -1
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/build-prelock.d.ts +20 -0
- package/dist/src/commands/build-prelock.js +50 -0
- package/dist/src/commands/build.d.ts +3 -1
- package/dist/src/commands/build.js +13 -6
- package/dist/src/commands/check-report.d.ts +41 -0
- package/dist/src/commands/check-report.js +91 -0
- package/dist/src/commands/check-run.d.ts +33 -0
- package/dist/src/commands/check-run.js +112 -0
- package/dist/src/commands/check-steps.d.ts +75 -0
- package/dist/src/commands/check-steps.js +200 -0
- package/dist/src/commands/check.d.ts +32 -0
- package/dist/src/commands/check.js +160 -0
- package/dist/src/commands/config.js +5 -6
- package/dist/src/commands/declarations-report.d.ts +43 -0
- package/dist/src/commands/declarations-report.js +76 -0
- package/dist/src/commands/doctor-engine-eslint.js +6 -1
- package/dist/src/commands/doctor-source-pin.js +4 -1
- package/dist/src/commands/export-adopt-check.d.ts +38 -0
- package/dist/src/commands/export-adopt-check.js +98 -0
- package/dist/src/commands/export-flow.js +29 -14
- package/dist/src/commands/export-placement-gate.d.ts +6 -2
- package/dist/src/commands/export-placement-gate.js +8 -0
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-staged-registration.d.ts +46 -0
- package/dist/src/commands/export-staged-registration.js +91 -0
- package/dist/src/commands/forward-import-remedy.d.ts +32 -0
- package/dist/src/commands/forward-import-remedy.js +63 -0
- package/dist/src/commands/furnace/apply.js +3 -3
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc.js +2 -2
- package/dist/src/commands/furnace/create.js +2 -2
- package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
- package/dist/src/commands/furnace/deploy-named.js +107 -0
- package/dist/src/commands/furnace/deploy.d.ts +3 -2
- package/dist/src/commands/furnace/deploy.js +50 -86
- package/dist/src/commands/furnace/diff.js +26 -3
- package/dist/src/commands/furnace/index.js +66 -41
- package/dist/src/commands/furnace/init.js +13 -6
- package/dist/src/commands/furnace/override.js +4 -2
- package/dist/src/commands/furnace/preview.js +4 -3
- package/dist/src/commands/furnace/refresh.js +2 -2
- package/dist/src/commands/furnace/remove.js +4 -3
- package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
- package/dist/src/commands/furnace/rename-dry-run.js +127 -0
- package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
- package/dist/src/commands/furnace/rename-helpers.js +15 -1
- package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
- package/dist/src/commands/furnace/rename-registrations.js +98 -0
- package/dist/src/commands/furnace/rename.d.ts +2 -1
- package/dist/src/commands/furnace/rename.js +28 -66
- package/dist/src/commands/furnace/scan.d.ts +9 -4
- package/dist/src/commands/furnace/scan.js +11 -9
- package/dist/src/commands/furnace/sync.js +3 -2
- package/dist/src/commands/furnace/validate-report.d.ts +45 -0
- package/dist/src/commands/furnace/validate-report.js +91 -0
- package/dist/src/commands/furnace/validate.d.ts +1 -1
- package/dist/src/commands/furnace/validate.js +151 -113
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +36 -61
- package/dist/src/commands/lint-per-run-checkjs.js +2 -2
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +20 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +4 -0
- package/dist/src/commands/park.d.ts +22 -0
- package/dist/src/commands/park.js +232 -0
- package/dist/src/commands/patch/delete-gap-notice.js +3 -1
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +24 -104
- package/dist/src/commands/patch/index.d.ts +3 -3
- package/dist/src/commands/patch/index.js +10 -4
- package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
- package/dist/src/commands/patch/lint-ignore-from.js +142 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +78 -31
- package/dist/src/commands/patch/move-files-create.js +34 -18
- package/dist/src/commands/patch/move-files-into.js +15 -7
- package/dist/src/commands/patch/move-files.js +6 -2
- package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
- package/dist/src/commands/patch/removal-created-files.js +83 -0
- package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
- package/dist/src/commands/patch/removal-dependents.js +133 -0
- package/dist/src/commands/patch/rename.js +20 -1
- package/dist/src/commands/patch/reserve.d.ts +33 -0
- package/dist/src/commands/patch/reserve.js +152 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +133 -0
- package/dist/src/commands/patch/split-plan.d.ts +17 -8
- package/dist/src/commands/patch/split-plan.js +60 -28
- package/dist/src/commands/patch/split-staged.d.ts +108 -0
- package/dist/src/commands/patch/split-staged.js +202 -0
- package/dist/src/commands/patch/split.d.ts +5 -0
- package/dist/src/commands/patch/split.js +62 -17
- package/dist/src/commands/patch/stage.d.ts +34 -0
- package/dist/src/commands/patch/stage.js +153 -0
- package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
- package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
- package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
- package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
- package/dist/src/commands/patch/staged-dependency-from.js +108 -0
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
- package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
- package/dist/src/commands/patch/staged-dependency.js +54 -139
- package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
- package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
- package/dist/src/commands/re-export-adjacent.d.ts +50 -2
- package/dist/src/commands/re-export-adjacent.js +160 -40
- package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
- package/dist/src/commands/re-export-bulk-scan.js +22 -7
- package/dist/src/commands/re-export-drift.d.ts +36 -8
- package/dist/src/commands/re-export-drift.js +73 -49
- package/dist/src/commands/re-export-files.js +11 -8
- package/dist/src/commands/re-export-hunks.d.ts +35 -0
- package/dist/src/commands/re-export-hunks.js +220 -0
- package/dist/src/commands/re-export-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +74 -6
- package/dist/src/commands/re-export-preflight.d.ts +23 -0
- package/dist/src/commands/re-export-preflight.js +160 -0
- package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
- package/dist/src/commands/re-export-purity-scope.js +131 -0
- package/dist/src/commands/re-export-register.js +56 -17
- package/dist/src/commands/re-export-removed.d.ts +13 -2
- package/dist/src/commands/re-export-removed.js +57 -12
- package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
- package/dist/src/commands/re-export-scan-owner.js +116 -0
- package/dist/src/commands/re-export-scan.d.ts +19 -9
- package/dist/src/commands/re-export-scan.js +60 -24
- package/dist/src/commands/re-export-single.js +122 -46
- package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
- package/dist/src/commands/re-export-stale-registrations.js +62 -0
- package/dist/src/commands/re-export-summary.d.ts +28 -0
- package/dist/src/commands/re-export-summary.js +36 -0
- package/dist/src/commands/re-export.js +71 -57
- package/dist/src/commands/rebase/index.js +17 -17
- package/dist/src/commands/run.js +16 -2
- package/dist/src/commands/status-check.d.ts +55 -16
- package/dist/src/commands/status-check.js +92 -37
- package/dist/src/commands/status-json.d.ts +22 -9
- package/dist/src/commands/status-json.js +47 -32
- package/dist/src/commands/status-output.js +3 -1
- package/dist/src/commands/status-scope.d.ts +37 -0
- package/dist/src/commands/status-scope.js +54 -0
- package/dist/src/commands/status.js +66 -23
- package/dist/src/commands/test-browser-preflight.js +19 -3
- package/dist/src/commands/test-build-furnace.d.ts +22 -0
- package/dist/src/commands/test-build-furnace.js +54 -0
- package/dist/src/commands/test-build-phase.js +64 -41
- package/dist/src/commands/test-checkjs.js +10 -2
- package/dist/src/commands/test-diagnose.js +7 -0
- package/dist/src/commands/test-dispatch.d.ts +39 -0
- package/dist/src/commands/test-dispatch.js +211 -0
- package/dist/src/commands/test-furnace-reach.d.ts +37 -0
- package/dist/src/commands/test-furnace-reach.js +132 -0
- package/dist/src/commands/test-modes.d.ts +16 -1
- package/dist/src/commands/test-modes.js +24 -1
- package/dist/src/commands/test-multi-verdict.d.ts +61 -0
- package/dist/src/commands/test-multi-verdict.js +111 -0
- package/dist/src/commands/test-orchestrate.d.ts +52 -0
- package/dist/src/commands/test-orchestrate.js +240 -0
- package/dist/src/commands/test-perf-scope.d.ts +50 -0
- package/dist/src/commands/test-perf-scope.js +138 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +273 -0
- package/dist/src/commands/test-register.js +69 -10
- package/dist/src/commands/test-results.d.ts +62 -0
- package/dist/src/commands/test-results.js +62 -0
- package/dist/src/commands/test-run.d.ts +13 -55
- package/dist/src/commands/test-run.js +74 -99
- package/dist/src/commands/test-shards.d.ts +110 -0
- package/dist/src/commands/test-shards.js +255 -0
- package/dist/src/commands/test-stale-gate.d.ts +5 -1
- package/dist/src/commands/test-stale-gate.js +60 -28
- package/dist/src/commands/test-verdict.d.ts +11 -1
- package/dist/src/commands/test-verdict.js +28 -1
- package/dist/src/commands/test.d.ts +6 -1
- package/dist/src/commands/test.js +120 -124
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +151 -0
- package/dist/src/commands/token.js +10 -0
- package/dist/src/commands/verify-scope.d.ts +28 -0
- package/dist/src/commands/verify-scope.js +67 -0
- package/dist/src/commands/verify.d.ts +10 -2
- package/dist/src/commands/verify.js +67 -36
- package/dist/src/core/build-baseline-types.d.ts +46 -0
- package/dist/src/core/build-baseline-validate.js +19 -0
- package/dist/src/core/build-baseline.d.ts +5 -1
- package/dist/src/core/build-baseline.js +3 -1
- package/dist/src/core/build-overwrite-guard.d.ts +50 -0
- package/dist/src/core/build-overwrite-guard.js +84 -4
- package/dist/src/core/build-prepare.d.ts +13 -0
- package/dist/src/core/build-prepare.js +42 -10
- package/dist/src/core/build-run-record.d.ts +74 -0
- package/dist/src/core/build-run-record.js +136 -0
- package/dist/src/core/checkjs-support-heads.d.ts +41 -0
- package/dist/src/core/checkjs-support-heads.js +104 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +10 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +219 -0
- package/dist/src/core/config-validate-file-size.d.ts +9 -6
- package/dist/src/core/config-validate-file-size.js +91 -2
- package/dist/src/core/config-validate-history.d.ts +11 -0
- package/dist/src/core/config-validate-history.js +38 -0
- package/dist/src/core/config-validate-patch-policy.js +100 -0
- package/dist/src/core/config-validate-test-toolchains.js +21 -0
- package/dist/src/core/config-validate-token-scales.d.ts +9 -0
- package/dist/src/core/config-validate-token-scales.js +92 -0
- package/dist/src/core/config-validate.js +20 -5
- package/dist/src/core/config.d.ts +5 -0
- package/dist/src/core/config.js +16 -0
- package/dist/src/core/coverage-dispatch.d.ts +24 -0
- package/dist/src/core/coverage-dispatch.js +44 -0
- package/dist/src/core/coverage-extend.d.ts +70 -45
- package/dist/src/core/coverage-extend.js +199 -144
- package/dist/src/core/coverage-records.d.ts +108 -0
- package/dist/src/core/coverage-records.js +384 -0
- package/dist/src/core/destructive.d.ts +7 -4
- package/dist/src/core/destructive.js +10 -10
- package/dist/src/core/engine-session-lock.d.ts +16 -1
- package/dist/src/core/engine-session-lock.js +38 -10
- package/dist/src/core/export-moved-code-shape.d.ts +49 -11
- package/dist/src/core/export-moved-code-shape.js +135 -44
- package/dist/src/core/file-lock-queue.d.ts +67 -0
- package/dist/src/core/file-lock-queue.js +221 -0
- package/dist/src/core/file-lock-shared.d.ts +57 -0
- package/dist/src/core/file-lock-shared.js +117 -0
- package/dist/src/core/file-lock.d.ts +13 -25
- package/dist/src/core/file-lock.js +163 -140
- package/dist/src/core/furnace-apply-output.d.ts +10 -0
- package/dist/src/core/furnace-apply-output.js +31 -1
- package/dist/src/core/furnace-apply.js +22 -12
- package/dist/src/core/furnace-composed-source.d.ts +76 -0
- package/dist/src/core/furnace-composed-source.js +167 -0
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +16 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +102 -0
- package/dist/src/core/furnace-config-validate.js +14 -0
- package/dist/src/core/furnace-css-fragments.d.ts +10 -0
- package/dist/src/core/furnace-css-fragments.js +26 -0
- package/dist/src/core/furnace-operation.d.ts +3 -3
- package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
- package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
- package/dist/src/core/furnace-registration-remove.d.ts +22 -1
- package/dist/src/core/furnace-registration-remove.js +53 -17
- package/dist/src/core/furnace-registration-rename.d.ts +26 -0
- package/dist/src/core/furnace-registration-rename.js +77 -0
- package/dist/src/core/furnace-registration.d.ts +14 -4
- package/dist/src/core/furnace-registration.js +44 -10
- package/dist/src/core/furnace-staleness.d.ts +7 -0
- package/dist/src/core/furnace-staleness.js +34 -24
- package/dist/src/core/furnace-validate-accessibility.d.ts +8 -4
- package/dist/src/core/furnace-validate-accessibility.js +71 -28
- package/dist/src/core/furnace-validate-exceptions.d.ts +48 -0
- package/dist/src/core/furnace-validate-exceptions.js +80 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +78 -0
- package/dist/src/core/furnace-validate.js +1 -1
- package/dist/src/core/harness-port-fallback.d.ts +60 -0
- package/dist/src/core/harness-port-fallback.js +96 -0
- package/dist/src/core/history-log-file.d.ts +61 -0
- package/dist/src/core/history-log-file.js +164 -0
- package/dist/src/core/history-log.d.ts +2 -1
- package/dist/src/core/history-log.js +2 -1
- package/dist/src/core/json-preserving-edit.d.ts +22 -0
- package/dist/src/core/json-preserving-edit.js +199 -0
- package/dist/src/core/line-prefixer.d.ts +18 -0
- package/dist/src/core/line-prefixer.js +34 -0
- package/dist/src/core/mach.d.ts +7 -0
- package/dist/src/core/mach.js +32 -10
- package/dist/src/core/module-resolution-preflight.d.ts +19 -3
- package/dist/src/core/module-resolution-preflight.js +24 -6
- package/dist/src/core/negative-control-compiled.d.ts +27 -0
- package/dist/src/core/negative-control-compiled.js +73 -0
- package/dist/src/core/negative-control-diff.d.ts +51 -0
- package/dist/src/core/negative-control-diff.js +179 -0
- package/dist/src/core/negative-control.d.ts +150 -0
- package/dist/src/core/negative-control.js +399 -0
- package/dist/src/core/objdir-install-manifests.d.ts +73 -0
- package/dist/src/core/objdir-install-manifests.js +226 -0
- package/dist/src/core/park-store.d.ts +63 -0
- package/dist/src/core/park-store.js +216 -0
- package/dist/src/core/patch-export-update.d.ts +6 -0
- package/dist/src/core/patch-export-update.js +13 -3
- package/dist/src/core/patch-export.d.ts +3 -2
- package/dist/src/core/patch-export.js +22 -16
- package/dist/src/core/patch-files.js +26 -8
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +39 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +63 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
- package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
- package/dist/src/core/patch-lint-checkjs.js +20 -13
- package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
- package/dist/src/core/patch-lint-code-lines.js +105 -0
- package/dist/src/core/patch-lint-cross.d.ts +3 -1
- package/dist/src/core/patch-lint-cross.js +17 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +24 -14
- package/dist/src/core/patch-lint-file-size.d.ts +12 -5
- package/dist/src/core/patch-lint-file-size.js +22 -11
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +23 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +36 -11
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +196 -0
- package/dist/src/core/patch-lint-ignore.js +429 -0
- package/dist/src/core/patch-lint-ownership.d.ts +10 -0
- package/dist/src/core/patch-lint-ownership.js +26 -0
- package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
- package/dist/src/core/patch-lint-size-thresholds.js +110 -0
- package/dist/src/core/patch-lint-size.d.ts +117 -0
- package/dist/src/core/patch-lint-size.js +331 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
- package/dist/src/core/patch-lint-staged-registration.js +20 -0
- package/dist/src/core/patch-lint-token-scale.d.ts +57 -0
- package/dist/src/core/patch-lint-token-scale.js +286 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +66 -288
- package/dist/src/core/patch-lock.js +7 -6
- package/dist/src/core/patch-manifest-consistency.js +7 -6
- package/dist/src/core/patch-manifest-io.d.ts +6 -3
- package/dist/src/core/patch-manifest-io.js +27 -9
- package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
- package/dist/src/core/patch-manifest-key-order.js +61 -0
- package/dist/src/core/patch-manifest-stage.d.ts +46 -0
- package/dist/src/core/patch-manifest-stage.js +96 -0
- package/dist/src/core/patch-manifest-validate.js +61 -3
- package/dist/src/core/patch-order-legal.d.ts +26 -0
- package/dist/src/core/patch-order-legal.js +88 -0
- package/dist/src/core/patch-policy-content.d.ts +40 -0
- package/dist/src/core/patch-policy-content.js +216 -0
- package/dist/src/core/patch-policy.d.ts +22 -5
- package/dist/src/core/patch-policy.js +26 -12
- package/dist/src/core/patch-retired.d.ts +57 -0
- package/dist/src/core/patch-retired.js +92 -0
- package/dist/src/core/patch-subset.d.ts +16 -0
- package/dist/src/core/patch-subset.js +66 -0
- package/dist/src/core/preflight-wait.d.ts +20 -0
- package/dist/src/core/preflight-wait.js +38 -0
- package/dist/src/core/rebase-from-version.d.ts +46 -0
- package/dist/src/core/rebase-from-version.js +71 -0
- package/dist/src/core/run-log.d.ts +26 -0
- package/dist/src/core/run-log.js +106 -4
- package/dist/src/core/run-profile.d.ts +7 -0
- package/dist/src/core/run-profile.js +7 -1
- package/dist/src/core/smoke-patterns.d.ts +5 -0
- package/dist/src/core/smoke-patterns.js +13 -0
- package/dist/src/core/test-harness-crash.d.ts +19 -1
- package/dist/src/core/test-harness-crash.js +8 -9
- package/dist/src/core/test-harness-signature.d.ts +33 -0
- package/dist/src/core/test-harness-signature.js +23 -1
- package/dist/src/core/test-raw-log.d.ts +66 -0
- package/dist/src/core/test-raw-log.js +122 -0
- package/dist/src/core/test-run-completeness.d.ts +90 -0
- package/dist/src/core/test-run-completeness.js +184 -0
- package/dist/src/core/test-stale-check.d.ts +27 -1
- package/dist/src/core/test-stale-check.js +39 -49
- package/dist/src/core/test-stale-exempt.d.ts +40 -0
- package/dist/src/core/test-stale-exempt.js +70 -0
- package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
- package/dist/src/core/test-xpcshell-retry.js +2 -1
- package/dist/src/core/token-lint.d.ts +53 -0
- package/dist/src/core/token-lint.js +131 -0
- package/dist/src/core/token-sibling-sheets.d.ts +46 -0
- package/dist/src/core/token-sibling-sheets.js +119 -0
- package/dist/src/core/tree-guard.js +5 -0
- package/dist/src/core/typecheck-shim.d.ts +6 -2
- package/dist/src/core/typecheck-shim.js +205 -4
- package/dist/src/core/typecheck.js +3 -1
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +6 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +212 -24
- package/dist/src/types/commands/patches.d.ts +118 -1
- package/dist/src/types/config.d.ts +264 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +63 -1
- package/dist/src/types/furnace.js +7 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +36 -7
- package/dist/src/utils/options.js +94 -8
- package/dist/src/utils/path-glob.d.ts +15 -0
- package/dist/src/utils/path-glob.js +47 -0
- package/dist/src/utils/regex.d.ts +15 -3
- package/dist/src/utils/regex.js +37 -16
- package/docs/configuration.md +369 -11
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +139 -3
- package/docs/lifecycle-invariants.md +65 -30
- package/docs/machine-output.md +120 -12
- package/docs/patch-workflow.md +458 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +346 -21
- package/package.json +3 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Unowned support heads for the named-file checkJs pass of `test --build`.
|
|
4
|
+
*
|
|
5
|
+
* Each named test is checked as its own program: the test plus the
|
|
6
|
+
* patch-owned `head*.js` beside it. A suite moved onto a NEW support head
|
|
7
|
+
* (`head_world_page.js`, loaded with `loadSubScript`) cannot be proven
|
|
8
|
+
* before that head is exported, because the head is in no patch: every kit
|
|
9
|
+
* name reads as "Cannot find name" and the run is refused at preflight,
|
|
10
|
+
* with the generic hint, which offers the shim as a remedy.
|
|
11
|
+
*
|
|
12
|
+
* So an unowned same-directory `head*.js` joins the pass when a named test
|
|
13
|
+
* loads it with `loadSubScript` or a manifest beside it lists it in
|
|
14
|
+
* `support-files`, which are the two ways the harness itself would bring
|
|
15
|
+
* it into the test's scope. The operator is told it is unowned and how to
|
|
16
|
+
* adopt it, as for the `head.js` companions in
|
|
17
|
+
* `patch-lint-unmanaged-companion.ts`.
|
|
18
|
+
*/
|
|
19
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { buildSupportFileMatcher, extractSupportFileEntries, } from './patch-lint-forward-registration.js';
|
|
22
|
+
import { findLoadSubScriptTargets } from './patch-lint-unmanaged-companion.js';
|
|
23
|
+
const HEAD_BASENAME_PATTERN = /^head(?:_.*)?\.js$/;
|
|
24
|
+
const TEST_MANIFEST_PATTERN = /^(?:xpcshell|mochitest|browser|chrome|a11y)\.(?:toml|ini)$/;
|
|
25
|
+
async function readOrUndefined(path) {
|
|
26
|
+
try {
|
|
27
|
+
return await readFile(path, 'utf8');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Why `head` is in scope for the named tests of its directory, if it is. */
|
|
34
|
+
async function findInclusionReason(engineDir, dir, head, context) {
|
|
35
|
+
const headName = head.slice(dir.length);
|
|
36
|
+
for (const test of context.tests) {
|
|
37
|
+
const source = await readOrUndefined(join(engineDir, test));
|
|
38
|
+
if (source === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
const loads = findLoadSubScriptTargets(source).some((target) => target.slice(target.lastIndexOf('/') + 1) === headName);
|
|
41
|
+
if (loads)
|
|
42
|
+
return `${test} loads it with loadSubScript`;
|
|
43
|
+
}
|
|
44
|
+
for (const manifest of context.manifests) {
|
|
45
|
+
const source = await readOrUndefined(join(engineDir, manifest));
|
|
46
|
+
if (source === undefined)
|
|
47
|
+
continue;
|
|
48
|
+
const listed = extractSupportFileEntries(source).some(({ entry }) => buildSupportFileMatcher(manifest, entry)?.(head) === true);
|
|
49
|
+
if (listed)
|
|
50
|
+
return `${manifest} lists it in support-files`;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Finds the unowned same-directory `head*.js` files the named tests bring
|
|
56
|
+
* into scope.
|
|
57
|
+
*
|
|
58
|
+
* @param engineDir - Absolute engine directory
|
|
59
|
+
* @param selected - Engine-relative named test files
|
|
60
|
+
* @param owned - Every file the pass already includes
|
|
61
|
+
*/
|
|
62
|
+
export async function findUnownedSupportHeads(engineDir, selected, owned) {
|
|
63
|
+
const testsByDir = new Map();
|
|
64
|
+
for (const test of selected) {
|
|
65
|
+
const dir = test.slice(0, test.lastIndexOf('/') + 1);
|
|
66
|
+
testsByDir.set(dir, [...(testsByDir.get(dir) ?? []), test]);
|
|
67
|
+
}
|
|
68
|
+
const heads = [];
|
|
69
|
+
for (const [dir, tests] of testsByDir) {
|
|
70
|
+
let names;
|
|
71
|
+
try {
|
|
72
|
+
names = (await readdir(join(engineDir, dir))).sort();
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const manifests = names
|
|
78
|
+
.filter((name) => TEST_MANIFEST_PATTERN.test(name))
|
|
79
|
+
.map((name) => `${dir}${name}`);
|
|
80
|
+
const candidates = names
|
|
81
|
+
.filter((name) => HEAD_BASENAME_PATTERN.test(name))
|
|
82
|
+
.map((name) => `${dir}${name}`)
|
|
83
|
+
.filter((file) => !owned.has(file));
|
|
84
|
+
for (const file of candidates) {
|
|
85
|
+
const reason = await findInclusionReason(engineDir, dir, file, { tests, manifests });
|
|
86
|
+
if (reason !== undefined)
|
|
87
|
+
heads.push({ file, reason });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return heads;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The notice for an included unowned head: the ownership fact, the
|
|
94
|
+
* adoption command, and an explicit "not the shim", for the same reason
|
|
95
|
+
* `formatUnmanagedCompanionHint` gives.
|
|
96
|
+
*
|
|
97
|
+
* @param head - From {@link findUnownedSupportHeads}
|
|
98
|
+
*/
|
|
99
|
+
export function formatUnownedSupportHeadNotice(head) {
|
|
100
|
+
return (`${head.file} is in no patch yet; the pass includes it because ${head.reason}. ` +
|
|
101
|
+
`Adopt it with "fireforge re-export <patch> --scan --scan-file ${head.file}" before ` +
|
|
102
|
+
'export. Do NOT add its globals to the test shim: that would hide a genuinely missing ' +
|
|
103
|
+
'helper once the head is exported.');
|
|
104
|
+
}
|
|
@@ -5,9 +5,9 @@ import type { ProjectPaths } from '../types/config.js';
|
|
|
5
5
|
/** Name of the fireforge data directory */
|
|
6
6
|
export declare const FIREFORGE_DIR = ".fireforge";
|
|
7
7
|
/** Supported top-level fireforge.json keys backed by the current schema. */
|
|
8
|
-
export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "buildAudit", "test", "externalToolchains", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment"];
|
|
8
|
+
export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "buildAudit", "test", "history", "externalToolchains", "license", "wire", "patchLint", "patchPolicy", "typecheck", "markerComment", "check"];
|
|
9
9
|
/** Supported config paths that can be read or set without --force. */
|
|
10
|
-
export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "firefox.candidate", "firefox.allowUnverifiedDownload", "build", "build.jobs", "test", "test.canaryPath", "test.canaryTimeoutSeconds", "test.reapOrphans", "externalToolchains", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.checkJsTestFiles", "patchLint.checkJsTestShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchLint.forwardRegistration", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment"];
|
|
10
|
+
export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "firefox.sha256", "firefox.candidate", "firefox.allowUnverifiedDownload", "build", "build.jobs", "test", "test.canaryPath", "test.canaryTimeoutSeconds", "test.reapOrphans", "test.mochitestPorts", "test.lockMode", "test.furnaceApply", "history", "history.path", "externalToolchains", "wire", "wire.subscriptDir", "patchLint", "patchLint.checkJs", "patchLint.checkJsStrict", "patchLint.checkJsCompilerOptions", "patchLint.checkJsExtraShim", "patchLint.checkJsTestFiles", "patchLint.checkJsTestShim", "patchLint.rawColorAllowlist", "patchLint.jsdocClassMethods", "patchLint.testAssertionFloor", "patchLint.chromeScriptJsDoc", "patchLint.forwardRegistration", "patchLint.fileSizeMetric", "patchLint.patchSizeMetric", "patchPolicy", "typecheck", "typecheck.projects", "typecheck.extraShim", "markerComment", "check"];
|
|
11
11
|
/**
|
|
12
12
|
* Gets all project paths based on a root directory.
|
|
13
13
|
* @param root - Root directory of the project
|
|
@@ -27,6 +27,7 @@ export const SUPPORTED_CONFIG_ROOT_KEYS = [
|
|
|
27
27
|
'build',
|
|
28
28
|
'buildAudit',
|
|
29
29
|
'test',
|
|
30
|
+
'history',
|
|
30
31
|
'externalToolchains',
|
|
31
32
|
'license',
|
|
32
33
|
'wire',
|
|
@@ -34,6 +35,7 @@ export const SUPPORTED_CONFIG_ROOT_KEYS = [
|
|
|
34
35
|
'patchPolicy',
|
|
35
36
|
'typecheck',
|
|
36
37
|
'markerComment',
|
|
38
|
+
'check',
|
|
37
39
|
];
|
|
38
40
|
/** Supported config paths that can be read or set without --force. */
|
|
39
41
|
export const SUPPORTED_CONFIG_PATHS = [
|
|
@@ -54,6 +56,11 @@ export const SUPPORTED_CONFIG_PATHS = [
|
|
|
54
56
|
'test.canaryPath',
|
|
55
57
|
'test.canaryTimeoutSeconds',
|
|
56
58
|
'test.reapOrphans',
|
|
59
|
+
'test.mochitestPorts',
|
|
60
|
+
'test.lockMode',
|
|
61
|
+
'test.furnaceApply',
|
|
62
|
+
'history',
|
|
63
|
+
'history.path',
|
|
57
64
|
'externalToolchains',
|
|
58
65
|
'wire',
|
|
59
66
|
'wire.subscriptDir',
|
|
@@ -69,11 +76,14 @@ export const SUPPORTED_CONFIG_PATHS = [
|
|
|
69
76
|
'patchLint.testAssertionFloor',
|
|
70
77
|
'patchLint.chromeScriptJsDoc',
|
|
71
78
|
'patchLint.forwardRegistration',
|
|
79
|
+
'patchLint.fileSizeMetric',
|
|
80
|
+
'patchLint.patchSizeMetric',
|
|
72
81
|
'patchPolicy',
|
|
73
82
|
'typecheck',
|
|
74
83
|
'typecheck.projects',
|
|
75
84
|
'typecheck.extraShim',
|
|
76
85
|
'markerComment',
|
|
86
|
+
'check',
|
|
77
87
|
];
|
|
78
88
|
/**
|
|
79
89
|
* Gets all project paths based on a root directory.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Validation for the `check` block (`fireforge check`).
|
|
4
|
+
*
|
|
5
|
+
* Split out of `config-validate.ts`, which is at its per-file line budget,
|
|
6
|
+
* following the `config-validate-build-audit.ts` precedent. Unknown keys are
|
|
7
|
+
* refused: a misspelt `extraSteps` would otherwise drop a project audit from
|
|
8
|
+
* the gate without a word.
|
|
9
|
+
*/
|
|
10
|
+
import { ConfigError } from '../errors/config.js';
|
|
11
|
+
import { CHECK_BUILTIN_STEPS, } from '../types/config.js';
|
|
12
|
+
import { isContainedRelativePath } from '../utils/paths.js';
|
|
13
|
+
import { isObject } from '../utils/validation.js';
|
|
14
|
+
const STEP_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
15
|
+
function assertKnownKeys(raw, field, known) {
|
|
16
|
+
for (const key of Object.keys(raw)) {
|
|
17
|
+
if (!known.includes(key)) {
|
|
18
|
+
throw new ConfigError(`Config field "${field}" has unknown key "${key}"`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function parseStringList(raw, field) {
|
|
23
|
+
if (!Array.isArray(raw) || raw.some((entry) => typeof entry !== 'string' || entry === '')) {
|
|
24
|
+
throw new ConfigError(`Config field "${field}" must be an array of non-empty strings`);
|
|
25
|
+
}
|
|
26
|
+
return raw;
|
|
27
|
+
}
|
|
28
|
+
function parseNonNegativeInteger(raw, field) {
|
|
29
|
+
if (typeof raw !== 'number' || !Number.isInteger(raw) || raw < 0) {
|
|
30
|
+
throw new ConfigError(`Config field "${field}" must be a non-negative integer`);
|
|
31
|
+
}
|
|
32
|
+
return raw;
|
|
33
|
+
}
|
|
34
|
+
function isBuiltinStep(value) {
|
|
35
|
+
return CHECK_BUILTIN_STEPS.includes(value);
|
|
36
|
+
}
|
|
37
|
+
function parseSkip(raw) {
|
|
38
|
+
const skip = parseStringList(raw, 'check.skip');
|
|
39
|
+
for (const entry of skip) {
|
|
40
|
+
if (!isBuiltinStep(entry)) {
|
|
41
|
+
throw new ConfigError(`Config field "check.skip" names unknown step "${entry}". Valid: ${CHECK_BUILTIN_STEPS.join(', ')}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return skip;
|
|
45
|
+
}
|
|
46
|
+
function parseStatusPolicy(raw) {
|
|
47
|
+
if (!isObject(raw))
|
|
48
|
+
throw new ConfigError('Config field "check.status" must be a plain object');
|
|
49
|
+
assertKnownKeys(raw, 'check.status', ['failOn', 'allow', 'failOnUnknown']);
|
|
50
|
+
const out = {};
|
|
51
|
+
if (raw['failOn'] !== undefined)
|
|
52
|
+
out.failOn = parseStringList(raw['failOn'], 'check.status.failOn');
|
|
53
|
+
if (raw['allow'] !== undefined)
|
|
54
|
+
out.allow = parseStringList(raw['allow'], 'check.status.allow');
|
|
55
|
+
if (raw['failOnUnknown'] !== undefined) {
|
|
56
|
+
if (typeof raw['failOnUnknown'] !== 'boolean') {
|
|
57
|
+
throw new ConfigError('Config field "check.status.failOnUnknown" must be a boolean');
|
|
58
|
+
}
|
|
59
|
+
out.failOnUnknown = raw['failOnUnknown'];
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
function parseMaxWarnings(raw) {
|
|
64
|
+
if (!isObject(raw)) {
|
|
65
|
+
throw new ConfigError('Config field "check.maxWarnings" must be a plain object');
|
|
66
|
+
}
|
|
67
|
+
assertKnownKeys(raw, 'check.maxWarnings', ['lint', 'furnace']);
|
|
68
|
+
const out = {};
|
|
69
|
+
if (raw['lint'] !== undefined) {
|
|
70
|
+
out.lint = parseNonNegativeInteger(raw['lint'], 'check.maxWarnings.lint');
|
|
71
|
+
}
|
|
72
|
+
if (raw['furnace'] !== undefined) {
|
|
73
|
+
out.furnace = parseNonNegativeInteger(raw['furnace'], 'check.maxWarnings.furnace');
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function parseExtraStep(raw, field) {
|
|
78
|
+
if (!isObject(raw)) {
|
|
79
|
+
throw new ConfigError(`Config field "${field}" must be a plain object with "name" and "command"`);
|
|
80
|
+
}
|
|
81
|
+
assertKnownKeys(raw, field, ['name', 'command', 'cwd', 'timeout', 'after']);
|
|
82
|
+
const name = raw['name'];
|
|
83
|
+
if (typeof name !== 'string' || !STEP_NAME_PATTERN.test(name)) {
|
|
84
|
+
throw new ConfigError(`Config field "${field}.name" must be lowercase letters, digits and dashes (e.g. "policy-audit")`);
|
|
85
|
+
}
|
|
86
|
+
if (isBuiltinStep(name)) {
|
|
87
|
+
throw new ConfigError(`Config field "${field}.name" "${name}" is a built-in step name`);
|
|
88
|
+
}
|
|
89
|
+
const command = raw['command'];
|
|
90
|
+
if (typeof command !== 'string' || command.trim() === '') {
|
|
91
|
+
throw new ConfigError(`Config field "${field}.command" must be a non-empty string`);
|
|
92
|
+
}
|
|
93
|
+
const step = { name, command };
|
|
94
|
+
if (raw['cwd'] !== undefined) {
|
|
95
|
+
const cwd = raw['cwd'];
|
|
96
|
+
if (typeof cwd !== 'string' || cwd.trim() === '' || !isContainedRelativePath(cwd)) {
|
|
97
|
+
throw new ConfigError(`Config field "${field}.cwd" must be a project-relative path`);
|
|
98
|
+
}
|
|
99
|
+
step.cwd = cwd;
|
|
100
|
+
}
|
|
101
|
+
if (raw['timeout'] !== undefined) {
|
|
102
|
+
step.timeout = parsePositiveSeconds(raw['timeout'], `${field}.timeout`);
|
|
103
|
+
}
|
|
104
|
+
if (raw['after'] !== undefined)
|
|
105
|
+
step.after = parseStringList(raw['after'], `${field}.after`);
|
|
106
|
+
return step;
|
|
107
|
+
}
|
|
108
|
+
function parsePositiveSeconds(raw, field) {
|
|
109
|
+
const seconds = parseNonNegativeInteger(raw, field);
|
|
110
|
+
if (seconds === 0) {
|
|
111
|
+
throw new ConfigError(`Config field "${field}" must be a positive number of seconds`);
|
|
112
|
+
}
|
|
113
|
+
return seconds;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Checks every `after` names a known step and the extra steps' ordering
|
|
117
|
+
* has no cycle: a cycle would leave its steps waiting forever.
|
|
118
|
+
*/
|
|
119
|
+
function assertExtraStepOrdering(steps) {
|
|
120
|
+
const extras = new Map(steps.map((step) => [step.name, step]));
|
|
121
|
+
for (const [index, step] of steps.entries()) {
|
|
122
|
+
for (const dependency of step.after ?? []) {
|
|
123
|
+
if (dependency === step.name) {
|
|
124
|
+
throw new ConfigError(`Config field "check.extraSteps[${String(index)}].after" names the step itself`);
|
|
125
|
+
}
|
|
126
|
+
if (!isBuiltinStep(dependency) && !extras.has(dependency)) {
|
|
127
|
+
throw new ConfigError(`Config field "check.extraSteps[${String(index)}].after" names unknown step "${dependency}"`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const state = new Map();
|
|
132
|
+
const visit = (name, path) => {
|
|
133
|
+
if (state.get(name) === 'done')
|
|
134
|
+
return;
|
|
135
|
+
if (state.get(name) === 'visiting') {
|
|
136
|
+
throw new ConfigError(`Config field "check.extraSteps" orders its steps in a cycle: ${[...path, name].join(' -> ')}`);
|
|
137
|
+
}
|
|
138
|
+
state.set(name, 'visiting');
|
|
139
|
+
for (const dependency of extras.get(name)?.after ?? []) {
|
|
140
|
+
if (extras.has(dependency))
|
|
141
|
+
visit(dependency, [...path, name]);
|
|
142
|
+
}
|
|
143
|
+
state.set(name, 'done');
|
|
144
|
+
};
|
|
145
|
+
for (const step of steps)
|
|
146
|
+
visit(step.name, []);
|
|
147
|
+
}
|
|
148
|
+
function parseTimeouts(raw) {
|
|
149
|
+
if (!isObject(raw))
|
|
150
|
+
throw new ConfigError('Config field "check.timeouts" must be a plain object');
|
|
151
|
+
assertKnownKeys(raw, 'check.timeouts', [...CHECK_BUILTIN_STEPS]);
|
|
152
|
+
const out = {};
|
|
153
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
154
|
+
if (isBuiltinStep(name))
|
|
155
|
+
out[name] = parsePositiveSeconds(value, `check.timeouts.${name}`);
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
function parseExtraSteps(raw) {
|
|
160
|
+
if (!Array.isArray(raw))
|
|
161
|
+
throw new ConfigError('Config field "check.extraSteps" must be an array');
|
|
162
|
+
const steps = raw.map((entry, index) => parseExtraStep(entry, `check.extraSteps[${String(index)}]`));
|
|
163
|
+
const seen = new Set();
|
|
164
|
+
for (const step of steps) {
|
|
165
|
+
if (seen.has(step.name)) {
|
|
166
|
+
throw new ConfigError(`Config field "check.extraSteps" repeats the step name "${step.name}"`);
|
|
167
|
+
}
|
|
168
|
+
seen.add(step.name);
|
|
169
|
+
}
|
|
170
|
+
assertExtraStepOrdering(steps);
|
|
171
|
+
return steps;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Parses the `check` block.
|
|
175
|
+
*
|
|
176
|
+
* @param raw - The raw `check` value from fireforge.json
|
|
177
|
+
* @returns The validated block
|
|
178
|
+
*/
|
|
179
|
+
export function parseCheckConfig(raw) {
|
|
180
|
+
if (!isObject(raw))
|
|
181
|
+
throw new ConfigError('Config field "check" must be a plain object');
|
|
182
|
+
assertKnownKeys(raw, 'check', [
|
|
183
|
+
'skip',
|
|
184
|
+
'status',
|
|
185
|
+
'maxWarnings',
|
|
186
|
+
'extraSteps',
|
|
187
|
+
'timeout',
|
|
188
|
+
'timeouts',
|
|
189
|
+
'failOnSkipped',
|
|
190
|
+
'lintReport',
|
|
191
|
+
]);
|
|
192
|
+
const out = {};
|
|
193
|
+
if (raw['skip'] !== undefined)
|
|
194
|
+
out.skip = parseSkip(raw['skip']);
|
|
195
|
+
if (raw['status'] !== undefined)
|
|
196
|
+
out.status = parseStatusPolicy(raw['status']);
|
|
197
|
+
if (raw['maxWarnings'] !== undefined)
|
|
198
|
+
out.maxWarnings = parseMaxWarnings(raw['maxWarnings']);
|
|
199
|
+
if (raw['extraSteps'] !== undefined)
|
|
200
|
+
out.extraSteps = parseExtraSteps(raw['extraSteps']);
|
|
201
|
+
if (raw['timeout'] !== undefined)
|
|
202
|
+
out.timeout = parsePositiveSeconds(raw['timeout'], 'check.timeout');
|
|
203
|
+
if (raw['timeouts'] !== undefined)
|
|
204
|
+
out.timeouts = parseTimeouts(raw['timeouts']);
|
|
205
|
+
if (raw['failOnSkipped'] !== undefined) {
|
|
206
|
+
if (typeof raw['failOnSkipped'] !== 'boolean') {
|
|
207
|
+
throw new ConfigError('Config field "check.failOnSkipped" must be a boolean');
|
|
208
|
+
}
|
|
209
|
+
out.failOnSkipped = raw['failOnSkipped'];
|
|
210
|
+
}
|
|
211
|
+
if (raw['lintReport'] !== undefined) {
|
|
212
|
+
const path = raw['lintReport'];
|
|
213
|
+
if (typeof path !== 'string' || path.trim() === '' || !isContainedRelativePath(path)) {
|
|
214
|
+
throw new ConfigError('Config field "check.lintReport" must be a project-relative path');
|
|
215
|
+
}
|
|
216
|
+
out.lintReport = path;
|
|
217
|
+
}
|
|
218
|
+
return out;
|
|
219
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Validation for `patchLint
|
|
2
|
+
* Validation for the size-rule keys of `patchLint`: `fileSizeThresholds`,
|
|
3
|
+
* `fileSizeMetric`, `patchSizeThresholds`, `patchSizeMetric` and
|
|
4
|
+
* `patchSizeRegistrationFiles`.
|
|
3
5
|
*
|
|
4
6
|
* Split out of `config-validate.ts`, which is at its per-file line budget.
|
|
5
7
|
*/
|
|
6
|
-
import type {
|
|
8
|
+
import type { PatchLintConfig } from '../types/config.js';
|
|
7
9
|
/**
|
|
8
|
-
* Parses the `patchLint
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Parses every size-rule key of the `patchLint` block.
|
|
11
|
+
*
|
|
12
|
+
* @param read - Reads one raw `patchLint` field by key
|
|
13
|
+
* @returns The parsed fields, only those present
|
|
11
14
|
*/
|
|
12
|
-
export declare function
|
|
15
|
+
export declare function parsePatchLintSizeFields(read: (key: string) => unknown): Pick<PatchLintConfig, 'fileSizeThresholds' | 'fileSizeMetric' | 'patchSizeThresholds' | 'patchSizeMetric' | 'patchSizeRegistrationFiles'>;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* Validation for `patchLint
|
|
3
|
+
* Validation for the size-rule keys of `patchLint`: `fileSizeThresholds`,
|
|
4
|
+
* `fileSizeMetric`, `patchSizeThresholds`, `patchSizeMetric` and
|
|
5
|
+
* `patchSizeRegistrationFiles`.
|
|
4
6
|
*
|
|
5
7
|
* Split out of `config-validate.ts`, which is at its per-file line budget.
|
|
6
8
|
*/
|
|
7
9
|
import { ConfigError } from '../errors/config.js';
|
|
8
10
|
import { isObject } from '../utils/validation.js';
|
|
9
11
|
import { DEFAULT_FILE_SIZE_THRESHOLDS } from './patch-lint-file-size.js';
|
|
12
|
+
import { resolvePatchSizeThresholds, } from './patch-lint-size-thresholds.js';
|
|
10
13
|
/**
|
|
11
14
|
* Parses one `patchLint.fileSizeThresholds.<tier>` triple. Every field is
|
|
12
15
|
* optional and merges over the built-in default. Values must be positive
|
|
@@ -39,7 +42,7 @@ function parseFileSizeTier(raw, field) {
|
|
|
39
42
|
* against the merged triple (overrides on top of the defaults), so setting
|
|
40
43
|
* only `warning` cannot land below the default `notice`.
|
|
41
44
|
*/
|
|
42
|
-
|
|
45
|
+
function parsePatchLintFileSizeThresholds(raw) {
|
|
43
46
|
if (!isObject(raw)) {
|
|
44
47
|
throw new ConfigError('Config field "patchLint.fileSizeThresholds" must be a plain object');
|
|
45
48
|
}
|
|
@@ -63,3 +66,89 @@ export function parsePatchLintFileSizeThresholds(raw) {
|
|
|
63
66
|
}
|
|
64
67
|
return out;
|
|
65
68
|
}
|
|
69
|
+
/** Throws unless `merged` is ordered `notice <= warning <= error` (a `null` error is unbounded). */
|
|
70
|
+
function assertOrderedTriple(merged, field) {
|
|
71
|
+
if (merged.notice > merged.warning || (merged.error !== null && merged.warning > merged.error)) {
|
|
72
|
+
throw new ConfigError(`Config field "${field}" must satisfy notice <= warning <= error ` +
|
|
73
|
+
`(resolved: ${merged.notice}/${merged.warning}/${merged.error ?? 'none'})`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parses one `patchLint.patchSizeThresholds.<tier>` entry: optional
|
|
78
|
+
* `lines` and `files` triples, each validated against its merged result.
|
|
79
|
+
*/
|
|
80
|
+
function parsePatchSizeTier(raw, tier) {
|
|
81
|
+
const field = `patchLint.patchSizeThresholds.${tier}`;
|
|
82
|
+
if (!isObject(raw)) {
|
|
83
|
+
throw new ConfigError(`Config field "${field}" must be a plain object`);
|
|
84
|
+
}
|
|
85
|
+
const out = {};
|
|
86
|
+
for (const key of Object.keys(raw)) {
|
|
87
|
+
if (key !== 'lines' && key !== 'files') {
|
|
88
|
+
throw new ConfigError(`Config field "${field}" has unknown key "${key}"`);
|
|
89
|
+
}
|
|
90
|
+
out[key] = parseFileSizeTier(raw[key], `${field}.${key}`);
|
|
91
|
+
}
|
|
92
|
+
const merged = resolvePatchSizeThresholds(tier, { [tier]: out });
|
|
93
|
+
assertOrderedTriple(merged.lines, `${field}.lines`);
|
|
94
|
+
assertOrderedTriple(merged.files, `${field}.files`);
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
/** Parses the `patchLint.patchSizeThresholds` block. */
|
|
98
|
+
function parsePatchLintPatchSizeThresholds(raw) {
|
|
99
|
+
if (!isObject(raw)) {
|
|
100
|
+
throw new ConfigError('Config field "patchLint.patchSizeThresholds" must be a plain object');
|
|
101
|
+
}
|
|
102
|
+
const out = {};
|
|
103
|
+
for (const key of Object.keys(raw)) {
|
|
104
|
+
if (key !== 'general' && key !== 'test' && key !== 'branding') {
|
|
105
|
+
throw new ConfigError(`Config field "patchLint.patchSizeThresholds" has unknown key "${key}"`);
|
|
106
|
+
}
|
|
107
|
+
out[key] = parsePatchSizeTier(raw[key], key);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
/** Parses an enum-valued `patchLint` key, naming the allowed values on failure. */
|
|
112
|
+
function parseEnum(raw, field, values) {
|
|
113
|
+
if (typeof raw !== 'string' || !values.includes(raw)) {
|
|
114
|
+
throw new ConfigError(`Config field "${field}" must be one of: ${values.join(', ')}`);
|
|
115
|
+
}
|
|
116
|
+
return raw;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Parses every size-rule key of the `patchLint` block.
|
|
120
|
+
*
|
|
121
|
+
* @param read - Reads one raw `patchLint` field by key
|
|
122
|
+
* @returns The parsed fields, only those present
|
|
123
|
+
*/
|
|
124
|
+
export function parsePatchLintSizeFields(read) {
|
|
125
|
+
const out = {};
|
|
126
|
+
const fileSizeThresholds = read('fileSizeThresholds');
|
|
127
|
+
if (fileSizeThresholds !== undefined) {
|
|
128
|
+
out.fileSizeThresholds = parsePatchLintFileSizeThresholds(fileSizeThresholds);
|
|
129
|
+
}
|
|
130
|
+
const fileSizeMetric = read('fileSizeMetric');
|
|
131
|
+
if (fileSizeMetric !== undefined) {
|
|
132
|
+
out.fileSizeMetric = parseEnum(fileSizeMetric, 'patchLint.fileSizeMetric', ['raw', 'code']);
|
|
133
|
+
}
|
|
134
|
+
const patchSizeThresholds = read('patchSizeThresholds');
|
|
135
|
+
if (patchSizeThresholds !== undefined) {
|
|
136
|
+
out.patchSizeThresholds = parsePatchLintPatchSizeThresholds(patchSizeThresholds);
|
|
137
|
+
}
|
|
138
|
+
const patchSizeMetric = read('patchSizeMetric');
|
|
139
|
+
if (patchSizeMetric !== undefined) {
|
|
140
|
+
out.patchSizeMetric = parseEnum(patchSizeMetric, 'patchLint.patchSizeMetric', [
|
|
141
|
+
'diff',
|
|
142
|
+
'addedCode',
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
const registration = read('patchSizeRegistrationFiles');
|
|
146
|
+
if (registration !== undefined) {
|
|
147
|
+
if (!Array.isArray(registration) ||
|
|
148
|
+
registration.some((v) => typeof v !== 'string' || v.trim() === '')) {
|
|
149
|
+
throw new ConfigError('Config field "patchLint.patchSizeRegistrationFiles" must be an array of non-empty strings');
|
|
150
|
+
}
|
|
151
|
+
out.patchSizeRegistrationFiles = registration;
|
|
152
|
+
}
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FireForgeConfig } from '../types/config.js';
|
|
2
|
+
import type { ParsedRecord } from '../utils/parse.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whether a `history.path` value is usable: a non-empty, project-relative
|
|
5
|
+
* path that stays inside the project and names a file, not the root.
|
|
6
|
+
* Shared with the history writer, which reads the raw config and must agree
|
|
7
|
+
* with validation about what it may write to.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isValidHistoryPath(value: unknown): value is string;
|
|
10
|
+
/** Parses the optional `history` block. */
|
|
11
|
+
export declare function parseHistoryBlock(rec: ParsedRecord, config: FireForgeConfig): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { ConfigError } from '../errors/config.js';
|
|
3
|
+
import { isContainedRelativePath } from '../utils/paths.js';
|
|
4
|
+
/**
|
|
5
|
+
* Whether a `history.path` value is usable: a non-empty, project-relative
|
|
6
|
+
* path that stays inside the project and names a file, not the root.
|
|
7
|
+
* Shared with the history writer, which reads the raw config and must agree
|
|
8
|
+
* with validation about what it may write to.
|
|
9
|
+
*/
|
|
10
|
+
export function isValidHistoryPath(value) {
|
|
11
|
+
return (typeof value === 'string' &&
|
|
12
|
+
value.trim() !== '' &&
|
|
13
|
+
value.trim() !== '.' &&
|
|
14
|
+
!/[\n\r]/.test(value) &&
|
|
15
|
+
isContainedRelativePath(value));
|
|
16
|
+
}
|
|
17
|
+
/** Parses the optional `history` block. */
|
|
18
|
+
export function parseHistoryBlock(rec, config) {
|
|
19
|
+
const raw = rec.raw('history');
|
|
20
|
+
if (raw === undefined)
|
|
21
|
+
return;
|
|
22
|
+
let historyRec;
|
|
23
|
+
try {
|
|
24
|
+
historyRec = rec.object('history');
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new ConfigError('Config field "history" must be an object');
|
|
28
|
+
}
|
|
29
|
+
const out = {};
|
|
30
|
+
const path = historyRec.raw('path');
|
|
31
|
+
if (path !== undefined) {
|
|
32
|
+
if (!isValidHistoryPath(path)) {
|
|
33
|
+
throw new ConfigError('Config field "history.path" must be a project-relative file path inside the project');
|
|
34
|
+
}
|
|
35
|
+
out.path = path;
|
|
36
|
+
}
|
|
37
|
+
config.history = out;
|
|
38
|
+
}
|