@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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Targeted `furnace deploy <name>...`: one or more named components applied
|
|
3
|
+
* under ONE furnace lock hold.
|
|
4
|
+
*
|
|
5
|
+
* Deploying a set of widgets one invocation at a time put every call at the
|
|
6
|
+
* back of the engine-lock queue, so a forty-widget deploy waited forty
|
|
7
|
+
* times. Naming them together waits once. Each named component is still its
|
|
8
|
+
* own atomic unit (applied, then its state persisted, before the next one
|
|
9
|
+
* starts), exactly as a single-name deploy, so a failure or signal midway
|
|
10
|
+
* leaves every earlier component committed and consistent.
|
|
11
|
+
*/
|
|
12
|
+
import { type ApplyAllComponentsResult } from '../../core/furnace-apply.js';
|
|
13
|
+
import type { FurnacePaths } from '../../core/furnace-config.js';
|
|
14
|
+
import type { FurnaceOperationContext } from '../../core/furnace-operation.js';
|
|
15
|
+
import type { FurnaceConfig } from '../../types/furnace.js';
|
|
16
|
+
import { type FragmentIncluderRefresh } from './deploy-fragment-includers.js';
|
|
17
|
+
/** Outcome of {@link deployNamedComponents}. */
|
|
18
|
+
export type NamedDeployOutcome = {
|
|
19
|
+
kind: 'stock';
|
|
20
|
+
stock: string[];
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'result';
|
|
23
|
+
result: ApplyAllComponentsResult;
|
|
24
|
+
includers: FragmentIncluderRefresh;
|
|
25
|
+
/** Named entries that are stock (warned about, never applied). */
|
|
26
|
+
stock: string[];
|
|
27
|
+
/** Named entries that are overrides or custom components, in order. */
|
|
28
|
+
deployed: string[];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Applies each named override or custom component through the same
|
|
32
|
+
* pipeline as deploy-all (`applyAllComponents` with a `componentName`
|
|
33
|
+
* filter), persisting each one's state right after it applies cleanly.
|
|
34
|
+
* Only then are the other stale includers of the fragments the cleanly
|
|
35
|
+
* applied components include refreshed, so an includer that is itself
|
|
36
|
+
* named is applied once, as a named component.
|
|
37
|
+
*
|
|
38
|
+
* Must run inside one `runFurnaceMutation` so the whole set shares a single
|
|
39
|
+
* lock hold.
|
|
40
|
+
*/
|
|
41
|
+
export declare function deployNamedComponents(args: {
|
|
42
|
+
projectRoot: string;
|
|
43
|
+
names: readonly string[];
|
|
44
|
+
config: FurnaceConfig;
|
|
45
|
+
furnacePaths: FurnacePaths;
|
|
46
|
+
isDryRun: boolean;
|
|
47
|
+
operationContext: FurnaceOperationContext;
|
|
48
|
+
}): Promise<NamedDeployOutcome>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Targeted `furnace deploy <name>...`: one or more named components applied
|
|
4
|
+
* under ONE furnace lock hold.
|
|
5
|
+
*
|
|
6
|
+
* Deploying a set of widgets one invocation at a time put every call at the
|
|
7
|
+
* back of the engine-lock queue, so a forty-widget deploy waited forty
|
|
8
|
+
* times. Naming them together waits once. Each named component is still its
|
|
9
|
+
* own atomic unit (applied, then its state persisted, before the next one
|
|
10
|
+
* starts), exactly as a single-name deploy, so a failure or signal midway
|
|
11
|
+
* leaves every earlier component committed and consistent.
|
|
12
|
+
*/
|
|
13
|
+
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
14
|
+
import { getPersistableAppliedEntry, persistSingleComponentState, shouldPersistSingleComponentState, } from '../../core/furnace-state-persist.js';
|
|
15
|
+
import { FurnaceError } from '../../errors/furnace.js';
|
|
16
|
+
import { mergeApplyResults, refreshStaleFragmentIncluders, } from './deploy-fragment-includers.js';
|
|
17
|
+
/**
|
|
18
|
+
* Splits the requested names into deployable and stock entries, refusing
|
|
19
|
+
* the whole invocation before any write when one is unknown. Duplicates
|
|
20
|
+
* are dropped, keeping the first occurrence.
|
|
21
|
+
*/
|
|
22
|
+
function partitionDeployNames(names, config) {
|
|
23
|
+
const deployable = [];
|
|
24
|
+
const stock = [];
|
|
25
|
+
for (const name of new Set(names)) {
|
|
26
|
+
if (name in config.overrides || name in config.custom)
|
|
27
|
+
deployable.push(name);
|
|
28
|
+
else if (config.stock.includes(name))
|
|
29
|
+
stock.push(name);
|
|
30
|
+
else
|
|
31
|
+
throw new FurnaceError(`Component "${name}" not found in furnace.json.`, name);
|
|
32
|
+
}
|
|
33
|
+
return { deployable, stock };
|
|
34
|
+
}
|
|
35
|
+
/** Folds several includer refreshes into one, without repeating a tag. */
|
|
36
|
+
function mergeIncluderRefreshes(refreshes, named) {
|
|
37
|
+
// A named component is reported as deployed in its own right, never as
|
|
38
|
+
// an includer some other named component refreshed on its behalf.
|
|
39
|
+
const refreshed = [...new Set(refreshes.flatMap((r) => r.refreshed))].filter((tag) => !named.has(tag));
|
|
40
|
+
return {
|
|
41
|
+
fragments: [...new Set(refreshes.flatMap((r) => r.fragments))].sort(),
|
|
42
|
+
refreshed,
|
|
43
|
+
failed: refreshes.flatMap((r) => r.failed).filter((f) => !named.has(f.tag)),
|
|
44
|
+
results: refreshes.flatMap((r) => r.results),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Applies each named override or custom component through the same
|
|
49
|
+
* pipeline as deploy-all (`applyAllComponents` with a `componentName`
|
|
50
|
+
* filter), persisting each one's state right after it applies cleanly.
|
|
51
|
+
* Only then are the other stale includers of the fragments the cleanly
|
|
52
|
+
* applied components include refreshed, so an includer that is itself
|
|
53
|
+
* named is applied once, as a named component.
|
|
54
|
+
*
|
|
55
|
+
* Must run inside one `runFurnaceMutation` so the whole set shares a single
|
|
56
|
+
* lock hold.
|
|
57
|
+
*/
|
|
58
|
+
export async function deployNamedComponents(args) {
|
|
59
|
+
const { projectRoot, names, config, furnacePaths, isDryRun, operationContext } = args;
|
|
60
|
+
const { deployable, stock } = partitionDeployNames(names, config);
|
|
61
|
+
if (deployable.length === 0)
|
|
62
|
+
return { kind: 'stock', stock };
|
|
63
|
+
const results = [];
|
|
64
|
+
const clean = [];
|
|
65
|
+
for (const name of deployable) {
|
|
66
|
+
const result = await applyAllComponents(projectRoot, isDryRun, {
|
|
67
|
+
componentName: name,
|
|
68
|
+
persistState: false,
|
|
69
|
+
operationContext,
|
|
70
|
+
});
|
|
71
|
+
results.push(result);
|
|
72
|
+
// Each named deploy is atomic: state is persisted only when every apply
|
|
73
|
+
// step succeeded, and any rollback has already restored the engine.
|
|
74
|
+
if (shouldPersistSingleComponentState(result, isDryRun)) {
|
|
75
|
+
await persistSingleComponentState(projectRoot, getPersistableAppliedEntry('Deploy', name, result.applied[0]), furnacePaths);
|
|
76
|
+
clean.push(name);
|
|
77
|
+
}
|
|
78
|
+
else if (isDryRun) {
|
|
79
|
+
clean.push(name);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Other deployed includers of a fragment these components include would
|
|
83
|
+
// otherwise keep a stale expansion. Only after a clean, persisted apply
|
|
84
|
+
// (dry-run always previews).
|
|
85
|
+
const refreshes = [];
|
|
86
|
+
for (const name of clean) {
|
|
87
|
+
refreshes.push(await refreshStaleFragmentIncluders({
|
|
88
|
+
projectRoot,
|
|
89
|
+
name,
|
|
90
|
+
config,
|
|
91
|
+
furnacePaths,
|
|
92
|
+
isDryRun,
|
|
93
|
+
operationContext,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
const includers = mergeIncluderRefreshes(refreshes, new Set(deployable));
|
|
97
|
+
const [first, ...rest] = results;
|
|
98
|
+
// `deployable` is non-empty, so `first` is always set.
|
|
99
|
+
const primary = first;
|
|
100
|
+
return {
|
|
101
|
+
kind: 'result',
|
|
102
|
+
result: mergeApplyResults(primary, [...rest, ...includers.results]),
|
|
103
|
+
includers,
|
|
104
|
+
stock,
|
|
105
|
+
deployed: deployable,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -2,7 +2,8 @@ import type { FurnaceDeployOptions } from '../../types/commands/index.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Runs the furnace deploy command: apply components then validate in one step.
|
|
4
4
|
* @param projectRoot - Root directory of the project
|
|
5
|
-
* @param
|
|
5
|
+
* @param names - Component name(s) to deploy, all under one lock hold
|
|
6
|
+
* (deploys all when omitted or empty)
|
|
6
7
|
* @param options - Command options
|
|
7
8
|
*/
|
|
8
|
-
export declare function furnaceDeployCommand(projectRoot: string,
|
|
9
|
+
export declare function furnaceDeployCommand(projectRoot: string, names?: string | readonly string[], options?: FurnaceDeployOptions): Promise<void>;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { loadConfig } from '../../core/config.js';
|
|
3
3
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
4
|
-
import { logApplyResult } from '../../core/furnace-apply-output.js';
|
|
4
|
+
import { formatSkipBreakdown, logApplyResult } from '../../core/furnace-apply-output.js';
|
|
5
5
|
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
6
6
|
import { reportJsconfigPathsSync } from '../../core/furnace-jsconfig.js';
|
|
7
|
-
import { runFurnaceMutation, waitLockMutationOptions
|
|
7
|
+
import { runFurnaceMutation, waitLockMutationOptions } from '../../core/furnace-operation.js';
|
|
8
8
|
import { assertFurnaceReady } from '../../core/furnace-precondition.js';
|
|
9
|
-
import {
|
|
9
|
+
import { getStepFailureCount } from '../../core/furnace-state-persist.js';
|
|
10
10
|
import { hasBlockingStepErrors } from '../../core/furnace-step-errors.js';
|
|
11
11
|
import { findOverrideBaseVersionDrift, formatOverrideBaseVersionDriftError, formatOverrideBaseVersionDriftWarning, } from '../../core/furnace-version-drift.js';
|
|
12
12
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
13
13
|
import { info, intro, note, notice, outro, spinner, warn } from '../../utils/logger.js';
|
|
14
|
-
import { formatFragmentIncluderNotice
|
|
14
|
+
import { formatFragmentIncluderNotice } from './deploy-fragment-includers.js';
|
|
15
|
+
import { deployNamedComponents } from './deploy-named.js';
|
|
15
16
|
import { runDeployValidation } from './validation-output.js';
|
|
16
17
|
/**
|
|
17
18
|
* Builds the final deploy failure summary from apply and validation error counts.
|
|
@@ -39,51 +40,6 @@ function getFailedComponentNames(result) {
|
|
|
39
40
|
}
|
|
40
41
|
return failed;
|
|
41
42
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Applies a single named override or custom component in targeted deploy
|
|
44
|
-
* mode.
|
|
45
|
-
*
|
|
46
|
-
* Delegates to {@link applyAllComponents} with a `componentName` filter so
|
|
47
|
-
* targeted deploys run the exact same pipeline as deploy-all, including
|
|
48
|
-
* workspace-deletion detection, engine orphan undeploy, and jar.mn /
|
|
49
|
-
* customElements.js re-sync. Calling the per-component apply helpers
|
|
50
|
-
* directly never prunes: renaming a helper file in the workspace then leaves
|
|
51
|
-
* the old deployed file and its stale jar.mn line in the engine.
|
|
52
|
-
*
|
|
53
|
-
* `persistState: false` matters here: the batch persist path replaces
|
|
54
|
-
* `appliedChecksums` wholesale with only this run's entries, which for a
|
|
55
|
-
* named deploy would wipe every other component's state. Named deploy keeps
|
|
56
|
-
* its per-component state merge ({@link persistSingleComponentState}) and
|
|
57
|
-
* its atomicity gate ({@link shouldPersistSingleComponentState}) at the call
|
|
58
|
-
* site. Rollback on failure happens inside `applyAllComponents`. The journal
|
|
59
|
-
* returned on success is ignored (the deploy keeps its files).
|
|
60
|
-
*
|
|
61
|
-
* The caller then runs the fragment-includer follow-up
|
|
62
|
-
* ({@link refreshStaleFragmentIncluders}) ONLY after this component's state
|
|
63
|
-
* is persisted: each includer is applied and persisted as its own unit, so
|
|
64
|
-
* a signal mid-loop restores at most the includer in flight and leaves every
|
|
65
|
-
* earlier unit committed. Moving the persist after the includer loop would
|
|
66
|
-
* silently break that atomicity.
|
|
67
|
-
*
|
|
68
|
-
* @param name - Component name to apply
|
|
69
|
-
* @param config - Loaded Furnace configuration
|
|
70
|
-
* @param isDryRun - Whether file writes should be skipped
|
|
71
|
-
* @returns Apply result for the named component, or `stock` for stock-only
|
|
72
|
-
* entries
|
|
73
|
-
*/
|
|
74
|
-
async function applyNamedComponent(name, config, isDryRun, projectRoot, operationContext) {
|
|
75
|
-
if (!(name in config.overrides) && !(name in config.custom)) {
|
|
76
|
-
if (config.stock.includes(name)) {
|
|
77
|
-
return 'stock';
|
|
78
|
-
}
|
|
79
|
-
throw new FurnaceError(`Component "${name}" not found in furnace.json.`, name);
|
|
80
|
-
}
|
|
81
|
-
return applyAllComponents(projectRoot, isDryRun, {
|
|
82
|
-
componentName: name,
|
|
83
|
-
persistState: false,
|
|
84
|
-
...(operationContext ? { operationContext } : {}),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
43
|
/**
|
|
88
44
|
* Prints the deploy summary after apply and validation complete.
|
|
89
45
|
* @param result - Aggregate apply result
|
|
@@ -109,7 +65,7 @@ function printDeploymentSummary(result, totalErrors, totalWarnings, componentCou
|
|
|
109
65
|
: ''), 'Dry Run Summary');
|
|
110
66
|
}
|
|
111
67
|
else {
|
|
112
|
-
note(`Applied ${appliedCount}, skipped ${skippedCount}\n` +
|
|
68
|
+
note(`Applied ${appliedCount}, skipped ${skippedCount}${formatSkipBreakdown(result.skipped)}\n` +
|
|
113
69
|
`${applyErrors} apply error(s)` +
|
|
114
70
|
(stepErrorCount > 0 ? `, ${stepErrorCount} registration step error(s)` : '') +
|
|
115
71
|
`\n` +
|
|
@@ -132,14 +88,25 @@ function enforceScopedOverrideVersionDriftPreflight(scopedDrift, force) {
|
|
|
132
88
|
throw new FurnaceError(formatOverrideBaseVersionDriftError(scopedDrift));
|
|
133
89
|
}
|
|
134
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Normalises the positional argument: a single name (programmatic callers)
|
|
93
|
+
* or the variadic list commander passes. An empty list means "deploy all".
|
|
94
|
+
*/
|
|
95
|
+
function normalizeDeployNames(names) {
|
|
96
|
+
if (names === undefined)
|
|
97
|
+
return [];
|
|
98
|
+
return typeof names === 'string' ? [names] : [...names];
|
|
99
|
+
}
|
|
135
100
|
/**
|
|
136
101
|
* Runs the furnace deploy command: apply components then validate in one step.
|
|
137
102
|
* @param projectRoot - Root directory of the project
|
|
138
|
-
* @param
|
|
103
|
+
* @param names - Component name(s) to deploy, all under one lock hold
|
|
104
|
+
* (deploys all when omitted or empty)
|
|
139
105
|
* @param options - Command options
|
|
140
106
|
*/
|
|
141
|
-
export async function furnaceDeployCommand(projectRoot,
|
|
107
|
+
export async function furnaceDeployCommand(projectRoot, names, options = {}) {
|
|
142
108
|
const isDryRun = options.dryRun ?? false;
|
|
109
|
+
const requested = normalizeDeployNames(names);
|
|
143
110
|
intro(isDryRun ? 'Furnace Deploy (dry run)' : 'Furnace Deploy');
|
|
144
111
|
const { config } = await assertFurnaceReady(projectRoot);
|
|
145
112
|
const furnacePaths = getFurnacePaths(projectRoot);
|
|
@@ -157,7 +124,9 @@ export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
|
157
124
|
const forgeConfig = await loadConfig(projectRoot);
|
|
158
125
|
const driftEntries = findOverrideBaseVersionDrift(config, forgeConfig.firefox.version);
|
|
159
126
|
const force = options.force ?? false;
|
|
160
|
-
const scopedDrift =
|
|
127
|
+
const scopedDrift = requested.length > 0
|
|
128
|
+
? driftEntries.filter((entry) => requested.includes(entry.name))
|
|
129
|
+
: driftEntries;
|
|
161
130
|
enforceScopedOverrideVersionDriftPreflight(scopedDrift, force);
|
|
162
131
|
// --- Step 1: Apply ---
|
|
163
132
|
const applySpinner = spinner(isDryRun ? 'Calculating planned actions...' : 'Applying components to engine...');
|
|
@@ -166,55 +135,37 @@ export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
|
166
135
|
// phase below is read-only and runs outside the lock so two concurrent
|
|
167
136
|
// `furnace deploy` runs only contend on the actual mutation.
|
|
168
137
|
const applyOutcome = await runFurnaceMutation(projectRoot, 'deploy-rollback', async (ctx) => {
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
if (namedApplyResult === 'stock') {
|
|
172
|
-
return { kind: 'stock' };
|
|
173
|
-
}
|
|
174
|
-
// Named deploy is atomic: state is persisted only when every apply
|
|
175
|
-
// step succeeded. Any rollback triggered by applyNamedComponent has
|
|
176
|
-
// already restored the engine to its pre-deploy state, so persisting
|
|
177
|
-
// partial checksums here would mis-report the next status/apply run
|
|
178
|
-
// against a workspace that was never actually deployed.
|
|
179
|
-
const primaryClean = shouldPersistSingleComponentState(namedApplyResult, isDryRun);
|
|
180
|
-
if (primaryClean) {
|
|
181
|
-
await persistSingleComponentState(projectRoot, getPersistableAppliedEntry('Deploy', name, namedApplyResult.applied[0]), furnacePaths);
|
|
182
|
-
}
|
|
183
|
-
// Other deployed includers of a fragment this component includes
|
|
184
|
-
// would otherwise keep a stale expansion. Only after a clean,
|
|
185
|
-
// persisted primary apply (dry-run always previews).
|
|
186
|
-
if (!primaryClean && !isDryRun) {
|
|
187
|
-
return { kind: 'result', result: namedApplyResult };
|
|
188
|
-
}
|
|
189
|
-
const includers = await refreshStaleFragmentIncluders({
|
|
138
|
+
if (requested.length > 0) {
|
|
139
|
+
return deployNamedComponents({
|
|
190
140
|
projectRoot,
|
|
191
|
-
|
|
141
|
+
names: requested,
|
|
192
142
|
config,
|
|
193
143
|
furnacePaths,
|
|
194
144
|
isDryRun,
|
|
195
145
|
operationContext: ctx,
|
|
196
146
|
});
|
|
197
|
-
return {
|
|
198
|
-
kind: 'result',
|
|
199
|
-
result: mergeApplyResults(namedApplyResult, includers.results),
|
|
200
|
-
includers,
|
|
201
|
-
};
|
|
202
147
|
}
|
|
203
148
|
const allResult = await applyAllComponents(projectRoot, isDryRun, {
|
|
204
149
|
operationContext: ctx,
|
|
205
150
|
});
|
|
206
|
-
return { kind: '
|
|
151
|
+
return { kind: 'all', result: allResult };
|
|
207
152
|
}, { dryRun: isDryRun, ...waitLockMutationOptions(options.waitLockSeconds) });
|
|
153
|
+
const warnStock = () => {
|
|
154
|
+
for (const stockName of applyOutcome.kind === 'all' ? [] : applyOutcome.stock) {
|
|
155
|
+
warn(`"${stockName}" is a stock component. Stock components are not applied locally.`);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
208
158
|
if (applyOutcome.kind === 'stock') {
|
|
209
159
|
applySpinner.stop('Apply skipped');
|
|
210
|
-
|
|
160
|
+
warnStock();
|
|
211
161
|
outro(isDryRun ? 'Dry run complete (no files modified)' : 'Deploy complete');
|
|
212
162
|
return;
|
|
213
163
|
}
|
|
214
164
|
const result = applyOutcome.result;
|
|
215
165
|
applySpinner.stop(isDryRun ? 'Planned actions calculated' : 'Components applied');
|
|
166
|
+
warnStock();
|
|
216
167
|
logApplyResult(result, isDryRun);
|
|
217
|
-
if (applyOutcome.
|
|
168
|
+
if (applyOutcome.kind === 'result') {
|
|
218
169
|
for (const line of formatFragmentIncluderNotice(applyOutcome.includers, isDryRun)) {
|
|
219
170
|
notice(line);
|
|
220
171
|
}
|
|
@@ -235,20 +186,33 @@ export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
|
235
186
|
}
|
|
236
187
|
const validateSpinner = spinner(isDryRun ? 'Validating (read-only)...' : 'Validating...');
|
|
237
188
|
const failedComponents = getFailedComponentNames(result);
|
|
189
|
+
// A named deploy validates every named component that applied, then the
|
|
190
|
+
// includers it refreshed. The first clean name leads (the validation
|
|
191
|
+
// runner skips the whole named branch when its lead failed), and every
|
|
192
|
+
// failed name is counted as skipped.
|
|
193
|
+
const deployed = applyOutcome.kind === 'result' ? applyOutcome.deployed : [];
|
|
194
|
+
const failedNamed = deployed.filter((tag) => failedComponents.has(tag));
|
|
195
|
+
const lead = deployed.find((tag) => !failedComponents.has(tag)) ?? deployed[0];
|
|
238
196
|
const validation = await runDeployValidation({
|
|
239
197
|
validateSpinner,
|
|
240
|
-
name,
|
|
198
|
+
name: lead,
|
|
241
199
|
config,
|
|
242
200
|
furnacePaths,
|
|
243
201
|
failedComponents,
|
|
244
202
|
isDryRun,
|
|
245
203
|
projectRoot,
|
|
246
204
|
dryRunActions: result.actions,
|
|
247
|
-
alsoValidate: applyOutcome.
|
|
205
|
+
alsoValidate: applyOutcome.kind === 'result'
|
|
206
|
+
? [...deployed.filter((tag) => tag !== lead), ...applyOutcome.includers.refreshed]
|
|
207
|
+
: [],
|
|
248
208
|
});
|
|
249
209
|
if (validation.done)
|
|
250
210
|
return;
|
|
251
|
-
const { totalErrors, totalWarnings, componentCount
|
|
211
|
+
const { totalErrors, totalWarnings, componentCount } = validation;
|
|
212
|
+
// The runner counts a failed lead itself; failed extras it drops silently.
|
|
213
|
+
const skippedValidationCount = lead !== undefined && failedComponents.has(lead)
|
|
214
|
+
? failedNamed.length
|
|
215
|
+
: validation.skippedValidationCount + failedNamed.length;
|
|
252
216
|
// --- Step 3: Summary ---
|
|
253
217
|
printDeploymentSummary(result, totalErrors, totalWarnings, componentCount, skippedValidationCount, isDryRun);
|
|
254
218
|
}
|
|
@@ -4,6 +4,8 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { getProjectPaths, loadState } from '../../core/config.js';
|
|
5
5
|
import { diffLines, renderHunks } from '../../core/diff-hunks.js';
|
|
6
6
|
import { getOverrideEngineTargetPath } from '../../core/furnace-apply-helpers.js';
|
|
7
|
+
import { normalizeForChecksum } from '../../core/furnace-checksum-utils.js';
|
|
8
|
+
import { composeComponentSource } from '../../core/furnace-composed-source.js';
|
|
7
9
|
import { getFurnacePaths, loadFurnaceConfig } from '../../core/furnace-config.js';
|
|
8
10
|
import { isComponentSourceFile, resolveFtlDir } from '../../core/furnace-constants.js';
|
|
9
11
|
import { getFileContentAtRef } from '../../core/git-file-ops.js';
|
|
@@ -108,6 +110,14 @@ async function diffOverride(name, projectRoot, config) {
|
|
|
108
110
|
* copy. Shows what would change (or has changed) on the next
|
|
109
111
|
* `furnace apply`.
|
|
110
112
|
*
|
|
113
|
+
* The workspace side is the Furnace-composed source: a stylesheet with
|
|
114
|
+
* `@fireforge-include` directives is compared in its fragment-expanded
|
|
115
|
+
* form, exactly as apply deploys it. Comparing the raw source instead
|
|
116
|
+
* reported every freshly deployed fragment includer as a large difference
|
|
117
|
+
* (the inlined fragment bodies and end markers), so the diff could not show
|
|
118
|
+
* whether a deploy would change anything. Line endings and a BOM are
|
|
119
|
+
* ignored, as apply's own drift check ignores them.
|
|
120
|
+
*
|
|
111
121
|
* `.ftl` files deploy to `engine/<ftlDir>/<name>.ftl` via
|
|
112
122
|
* `applyCustomFtlFile`, not to `customConfig.targetPath`, so the
|
|
113
123
|
* deployment-target lookup has to branch on extension. Without the branch, a
|
|
@@ -136,7 +146,19 @@ async function diffCustom(name, projectRoot, config) {
|
|
|
136
146
|
if (!isComponentSourceFile(entry.name))
|
|
137
147
|
continue;
|
|
138
148
|
const workspacePath = join(customDir, entry.name);
|
|
139
|
-
const
|
|
149
|
+
const rawWorkspace = await readText(workspacePath);
|
|
150
|
+
let workspaceContent = rawWorkspace;
|
|
151
|
+
let composedNote = '';
|
|
152
|
+
try {
|
|
153
|
+
workspaceContent = await composeComponentSource(rawWorkspace, entry.name, furnacePaths.sharedDir);
|
|
154
|
+
if (workspaceContent !== rawWorkspace)
|
|
155
|
+
composedNote = ' (composed: fragments expanded)';
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
// A missing fragment: no composed form exists, so show the raw
|
|
159
|
+
// source and say why; `furnace validate` reports the fragment itself.
|
|
160
|
+
composedNote = ` (raw: ${toError(error).message})`;
|
|
161
|
+
}
|
|
140
162
|
// `.ftl` files deploy to the locale tree, not the component's
|
|
141
163
|
// targetPath. Mirror `applyCustomFtlFile`'s target computation so the
|
|
142
164
|
// diff header and the existence probe name the same path apply
|
|
@@ -154,13 +176,14 @@ async function diffCustom(name, projectRoot, config) {
|
|
|
154
176
|
hasDifferences = true;
|
|
155
177
|
continue;
|
|
156
178
|
}
|
|
157
|
-
const deployedContent = await readText(deployedPath);
|
|
179
|
+
const deployedContent = normalizeForChecksum(await readText(deployedPath));
|
|
180
|
+
workspaceContent = normalizeForChecksum(workspaceContent);
|
|
158
181
|
if (workspaceContent === deployedContent) {
|
|
159
182
|
continue;
|
|
160
183
|
}
|
|
161
184
|
hasDifferences = true;
|
|
162
185
|
info(`--- ${deployedDisplayPath}`);
|
|
163
|
-
info(`+++ components/custom/${name}/${entry.name}`);
|
|
186
|
+
info(`+++ components/custom/${name}/${entry.name}${composedNote}`);
|
|
164
187
|
for (const line of formatUnifiedDiff(deployedContent, workspaceContent)) {
|
|
165
188
|
info(line);
|
|
166
189
|
}
|