@treeseed/sdk 0.11.0 → 0.12.5
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/README.md +9 -4
- package/dist/agent-capacity.d.ts +916 -0
- package/dist/agent-capacity.js +1600 -0
- package/dist/agent-tools.d.ts +37 -0
- package/dist/agent-tools.js +301 -0
- package/dist/api/app.d.ts +1 -1
- package/dist/api/auth/d1-database.d.ts +2 -2
- package/dist/api/auth/d1-provider.d.ts +4 -4
- package/dist/api/auth/d1-store.d.ts +2 -2
- package/dist/api/auth/memory-provider.d.ts +1 -1
- package/dist/api/auth/tokens.d.ts +1 -1
- package/dist/api/config.d.ts +3 -1
- package/dist/api/config.js +34 -10
- package/dist/api/http.d.ts +2 -2
- package/dist/api/index.d.ts +10 -10
- package/dist/api/index.js +4 -2
- package/dist/api/operations-routes.d.ts +3 -3
- package/dist/api/operations.d.ts +1 -1
- package/dist/api/providers.d.ts +1 -1
- package/dist/api/providers.js +21 -4
- package/dist/api/railway.d.ts +3 -2
- package/dist/api/sdk-dispatch.d.ts +4 -4
- package/dist/api/sdk-routes.d.ts +2 -2
- package/dist/api/templates.d.ts +2 -2
- package/dist/api/types.d.ts +3 -2
- package/dist/capacity-provider.d.ts +117 -60
- package/dist/capacity-provider.js +215 -43
- package/dist/capacity.d.ts +2 -2
- package/dist/cli-tools.d.ts +1 -1
- package/dist/content-operations.d.ts +97 -0
- package/dist/content-operations.js +250 -0
- package/dist/content-store.d.ts +4 -4
- package/dist/control-plane-client.d.ts +13 -18
- package/dist/control-plane-client.js +8 -86
- package/dist/control-plane.d.ts +2 -2
- package/dist/copilot.d.ts +3 -0
- package/dist/copilot.js +16 -1
- package/dist/d1-http.d.ts +1 -1
- package/dist/d1-store.d.ts +32 -57
- package/dist/d1-store.js +115 -318
- package/dist/db/d1.d.ts +1 -232
- package/dist/db/index.d.ts +3 -3
- package/dist/db/market-schema.d.ts +49037 -11843
- package/dist/db/market-schema.js +1788 -50
- package/dist/db/node-sqlite.d.ts +1 -232
- package/dist/db/schema.d.ts +0 -462
- package/dist/db/schema.js +2 -22
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +0 -11
- package/dist/fixture-support.js +52 -4
- package/dist/governance.d.ts +133 -0
- package/dist/governance.js +285 -0
- package/dist/graph/build.d.ts +2 -2
- package/dist/graph/context-query-contracts.d.ts +1 -1
- package/dist/graph/dsl.d.ts +1 -1
- package/dist/graph/query.d.ts +4 -4
- package/dist/graph/ranking.d.ts +1 -1
- package/dist/graph/schema.d.ts +1 -1
- package/dist/graph.d.ts +11 -11
- package/dist/guarantees/index.d.ts +425 -0
- package/dist/guarantees/index.js +1146 -0
- package/dist/hosting/apps.d.ts +1 -1
- package/dist/hosting/builtins.d.ts +1 -1
- package/dist/hosting/builtins.js +9 -198
- package/dist/hosting/contracts.d.ts +3 -2
- package/dist/hosting/graph.d.ts +24 -21
- package/dist/hosting/graph.js +280 -294
- package/dist/hosting/index.d.ts +4 -4
- package/dist/index.d.ts +88 -74
- package/dist/index.js +81 -10
- package/dist/local-dev/managed-dev.d.ts +85 -0
- package/dist/local-dev/managed-dev.js +368 -0
- package/dist/managed-dependencies.d.ts +9 -0
- package/dist/managed-dependencies.js +10 -8
- package/dist/market-client.d.ts +265 -7
- package/dist/market-client.js +381 -9
- package/dist/model-registry.d.ts +1 -1
- package/dist/model-registry.js +19 -19
- package/dist/operations/agent-tools.d.ts +2 -11
- package/dist/operations/agent-tools.js +2 -14
- package/dist/operations/providers/default.d.ts +1 -1
- package/dist/operations/providers/default.js +20 -37
- package/dist/operations/repository-operations.d.ts +26 -2
- package/dist/operations/repository-operations.js +159 -1
- package/dist/operations/runtime.d.ts +3 -3
- package/dist/operations/services/bootstrap-runner.d.ts +1 -1
- package/dist/operations/services/build-warning-policy.d.ts +34 -0
- package/dist/operations/services/build-warning-policy.js +81 -82
- package/dist/operations/services/commit-message-provider.js +4 -4
- package/dist/operations/services/config-runtime.d.ts +73 -19
- package/dist/operations/services/config-runtime.js +276 -100
- package/dist/operations/services/deploy.d.ts +41 -622
- package/dist/operations/services/deploy.js +181 -213
- package/dist/operations/services/deployment-readiness.d.ts +1 -1
- package/dist/operations/services/deployment-readiness.js +38 -7
- package/dist/operations/services/git-remote-policy.js +12 -4
- package/dist/operations/services/git-runner.d.ts +66 -0
- package/dist/operations/services/git-runner.js +479 -0
- package/dist/operations/services/git-workflow.d.ts +43 -5
- package/dist/operations/services/git-workflow.js +242 -20
- package/dist/operations/services/github-actions-verification.d.ts +3 -1
- package/dist/operations/services/github-actions-verification.js +11 -3
- package/dist/operations/services/github-api.js +21 -5
- package/dist/operations/services/github-automation.d.ts +3 -3
- package/dist/operations/services/github-automation.js +15 -18
- package/dist/operations/services/github-credentials.js +2 -1
- package/dist/operations/services/hosted-service-checks.d.ts +19 -1
- package/dist/operations/services/hosted-service-checks.js +162 -11
- package/dist/operations/services/hosting-audit.d.ts +2 -2
- package/dist/operations/services/hosting-audit.js +7 -7
- package/dist/operations/services/hub-launch.d.ts +1 -1
- package/dist/operations/services/hub-provider-launch.d.ts +5 -5
- package/dist/operations/services/hub-provider-launch.js +19 -14
- package/dist/operations/services/live-hosted-service-checks.d.ts +2 -1
- package/dist/operations/services/live-hosted-service-checks.js +193 -80
- package/dist/operations/services/local-dev.js +0 -1
- package/dist/operations/services/managed-host-security.d.ts +1 -1
- package/dist/operations/services/managed-repositories.d.ts +37 -0
- package/dist/operations/services/managed-repositories.js +177 -0
- package/dist/operations/services/operations-runner-smoke.d.ts +3 -2
- package/dist/operations/services/operations-runner-smoke.js +22 -4
- package/dist/operations/services/package-adapters.d.ts +77 -2
- package/dist/operations/services/package-adapters.js +629 -56
- package/dist/operations/services/package-reference-policy.d.ts +12 -88
- package/dist/operations/services/package-reference-policy.js +81 -213
- package/dist/operations/services/project-host-operations.d.ts +4 -4
- package/dist/operations/services/project-platform.d.ts +19 -193
- package/dist/operations/services/project-platform.js +31 -103
- package/dist/operations/services/project-web-monitor.d.ts +2 -2
- package/dist/operations/services/project-web-monitor.js +97 -2
- package/dist/operations/services/railway-api.d.ts +36 -7
- package/dist/operations/services/railway-api.js +331 -100
- package/dist/operations/services/railway-deploy.d.ts +7 -95
- package/dist/operations/services/railway-deploy.js +334 -742
- package/dist/operations/services/release-history.js +3 -4
- package/dist/operations/services/release-proof-ledger.d.ts +13 -0
- package/dist/operations/services/release-proof-ledger.js +81 -0
- package/dist/operations/services/release-proof-planner.d.ts +48 -0
- package/dist/operations/services/release-proof-planner.js +195 -0
- package/dist/operations/services/release-proof-runner.d.ts +16 -0
- package/dist/operations/services/release-proof-runner.js +169 -0
- package/dist/operations/services/release-proof.d.ts +81 -0
- package/dist/operations/services/release-proof.js +79 -0
- package/dist/operations/services/repository-save-orchestrator.d.ts +6 -7
- package/dist/operations/services/repository-save-orchestrator.js +353 -174
- package/dist/operations/services/runtime-paths.d.ts +1 -3
- package/dist/operations/services/runtime-paths.js +0 -4
- package/dist/operations/services/runtime-tools.d.ts +1 -192
- package/dist/operations/services/runtime-tools.js +4 -444
- package/dist/operations/services/save-deploy-preflight.js +9 -1
- package/dist/operations/services/template-host-bindings.d.ts +2 -2
- package/dist/operations/services/template-host-bindings.js +3 -2
- package/dist/operations/services/template-registry.d.ts +6 -6
- package/dist/operations/services/template-registry.js +33 -14
- package/dist/operations/services/template-secret-sync.d.ts +3 -3
- package/dist/operations/services/workflow-timing.d.ts +25 -0
- package/dist/operations/services/workflow-timing.js +79 -0
- package/dist/operations/services/workspace-dependency-mode.js +41 -4
- package/dist/operations/services/workspace-preflight.js +8 -8
- package/dist/operations/services/workspace-save-script.d.ts +4 -4
- package/dist/operations/services/workspace-save.d.ts +1 -0
- package/dist/operations/services/workspace-save.js +41 -18
- package/dist/operations/services/workspace-tools.js +40 -6
- package/dist/operations-registry.d.ts +1 -1
- package/dist/operations-registry.js +5 -6
- package/dist/operations-types.d.ts +1 -1
- package/dist/operations.d.ts +17 -11
- package/dist/operations.js +57 -3
- package/dist/platform/book-export.js +2 -0
- package/dist/platform/books-data.d.ts +1 -1
- package/dist/platform/config.d.ts +27 -0
- package/dist/platform/config.js +100 -0
- package/dist/platform/content-runtime-source.d.ts +54 -0
- package/dist/platform/content-runtime-source.js +169 -0
- package/dist/platform/contracts.d.ts +6 -1
- package/dist/platform/deploy-config.d.ts +1 -1
- package/dist/platform/deploy-config.js +7 -1
- package/dist/platform/deploy-runtime.d.ts +1 -1
- package/dist/platform/desired-state.d.ts +66 -0
- package/dist/platform/desired-state.js +1052 -0
- package/dist/platform/env.yaml +414 -19
- package/dist/platform/environment.d.ts +2 -2
- package/dist/platform/environment.js +54 -22
- package/dist/platform/local-content-materialization.d.ts +9 -0
- package/dist/platform/local-content-materialization.js +212 -0
- package/dist/platform/plugin.d.ts +5 -5
- package/dist/platform/plugins/runtime.d.ts +3 -3
- package/dist/platform/plugins/runtime.js +62 -1
- package/dist/platform/plugins.d.ts +6 -6
- package/dist/platform/published-content-pipeline.d.ts +3 -3
- package/dist/platform/published-content-pipeline.js +5 -1
- package/dist/platform/published-content.d.ts +4 -3
- package/dist/platform/site-config-schema.d.ts +1 -0
- package/dist/platform/site-config-schema.js +4 -1
- package/dist/platform/tenant/runtime-config.d.ts +152 -2
- package/dist/platform/tenant-config.d.ts +1 -1
- package/dist/platform/utils/site-config-schema.d.ts +154 -0
- package/dist/platform/utils/site-config-schema.js +400 -461
- package/dist/platform-operation-store.d.ts +1 -1
- package/dist/plugin-default.d.ts +1 -1
- package/dist/plugin-default.js +27 -12
- package/dist/project-import.d.ts +91 -0
- package/dist/project-import.js +257 -0
- package/dist/project-workflow.d.ts +1 -1
- package/dist/reconcile/bootstrap-systems.d.ts +2 -2
- package/dist/reconcile/bootstrap-systems.js +3 -3
- package/dist/reconcile/builtin-adapters.d.ts +7 -1
- package/dist/reconcile/builtin-adapters.js +2924 -346
- package/dist/reconcile/contracts.d.ts +15 -2
- package/dist/reconcile/desired-state.d.ts +2 -193
- package/dist/reconcile/desired-state.js +24 -33
- package/dist/reconcile/engine.d.ts +60 -397
- package/dist/reconcile/engine.js +182 -18
- package/dist/reconcile/index.d.ts +10 -10
- package/dist/reconcile/live-acceptance.d.ts +22 -1
- package/dist/reconcile/live-acceptance.js +456 -44
- package/dist/reconcile/providers/docker-private.d.ts +54 -0
- package/dist/reconcile/providers/docker-private.js +101 -0
- package/dist/reconcile/providers/github-private.d.ts +65 -0
- package/dist/reconcile/providers/github-private.js +119 -0
- package/dist/reconcile/providers/local-private.d.ts +28 -0
- package/dist/reconcile/providers/local-private.js +75 -0
- package/dist/reconcile/providers/railway-iac.d.ts +66 -0
- package/dist/reconcile/providers/railway-iac.js +275 -0
- package/dist/reconcile/providers/release-private.d.ts +92 -0
- package/dist/reconcile/providers/release-private.js +152 -0
- package/dist/reconcile/registry.d.ts +2 -2
- package/dist/reconcile/registry.js +16 -1
- package/dist/reconcile/state.d.ts +1 -1
- package/dist/reconcile/state.js +3 -40
- package/dist/reconcile/units.d.ts +1 -1
- package/dist/reconcile/units.js +7 -1
- package/dist/remote.d.ts +6 -6
- package/dist/scenes/artifacts.d.ts +16 -0
- package/dist/scenes/artifacts.js +61 -0
- package/dist/scenes/auth.d.ts +2 -0
- package/dist/scenes/auth.js +28 -0
- package/dist/scenes/base-url.d.ts +12 -0
- package/dist/scenes/base-url.js +123 -0
- package/dist/scenes/builtin-plugins.d.ts +2 -0
- package/dist/scenes/builtin-plugins.js +447 -0
- package/dist/scenes/checkpoints.d.ts +14 -0
- package/dist/scenes/checkpoints.js +33 -0
- package/dist/scenes/device-matrix.d.ts +2 -0
- package/dist/scenes/device-matrix.js +97 -0
- package/dist/scenes/devices.d.ts +11 -0
- package/dist/scenes/devices.js +22 -0
- package/dist/scenes/diagnostics.d.ts +5 -0
- package/dist/scenes/diagnostics.js +22 -0
- package/dist/scenes/diagram-providers.d.ts +2 -0
- package/dist/scenes/diagram-providers.js +181 -0
- package/dist/scenes/diagram-validation.d.ts +22 -0
- package/dist/scenes/diagram-validation.js +74 -0
- package/dist/scenes/environment.d.ts +2 -0
- package/dist/scenes/environment.js +65 -0
- package/dist/scenes/evidence-bundle.d.ts +5 -0
- package/dist/scenes/evidence-bundle.js +42 -0
- package/dist/scenes/evidence-report.d.ts +10 -0
- package/dist/scenes/evidence-report.js +73 -0
- package/dist/scenes/evidence.d.ts +16 -0
- package/dist/scenes/evidence.js +277 -0
- package/dist/scenes/index.d.ts +48 -0
- package/dist/scenes/index.js +312 -0
- package/dist/scenes/inspect.d.ts +9 -0
- package/dist/scenes/inspect.js +64 -0
- package/dist/scenes/loader.d.ts +3 -0
- package/dist/scenes/loader.js +38 -0
- package/dist/scenes/logs.d.ts +2 -0
- package/dist/scenes/logs.js +47 -0
- package/dist/scenes/operations.d.ts +3 -0
- package/dist/scenes/operations.js +128 -0
- package/dist/scenes/phase0.d.ts +9 -0
- package/dist/scenes/phase0.js +637 -0
- package/dist/scenes/planner.d.ts +12 -0
- package/dist/scenes/planner.js +166 -0
- package/dist/scenes/playwright-adapter.d.ts +2 -0
- package/dist/scenes/playwright-adapter.js +63 -0
- package/dist/scenes/plugins.d.ts +5 -0
- package/dist/scenes/plugins.js +115 -0
- package/dist/scenes/progress.d.ts +17 -0
- package/dist/scenes/progress.js +24 -0
- package/dist/scenes/publish-destinations.d.ts +12 -0
- package/dist/scenes/publish-destinations.js +99 -0
- package/dist/scenes/publish-plan-report.d.ts +10 -0
- package/dist/scenes/publish-plan-report.js +70 -0
- package/dist/scenes/publish-plan.d.ts +15 -0
- package/dist/scenes/publish-plan.js +248 -0
- package/dist/scenes/publish-redaction.d.ts +16 -0
- package/dist/scenes/publish-redaction.js +148 -0
- package/dist/scenes/publish-release-record.d.ts +13 -0
- package/dist/scenes/publish-release-record.js +34 -0
- package/dist/scenes/publish-report.d.ts +10 -0
- package/dist/scenes/publish-report.js +67 -0
- package/dist/scenes/publish.d.ts +16 -0
- package/dist/scenes/publish.js +298 -0
- package/dist/scenes/registry.d.ts +12 -0
- package/dist/scenes/registry.js +65 -0
- package/dist/scenes/remotion-adapter.d.ts +3 -0
- package/dist/scenes/remotion-adapter.js +94 -0
- package/dist/scenes/remotion-composition-registry.d.ts +2 -0
- package/dist/scenes/remotion-composition-registry.js +12 -0
- package/dist/scenes/remotion-compositions.d.ts +15 -0
- package/dist/scenes/remotion-compositions.js +464 -0
- package/dist/scenes/remotion-diagrams.d.ts +9 -0
- package/dist/scenes/remotion-diagrams.js +188 -0
- package/dist/scenes/remotion-input.d.ts +13 -0
- package/dist/scenes/remotion-input.js +291 -0
- package/dist/scenes/remotion-visuals.d.ts +29 -0
- package/dist/scenes/remotion-visuals.js +198 -0
- package/dist/scenes/render-media-assets.d.ts +9 -0
- package/dist/scenes/render-media-assets.js +117 -0
- package/dist/scenes/render-report.d.ts +10 -0
- package/dist/scenes/render-report.js +27 -0
- package/dist/scenes/render.d.ts +2 -0
- package/dist/scenes/render.js +218 -0
- package/dist/scenes/reporter.d.ts +3 -0
- package/dist/scenes/reporter.js +101 -0
- package/dist/scenes/resume.d.ts +2 -0
- package/dist/scenes/resume.js +79 -0
- package/dist/scenes/runner.d.ts +2 -0
- package/dist/scenes/runner.js +674 -0
- package/dist/scenes/schema.d.ts +6 -0
- package/dist/scenes/schema.js +994 -0
- package/dist/scenes/seed.d.ts +2 -0
- package/dist/scenes/seed.js +83 -0
- package/dist/scenes/segments.d.ts +15 -0
- package/dist/scenes/segments.js +79 -0
- package/dist/scenes/selectors.d.ts +3 -0
- package/dist/scenes/selectors.js +21 -0
- package/dist/scenes/timeline.d.ts +11 -0
- package/dist/scenes/timeline.js +26 -0
- package/dist/scenes/timeouts.d.ts +6 -0
- package/dist/scenes/timeouts.js +17 -0
- package/dist/scenes/training-captions.d.ts +14 -0
- package/dist/scenes/training-captions.js +98 -0
- package/dist/scenes/training-report.d.ts +10 -0
- package/dist/scenes/training-report.js +78 -0
- package/dist/scenes/training-transcript.d.ts +24 -0
- package/dist/scenes/training-transcript.js +204 -0
- package/dist/scenes/training.d.ts +10 -0
- package/dist/scenes/training.js +134 -0
- package/dist/scenes/types.d.ts +1872 -0
- package/dist/scenes/types.js +8 -0
- package/dist/scenes/visual-audit-contact-sheets.d.ts +6 -0
- package/dist/scenes/visual-audit-contact-sheets.js +119 -0
- package/dist/scenes/visual-audit-fixtures.d.ts +25 -0
- package/dist/scenes/visual-audit-fixtures.js +210 -0
- package/dist/scenes/visual-audit-report.d.ts +11 -0
- package/dist/scenes/visual-audit-report.js +85 -0
- package/dist/scenes/visual-audit-review.d.ts +23 -0
- package/dist/scenes/visual-audit-review.js +829 -0
- package/dist/scenes/visual-audit-routes.d.ts +13 -0
- package/dist/scenes/visual-audit-routes.js +308 -0
- package/dist/scenes/visual-audit.d.ts +3 -0
- package/dist/scenes/visual-audit.js +596 -0
- package/dist/scripts/build-dist.js +154 -40
- package/dist/scripts/check-build-warnings.js +42 -53
- package/dist/scripts/cleanup-markdown.js +1 -1
- package/dist/scripts/cli-test-fixtures.js +24 -28
- package/dist/scripts/migrate-journey-csv-to-guarantees.js +140 -0
- package/dist/scripts/package-tools.js +12 -1
- package/dist/scripts/prepare.js +3 -7
- package/dist/scripts/release-verify.js +2 -5
- package/dist/scripts/run-fixture-astro-command.js +1 -1
- package/dist/scripts/template-catalog.test.js +68 -82
- package/dist/scripts/tenant-dev.js +0 -10
- package/dist/scripts/test-cloudflare-local.js +1 -1
- package/dist/scripts/test-scaffold.js +0 -1
- package/dist/scripts/test-smoke.js +3 -3
- package/dist/scripts/treeseed-build-dist.js +4 -7
- package/dist/scripts/treeseed-release-verify.js +1 -1
- package/dist/scripts/verify-driver.js +30 -21
- package/dist/scripts/workflow-commands.test.js +18 -27
- package/dist/scripts/workspace-command-e2e.js +1 -1
- package/dist/scripts/workspace-lint.js +6 -0
- package/dist/scripts/workspace-release-test.js +90 -1
- package/dist/scripts/workspace-test.js +6 -0
- package/dist/sdk-dispatch.d.ts +1 -1
- package/dist/sdk-dispatch.js +0 -16
- package/dist/sdk-fields.d.ts +1 -1
- package/dist/sdk-filters.d.ts +1 -1
- package/dist/sdk-types.d.ts +1184 -113
- package/dist/sdk-types.js +393 -0
- package/dist/sdk.d.ts +74 -79
- package/dist/sdk.js +27 -36
- package/dist/secrets-capability.d.ts +421 -0
- package/dist/secrets-capability.js +530 -0
- package/dist/seeds/normalize.js +1 -0
- package/dist/seeds/planner.js +38 -0
- package/dist/seeds/schema.js +293 -4
- package/dist/seeds/types.d.ts +60 -0
- package/dist/seeds/types.js +9 -1
- package/dist/service-credentials.d.ts +54 -0
- package/dist/service-credentials.js +112 -0
- package/dist/stores/cursor-store.d.ts +2 -2
- package/dist/stores/envelopes.d.ts +1 -1
- package/dist/stores/helpers.d.ts +1 -1
- package/dist/stores/lease-store.d.ts +2 -2
- package/dist/stores/message-store.d.ts +2 -2
- package/dist/stores/operational-store.d.ts +3 -26
- package/dist/stores/operational-store.js +0 -225
- package/dist/stores/project-workflow-store.d.ts +2 -2
- package/dist/stores/run-store.d.ts +2 -3
- package/dist/stores/run-store.js +0 -98
- package/dist/stores/subscription-store.d.ts +2 -3
- package/dist/stores/subscription-store.js +0 -100
- package/dist/template-catalog.d.ts +1 -1
- package/dist/template-launch-requirements.d.ts +2 -2
- package/dist/template-launch-ui.d.ts +2 -2
- package/dist/treedx/adapters.d.ts +6 -6
- package/dist/treedx/client.d.ts +1 -1
- package/dist/treedx/errors.d.ts +1 -1
- package/dist/treedx/federated-client.d.ts +3 -3
- package/dist/treedx/graph-adapter.d.ts +2 -2
- package/dist/treedx/index.d.ts +14 -14
- package/dist/treedx/market-integration.d.ts +1 -1
- package/dist/treedx/ports.d.ts +30 -30
- package/dist/treedx/query-adapter.d.ts +3 -3
- package/dist/treedx/registry-client.d.ts +2 -2
- package/dist/treedx/repository-adapter.d.ts +4 -4
- package/dist/treedx/repository-adapter.js +14 -3
- package/dist/treedx/sdk-integration.d.ts +3 -3
- package/dist/treedx/types.d.ts +2 -2
- package/dist/treedx/workspace-adapter.d.ts +2 -2
- package/dist/treedx-backends.d.ts +13 -11
- package/dist/treedx-backends.js +52 -50
- package/dist/treedx-client.d.ts +3 -0
- package/dist/treedx-client.js +10 -1
- package/dist/treeseed/services/compose.yml +2 -3
- package/dist/treeseed/template-catalog/catalog.fixture.json +4 -4
- package/dist/types/agents.d.ts +256 -0
- package/dist/types/agents.js +42 -1
- package/dist/verification.d.ts +1 -0
- package/dist/verification.js +143 -14
- package/dist/workflow/operations.d.ts +510 -559
- package/dist/workflow/operations.js +1891 -1342
- package/dist/workflow/policy.js +19 -7
- package/dist/workflow/runs.d.ts +9 -3
- package/dist/workflow/runs.js +66 -26
- package/dist/workflow/session.d.ts +4 -1
- package/dist/workflow/session.js +50 -10
- package/dist/workflow/worktrees.d.ts +6 -2
- package/dist/workflow/worktrees.js +98 -15
- package/dist/workflow-state.d.ts +5 -5
- package/dist/workflow-state.js +27 -17
- package/dist/workflow-support.d.ts +26 -25
- package/dist/workflow-support.js +27 -31
- package/dist/workflow.d.ts +46 -16
- package/dist/workflow.js +19 -7
- package/drizzle/d1/0000_treeseed_d1.sql +0 -18
- package/drizzle/market/0000_market_control_plane.sql +1793 -1499
- package/drizzle/market/0005_agent_capacity_coordination.sql +145 -0
- package/drizzle/market/0006_provider_assignment_lifecycle.sql +9 -0
- package/drizzle/market/0007_agent_architecture_gap_closure.sql +157 -0
- package/drizzle/market/0008_agent_capacity_operational_closure.sql +27 -0
- package/drizzle/market/0009_agent_capacity_runtime_hardening.sql +29 -0
- package/drizzle/market/0010_secrets_capability_persistence.sql +130 -0
- package/drizzle/market/0011_github_app_adapter.sql +47 -0
- package/drizzle/market/0012_workday_test_runs.sql +44 -0
- package/drizzle/market/0013_runtime_task_lifecycle.sql +39 -0
- package/drizzle/market/0014_governance_pipeline.sql +189 -0
- package/package.json +75 -18
- package/scripts/{verify-driver.mjs → verify-driver.ts} +19 -4
- package/templates/github/deploy-web.workflow.yml +12 -8
- package/dist/operations/services/mailpit-runtime.d.ts +0 -20
- package/dist/operations/services/mailpit-runtime.js +0 -67
- package/dist/operations/services/release-candidate.d.ts +0 -60
- package/dist/operations/services/release-candidate.js +0 -953
- package/dist/scripts/ensure-mailpit.js +0 -48
- package/dist/scripts/logs-mailpit.js +0 -2
- package/dist/scripts/run-ts.js +0 -45
- package/dist/scripts/stop-mailpit.js +0 -5
- package/dist/scripts/treeseed-run-ts.js +0 -45
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { relative, resolve } from "node:path";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, relative, resolve } from "node:path";
|
|
4
3
|
import { parse as parseYaml } from "yaml";
|
|
5
4
|
import { workspacePackages, workspaceRoot } from "./workspace-tools.js";
|
|
5
|
+
import { runTreeseedGit } from "./git-runner.js";
|
|
6
|
+
import { resolveTreeseedLaunchEnvironment } from "./config-runtime.js";
|
|
7
|
+
import { resolveGitHubCredentialForRepository } from "./github-credentials.js";
|
|
8
|
+
import {
|
|
9
|
+
createGitHubApiClient,
|
|
10
|
+
getLatestGitHubWorkflowRun
|
|
11
|
+
} from "./github-api.js";
|
|
12
|
+
import { resolveTreeseedDockerhubToken, resolveTreeseedDockerhubUsername } from "../../service-credentials.js";
|
|
13
|
+
import { inspectTreeseedContentStructure } from "../../platform/content-runtime-source.js";
|
|
14
|
+
import {
|
|
15
|
+
SEED_CONTENT_PUBLISH_TARGETS,
|
|
16
|
+
SEED_CONTENT_RUNTIME_SOURCES,
|
|
17
|
+
SEED_LOCAL_CONTENT_MATERIALIZATIONS,
|
|
18
|
+
SEED_PROJECT_TOPOLOGIES
|
|
19
|
+
} from "../../seeds/types.js";
|
|
6
20
|
function readJsonFile(filePath) {
|
|
7
21
|
try {
|
|
8
22
|
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
@@ -42,6 +56,49 @@ function commandFromScript(dir, script, label) {
|
|
|
42
56
|
}
|
|
43
57
|
return { label, command: "bash", args: ["-lc", trimmed], cwd: dir };
|
|
44
58
|
}
|
|
59
|
+
function normalizePackageSlug(id) {
|
|
60
|
+
const raw = id.startsWith("@treeseed/") ? id.slice("@treeseed/".length) : id;
|
|
61
|
+
return raw.toLowerCase().replace(/^treeseed-/u, "").replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "") || "package";
|
|
62
|
+
}
|
|
63
|
+
function enumValue(value, allowed, fallback) {
|
|
64
|
+
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
65
|
+
}
|
|
66
|
+
function normalizeTreeseedPackageProjectArchitecture(value, packageId) {
|
|
67
|
+
const record = stringRecord(value);
|
|
68
|
+
if (Object.keys(record).length === 0) return null;
|
|
69
|
+
const publishTarget = stringRecord(record.contentPublishTarget);
|
|
70
|
+
const packageSlug = normalizePackageSlug(packageId);
|
|
71
|
+
const targetKind = enumValue(publishTarget.kind, SEED_CONTENT_PUBLISH_TARGETS, "cloudflare_r2");
|
|
72
|
+
return {
|
|
73
|
+
topology: enumValue(record.topology, SEED_PROJECT_TOPOLOGIES, "single_repository_site"),
|
|
74
|
+
rootPath: stringValue(record.rootPath) ?? ".",
|
|
75
|
+
sitePath: stringValue(record.sitePath) ?? "docs",
|
|
76
|
+
contentPath: stringValue(record.contentPath) ?? "docs",
|
|
77
|
+
contentRuntimeSource: enumValue(record.contentRuntimeSource, SEED_CONTENT_RUNTIME_SOURCES, "r2_published_manifest"),
|
|
78
|
+
localContentMaterialization: enumValue(record.localContentMaterialization, SEED_LOCAL_CONTENT_MATERIALIZATIONS, "none"),
|
|
79
|
+
contentPublishTarget: {
|
|
80
|
+
kind: targetKind,
|
|
81
|
+
...stringValue(publishTarget.bucket) ? { bucket: stringValue(publishTarget.bucket) } : {},
|
|
82
|
+
prefix: stringValue(publishTarget.prefix) ?? `packages/${packageSlug}`,
|
|
83
|
+
...stringValue(publishTarget.manifestPath) ? { manifestPath: stringValue(publishTarget.manifestPath) } : {}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function docsSiteReadiness(dir, architecture) {
|
|
88
|
+
if (!architecture) return null;
|
|
89
|
+
const diagnostic = inspectTreeseedContentStructure({ projectRoot: dir, architecture });
|
|
90
|
+
const readiness = diagnostic.status === "ready" ? "ready" : diagnostic.status === "unsupported_structure" ? "unsupported_structure" : "site_not_prepared";
|
|
91
|
+
return {
|
|
92
|
+
status: readiness,
|
|
93
|
+
diagnostic
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function deploymentSourceModeForBranch(metadata, branch) {
|
|
97
|
+
const source = stringRecord(metadata.deploymentSource);
|
|
98
|
+
const normalizedBranch = branch === "prod" || branch === "production" || branch === "main" ? "prod" : branch === "staging" ? "staging" : "local";
|
|
99
|
+
const configured = stringValue(source[normalizedBranch]);
|
|
100
|
+
return configured === "git" || configured === "image" ? configured : normalizedBranch === "prod" ? "image" : stringValue(source.staging) === "git" ? "git" : null;
|
|
101
|
+
}
|
|
45
102
|
function nodeTypeScriptAdapter(pkg) {
|
|
46
103
|
const manifest = readTreeseedPackageManifest(pkg.dir);
|
|
47
104
|
const scripts = pkg.packageJson?.scripts && typeof pkg.packageJson.scripts === "object" && !Array.isArray(pkg.packageJson.scripts) ? pkg.packageJson.scripts : {};
|
|
@@ -49,8 +106,15 @@ function nodeTypeScriptAdapter(pkg) {
|
|
|
49
106
|
const repository = stringValue(manifest?.repository) ?? normalizeGitHubRepositorySlug(pkg.packageJson?.repository);
|
|
50
107
|
const id = stringValue(manifest?.id) ?? String(pkg.name);
|
|
51
108
|
const name = stringValue(manifest?.name) ?? String(pkg.name);
|
|
52
|
-
const
|
|
53
|
-
const
|
|
109
|
+
const dockerArtifacts = manifestDockerArtifacts(manifest?.artifacts);
|
|
110
|
+
const dockerImages = stringRecord(manifest?.dockerImages);
|
|
111
|
+
const dockerImageReleaseWorkflow = stringValue(dockerImages.releaseWorkflow);
|
|
112
|
+
const dockerImageArchitectures = stringArray(dockerImages.architectures);
|
|
113
|
+
const publishTargetRaw = stringValue(manifest?.publishTarget);
|
|
114
|
+
const publishTarget = dockerArtifacts.length > 0 && publishTargetRaw === "docker" ? dockerArtifacts[0].name : publishTargetRaw ?? "npm";
|
|
115
|
+
const hostedVerifyWorkflow = stringValue(manifest?.hostedVerifyWorkflow) ?? stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(pkg.dir, ".github/workflows/deploy.yml")) ? "deploy.yml" : null);
|
|
116
|
+
const projectArchitecture = normalizeTreeseedPackageProjectArchitecture(manifest?.projectArchitecture, id);
|
|
117
|
+
const docsReadiness = docsSiteReadiness(pkg.dir, projectArchitecture);
|
|
54
118
|
const verifyLocal = typeof scripts["verify:local"] === "string" ? "verify:local" : typeof scripts.verify === "string" ? "verify" : typeof scripts["verify:action"] === "string" ? "verify:action" : null;
|
|
55
119
|
return {
|
|
56
120
|
id,
|
|
@@ -67,13 +131,40 @@ function nodeTypeScriptAdapter(pkg) {
|
|
|
67
131
|
local: commandFromScript(pkg.dir, manifestVerify.local, "local") ?? (verifyLocal ? { label: verifyLocal, command: "npm", args: ["run", verifyLocal], cwd: pkg.dir } : null),
|
|
68
132
|
release: commandFromScript(pkg.dir, manifestVerify.release, "release") ?? (typeof scripts["release:publish"] === "string" ? { label: "release:publish", command: "npm", args: ["run", "release:publish"], cwd: pkg.dir } : null)
|
|
69
133
|
},
|
|
70
|
-
artifacts:
|
|
134
|
+
artifacts: dockerArtifacts.length > 0 ? dockerArtifacts.map((artifact) => ({
|
|
135
|
+
provider: "docker",
|
|
136
|
+
name: artifact.name,
|
|
137
|
+
dockerfile: artifact.dockerfile,
|
|
138
|
+
context: artifact.context,
|
|
139
|
+
target: artifact.target,
|
|
140
|
+
role: artifact.role,
|
|
141
|
+
architectures: artifact.architectures
|
|
142
|
+
})) : [{ provider: "npm", name: String(pkg.name) }],
|
|
71
143
|
releaseChecks: [
|
|
72
|
-
{ kind: "github-workflow", name: "publish workflow", detail: ".github/workflows/publish.yml" },
|
|
73
|
-
{ kind: "npm-pack-dry-run", name: "npm pack", detail: "npm pack --dry-run" }
|
|
144
|
+
{ kind: "github-workflow", name: "publish workflow", detail: dockerImageReleaseWorkflow ? `.github/workflows/${dockerImageReleaseWorkflow}` : ".github/workflows/publish.yml" },
|
|
145
|
+
...dockerArtifacts.length > 0 ? dockerArtifacts.map((artifact) => ({ kind: "docker-manifest", name: `${artifact.name} Docker image manifest`, detail: `${artifact.name}:<version>` })) : [{ kind: "npm-pack-dry-run", name: "npm pack", detail: "npm pack --dry-run" }]
|
|
74
146
|
],
|
|
75
147
|
metadata: {
|
|
76
148
|
...repository ? { repository } : {},
|
|
149
|
+
deploymentSource: stringRecord(manifest?.deploymentSource),
|
|
150
|
+
...dockerArtifacts.length > 0 ? {
|
|
151
|
+
dockerArtifacts,
|
|
152
|
+
dockerImageReleaseWorkflow: dockerImageReleaseWorkflow ? `.github/workflows/${dockerImageReleaseWorkflow}` : ".github/workflows/publish.yml",
|
|
153
|
+
dockerImageArchitectures,
|
|
154
|
+
imageHosting: stringRecord(dockerImages.hosting)
|
|
155
|
+
} : {},
|
|
156
|
+
type: stringValue(manifest?.type) ?? null,
|
|
157
|
+
githubEnvironments: stringArray(manifest?.githubEnvironments),
|
|
158
|
+
requiredSecrets: stringArray(manifest?.requiredSecrets),
|
|
159
|
+
requiredVariables: stringArray(manifest?.requiredVariables),
|
|
160
|
+
workflowTemplateVersion: stringValue(manifest?.workflowTemplateVersion) ?? null,
|
|
161
|
+
localDev: stringRecord(manifest?.localDev),
|
|
162
|
+
capacityProvider: stringRecord(manifest?.capacityProvider),
|
|
163
|
+
...projectArchitecture ? {
|
|
164
|
+
projectArchitecture,
|
|
165
|
+
docsSiteReadiness: docsReadiness?.status ?? "site_not_prepared",
|
|
166
|
+
docsSiteDiagnostic: docsReadiness?.diagnostic ?? null
|
|
167
|
+
} : {},
|
|
77
168
|
...hostedVerifyWorkflow ? {
|
|
78
169
|
hostedVerifyWorkflow: hostedVerifyWorkflow.startsWith(".github/workflows/") ? hostedVerifyWorkflow : `.github/workflows/${hostedVerifyWorkflow}`
|
|
79
170
|
} : {},
|
|
@@ -101,6 +192,24 @@ function stringValue(value) {
|
|
|
101
192
|
function stringArray(value) {
|
|
102
193
|
return Array.isArray(value) ? value.map((entry) => stringValue(entry)).filter((entry) => Boolean(entry)) : [];
|
|
103
194
|
}
|
|
195
|
+
function manifestDockerArtifacts(value) {
|
|
196
|
+
if (!Array.isArray(value)) return [];
|
|
197
|
+
return value.map((entry) => {
|
|
198
|
+
const record = stringRecord(entry);
|
|
199
|
+
if (stringValue(record.provider) !== "docker") return null;
|
|
200
|
+
const name = stringValue(record.name);
|
|
201
|
+
if (!name) return null;
|
|
202
|
+
return {
|
|
203
|
+
provider: "docker",
|
|
204
|
+
name,
|
|
205
|
+
dockerfile: stringValue(record.dockerfile),
|
|
206
|
+
context: stringValue(record.context),
|
|
207
|
+
target: stringValue(record.target),
|
|
208
|
+
role: stringValue(record.role),
|
|
209
|
+
architectures: stringArray(record.architectures)
|
|
210
|
+
};
|
|
211
|
+
}).filter((entry) => Boolean(entry));
|
|
212
|
+
}
|
|
104
213
|
function beamPackageAdapter(root, dir) {
|
|
105
214
|
const manifest = readTreeseedPackageManifest(dir);
|
|
106
215
|
const hasMixProject = existsSync(resolve(dir, "apps/api/mix.exs")) || existsSync(resolve(dir, "mix.exs"));
|
|
@@ -113,18 +222,13 @@ function beamPackageAdapter(root, dir) {
|
|
|
113
222
|
const versionSource = resolve(dir, versionSourceRel);
|
|
114
223
|
const image = typeof manifest?.image === "string" && manifest.image.trim() ? manifest.image.trim() : id === "treedx" ? "treeseed/treedx" : null;
|
|
115
224
|
const repository = stringValue(manifest?.repository) ?? (id === "treedx" ? "treeseed-ai/treedx" : null);
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
const
|
|
119
|
-
const hostedVerifyWorkflow = stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(dir, ".github/workflows/release-gate.yml")) ? "release-gate.yml" : null);
|
|
120
|
-
const developmentImageDefaultBranch = stringValue(developmentImages.defaultBranch) ?? "staging";
|
|
121
|
-
const developmentImageTagPrefix = stringValue(developmentImages.tagPrefix) ?? "dev";
|
|
122
|
-
const developmentImageMovingTag = developmentImages.movingTag === false ? false : true;
|
|
123
|
-
const developmentImageArchitectures = stringArray(developmentImages.architectures);
|
|
225
|
+
const hostedVerifyWorkflow = stringValue(manifest?.hostedVerifyWorkflow) ?? stringValue(stringRecord(manifest?.releaseGate).workflow) ?? (existsSync(resolve(dir, ".github/workflows/release-gate.yml")) ? "release-gate.yml" : null);
|
|
226
|
+
const projectArchitecture = normalizeTreeseedPackageProjectArchitecture(manifest?.projectArchitecture, id);
|
|
227
|
+
const docsReadiness = docsSiteReadiness(dir, projectArchitecture);
|
|
124
228
|
const verify = manifest?.verify && typeof manifest.verify === "object" && !Array.isArray(manifest.verify) ? manifest.verify : {};
|
|
125
229
|
const fast = verify.fast ?? (existsSync(resolve(dir, "scripts/test-treedx-fast.sh")) ? "scripts/test-treedx-fast.sh" : null);
|
|
126
230
|
const local = verify.local ?? (existsSync(resolve(dir, "scripts/test-all.sh")) ? "scripts/test-all.sh" : null);
|
|
127
|
-
const releaseGate = manifest?.releaseGate ?? verify.release ?? (existsSync(resolve(dir, "scripts/release-gate.sh")) ? "scripts/release-gate.sh" : null);
|
|
231
|
+
const releaseGate = stringValue(manifest?.releaseGate) ?? verify.release ?? (existsSync(resolve(dir, "scripts/release-gate.sh")) ? "scripts/release-gate.sh" : null);
|
|
128
232
|
const version = readMixProjectVersion(versionSource);
|
|
129
233
|
const shaTag = "sha-<short-sha>";
|
|
130
234
|
return {
|
|
@@ -142,37 +246,57 @@ function beamPackageAdapter(root, dir) {
|
|
|
142
246
|
local: commandFromScript(dir, local, "local"),
|
|
143
247
|
release: commandFromScript(dir, releaseGate, "release")
|
|
144
248
|
},
|
|
145
|
-
artifacts: image ? [{
|
|
249
|
+
artifacts: image ? [{
|
|
250
|
+
provider: "docker",
|
|
251
|
+
name: image,
|
|
252
|
+
tags: version ? [version, shaTag] : [shaTag],
|
|
253
|
+
dockerfile: "Dockerfile",
|
|
254
|
+
context: ".",
|
|
255
|
+
target: null,
|
|
256
|
+
role: id,
|
|
257
|
+
architectures: stringArray(stringRecord(manifest?.dockerImages).architectures)
|
|
258
|
+
}] : [],
|
|
146
259
|
releaseChecks: image ? [{ kind: "docker-manifest", name: "Docker image manifest", detail: `${image}:${version ?? "<version>"}` }] : [],
|
|
147
260
|
metadata: {
|
|
148
261
|
hasCargo: existsSync(resolve(dir, "Cargo.toml")),
|
|
149
262
|
hasDockerfile: existsSync(resolve(dir, "Dockerfile")),
|
|
150
263
|
repository,
|
|
264
|
+
deploymentSource: stringRecord(manifest?.deploymentSource),
|
|
265
|
+
imageHosting: stringRecord(stringRecord(manifest?.dockerImages).hosting),
|
|
151
266
|
versionSource: versionSourceRel,
|
|
152
|
-
...developmentImageWorkflow ? {
|
|
153
|
-
developmentImageWorkflow: developmentImageWorkflow.startsWith(".github/workflows/") ? developmentImageWorkflow : `.github/workflows/${developmentImageWorkflow}`,
|
|
154
|
-
developmentImageDefaultBranch,
|
|
155
|
-
developmentImageTagPrefix,
|
|
156
|
-
developmentImageMovingTag,
|
|
157
|
-
developmentImageArchitectures,
|
|
158
|
-
developmentImageTagPattern: `${image}:${developmentImageTagPrefix}-<branch-slug>-<short-sha>`,
|
|
159
|
-
developmentImageMovingTagPattern: developmentImageMovingTag ? `${image}:${developmentImageTagPrefix}-<branch-slug>` : null,
|
|
160
|
-
developmentImageHosting: Object.keys(developmentImageHosting).length > 0 ? developmentImageHosting : null
|
|
161
|
-
} : {},
|
|
162
267
|
...hostedVerifyWorkflow ? {
|
|
163
268
|
hostedVerifyWorkflow: hostedVerifyWorkflow.startsWith(".github/workflows/") ? hostedVerifyWorkflow : `.github/workflows/${hostedVerifyWorkflow}`
|
|
269
|
+
} : {},
|
|
270
|
+
type: stringValue(manifest?.type) ?? null,
|
|
271
|
+
githubEnvironments: stringArray(manifest?.githubEnvironments),
|
|
272
|
+
requiredSecrets: stringArray(manifest?.requiredSecrets),
|
|
273
|
+
requiredVariables: stringArray(manifest?.requiredVariables),
|
|
274
|
+
workflowTemplateVersion: stringValue(manifest?.workflowTemplateVersion) ?? null,
|
|
275
|
+
...projectArchitecture ? {
|
|
276
|
+
projectArchitecture,
|
|
277
|
+
docsSiteReadiness: docsReadiness?.status ?? "site_not_prepared",
|
|
278
|
+
docsSiteDiagnostic: docsReadiness?.diagnostic ?? null
|
|
164
279
|
} : {}
|
|
165
280
|
}
|
|
166
281
|
};
|
|
167
282
|
}
|
|
168
283
|
function gitOutput(cwd, args) {
|
|
169
|
-
const result =
|
|
170
|
-
if (result.status !== 0) {
|
|
171
|
-
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
|
|
172
|
-
throw new Error(stderr || `git ${args.join(" ")} failed in ${cwd}.`);
|
|
173
|
-
}
|
|
284
|
+
const result = runTreeseedGit(args, { cwd, mode: "read" });
|
|
174
285
|
return result.stdout.trim();
|
|
175
286
|
}
|
|
287
|
+
function gitRevisionSha(cwd, revision) {
|
|
288
|
+
try {
|
|
289
|
+
return gitOutput(cwd, ["rev-parse", revision]);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
if (/^[A-Za-z0-9._/-]+$/u.test(revision) && !revision.startsWith("origin/")) {
|
|
292
|
+
try {
|
|
293
|
+
return gitOutput(cwd, ["rev-parse", `origin/${revision}`]);
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
176
300
|
function branchSlug(value) {
|
|
177
301
|
const normalized = value.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 40);
|
|
178
302
|
return normalized || "branch";
|
|
@@ -182,30 +306,58 @@ function planTreeseedPackageDevelopmentImage(root = workspaceRoot(), idOrName, {
|
|
|
182
306
|
if (!adapter) {
|
|
183
307
|
throw new Error(`Treeseed package adapter ${idOrName} was not discovered.`);
|
|
184
308
|
}
|
|
185
|
-
const
|
|
309
|
+
const firstDockerArtifact = adapter.artifacts.find((artifact) => artifact.provider === "docker") ?? null;
|
|
310
|
+
const imageName = typeof adapter.publishTarget === "string" && adapter.publishTarget.trim() ? adapter.publishTarget.trim() : firstDockerArtifact?.name ?? null;
|
|
186
311
|
if (!imageName) {
|
|
187
312
|
throw new Error(`${adapter.id} does not declare a publish image target.`);
|
|
188
313
|
}
|
|
189
314
|
const metadata = adapter.metadata;
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
const selectedBranch = branch ?? stringValue(metadata.developmentImageDefaultBranch) ?? "staging";
|
|
195
|
-
const sha = gitOutput(adapter.dir, ["rev-parse", selectedBranch]);
|
|
196
|
-
const slug = branchSlug(selectedBranch);
|
|
315
|
+
const selectedBranch = branch ?? "staging";
|
|
316
|
+
const deploymentSourceMode = deploymentSourceModeForBranch(metadata, selectedBranch);
|
|
317
|
+
const sha = gitRevisionSha(adapter.dir, selectedBranch);
|
|
197
318
|
const shortSha = sha.slice(0, 12);
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
319
|
+
const deploymentEnvironment = selectedBranch === "main" ? "prod" : selectedBranch;
|
|
320
|
+
const imagePublicationRequired = (deploymentSourceMode ?? "image") === "image";
|
|
321
|
+
if (deploymentEnvironment !== "prod" && imagePublicationRequired) {
|
|
322
|
+
throw new Error(`${adapter.id} non-production package image planning is tagless and must use deploymentSource git.`);
|
|
323
|
+
}
|
|
324
|
+
const workflow = imagePublicationRequired ? stringValue(metadata.dockerImageReleaseWorkflow)?.replace(/^\.github\/workflows\//u, "") ?? "publish.yml" : "source-build";
|
|
325
|
+
const productionImageTag = deploymentEnvironment === "prod" ? adapter.version : null;
|
|
326
|
+
if (deploymentEnvironment === "prod" && (!productionImageTag || !/^\d+\.\d+\.\d+$/u.test(productionImageTag))) {
|
|
327
|
+
throw new Error(`${adapter.id} production image publication requires a stable semantic package version.`);
|
|
328
|
+
}
|
|
329
|
+
const immutableTag = productionImageTag;
|
|
330
|
+
const movingTag = null;
|
|
331
|
+
const architectures = stringArray(metadata.dockerImageArchitectures);
|
|
332
|
+
const dockerArtifacts = Array.isArray(metadata.dockerArtifacts) ? metadata.dockerArtifacts.map((entry) => {
|
|
333
|
+
const record = stringRecord(entry);
|
|
334
|
+
const artifactImageName = stringValue(record.name);
|
|
335
|
+
if (!artifactImageName) return null;
|
|
336
|
+
return {
|
|
337
|
+
role: stringValue(record.role) ?? artifactImageName.split("/").at(-1)?.replace(/^agent-/u, "") ?? artifactImageName,
|
|
338
|
+
imageName: artifactImageName,
|
|
339
|
+
target: stringValue(record.target),
|
|
340
|
+
architectures: stringArray(record.architectures)
|
|
341
|
+
};
|
|
342
|
+
}).filter((entry) => Boolean(entry)) : [];
|
|
343
|
+
const imageHosting = stringRecord(metadata.imageHosting);
|
|
344
|
+
const app = stringValue(imageHosting.app);
|
|
345
|
+
const overrideEnvVar = stringValue(imageHosting.envVar);
|
|
346
|
+
const environment = deploymentEnvironment === "prod" ? "prod" : stringValue(imageHosting.environment) ?? selectedBranch;
|
|
347
|
+
const imageRef = immutableTag ? `${imageName}:${immutableTag}` : null;
|
|
348
|
+
const movingImageRef = null;
|
|
208
349
|
const hostingImageRef = movingImageRef ?? imageRef;
|
|
350
|
+
const roleImages = dockerArtifacts.length > 0 ? dockerArtifacts.map((artifact) => {
|
|
351
|
+
const artifactArchitectures = artifact.architectures.length > 0 ? artifact.architectures : architectures;
|
|
352
|
+
return {
|
|
353
|
+
role: artifact.role,
|
|
354
|
+
imageName: artifact.imageName,
|
|
355
|
+
target: artifact.target,
|
|
356
|
+
immutableRef: immutableTag ? `${artifact.imageName}:${immutableTag}` : null,
|
|
357
|
+
movingRef: null,
|
|
358
|
+
archImageRefs: immutableTag ? artifactArchitectures.map((arch) => `${artifact.imageName}:${immutableTag}-${arch}`) : []
|
|
359
|
+
};
|
|
360
|
+
}) : void 0;
|
|
209
361
|
return {
|
|
210
362
|
package: {
|
|
211
363
|
id: adapter.id,
|
|
@@ -222,16 +374,24 @@ function planTreeseedPackageDevelopmentImage(root = workspaceRoot(), idOrName, {
|
|
|
222
374
|
refs: {
|
|
223
375
|
imageName,
|
|
224
376
|
branch: selectedBranch,
|
|
225
|
-
branchSlug:
|
|
377
|
+
branchSlug: branchSlug(selectedBranch),
|
|
226
378
|
sha,
|
|
227
379
|
shortSha,
|
|
228
380
|
immutableTag,
|
|
229
381
|
movingTag,
|
|
230
382
|
imageRef,
|
|
231
383
|
movingImageRef,
|
|
232
|
-
archImageRefs: architectures.map((arch) => `${imageName}:${immutableTag}-${arch}`)
|
|
384
|
+
archImageRefs: immutableTag ? architectures.map((arch) => `${imageName}:${immutableTag}-${arch}`) : [],
|
|
385
|
+
...roleImages ? { roleImages } : {}
|
|
386
|
+
},
|
|
387
|
+
deploymentSource: {
|
|
388
|
+
environment: deploymentEnvironment,
|
|
389
|
+
mode: deploymentSourceMode ?? "image",
|
|
390
|
+
repository: stringValue(metadata.repository) ?? `${adapter.id}`,
|
|
391
|
+
commitSha: sha,
|
|
392
|
+
imagePublicationRequired
|
|
233
393
|
},
|
|
234
|
-
hosting: app && overrideEnvVar ? {
|
|
394
|
+
hosting: imagePublicationRequired && app && overrideEnvVar && hostingImageRef ? {
|
|
235
395
|
app,
|
|
236
396
|
environment,
|
|
237
397
|
overrideEnvVar,
|
|
@@ -260,7 +420,13 @@ function discoverTreeseedPackageAdapters(root = workspaceRoot()) {
|
|
|
260
420
|
});
|
|
261
421
|
}
|
|
262
422
|
function findTreeseedPackageAdapter(root, idOrName) {
|
|
263
|
-
|
|
423
|
+
const normalized = idOrName.trim();
|
|
424
|
+
return discoverTreeseedPackageAdapters(root).find((adapter) => {
|
|
425
|
+
const scopedId = adapter.id.startsWith("@treeseed/") ? adapter.id.slice("@treeseed/".length) : null;
|
|
426
|
+
const scopedName = adapter.name.startsWith("@treeseed/") ? adapter.name.slice("@treeseed/".length) : null;
|
|
427
|
+
const directoryName = adapter.relativeDir.split("/").at(-1);
|
|
428
|
+
return adapter.id === normalized || adapter.name === normalized || scopedId === normalized || scopedName === normalized || directoryName === normalized;
|
|
429
|
+
}) ?? null;
|
|
264
430
|
}
|
|
265
431
|
function packageAdapterPlanSummary(root = workspaceRoot()) {
|
|
266
432
|
return discoverTreeseedPackageAdapters(root).map((adapter) => ({
|
|
@@ -279,10 +445,417 @@ function packageAdapterPlanSummary(root = workspaceRoot()) {
|
|
|
279
445
|
metadata: adapter.metadata
|
|
280
446
|
}));
|
|
281
447
|
}
|
|
448
|
+
async function runTreeseedPackageImageWorkflow(options) {
|
|
449
|
+
const root = options.root ?? workspaceRoot();
|
|
450
|
+
const branch = options.branch ?? "staging";
|
|
451
|
+
const imagePlan = planTreeseedPackageDevelopmentImage(root, options.packageId, { branch });
|
|
452
|
+
const selectedWorkflow = options.workflow ?? imagePlan.workflow;
|
|
453
|
+
const execute = options.execute === true;
|
|
454
|
+
const syncConfig = options.syncConfig === true;
|
|
455
|
+
const configEnv = resolveTreeseedLaunchEnvironment({
|
|
456
|
+
tenantRoot: root,
|
|
457
|
+
scope: "staging",
|
|
458
|
+
baseEnv: options.env ?? process.env
|
|
459
|
+
});
|
|
460
|
+
const dockerHubUsername = resolveTreeseedDockerhubUsername(configEnv);
|
|
461
|
+
const dockerHubToken = resolveTreeseedDockerhubToken(configEnv);
|
|
462
|
+
const dockerHub = {
|
|
463
|
+
usernameConfigured: Boolean(dockerHubUsername),
|
|
464
|
+
tokenConfigured: Boolean(dockerHubToken),
|
|
465
|
+
requiredSecrets: imagePlan.deploymentSource?.imagePublicationRequired === false ? [] : ["TREESEED_DOCKERHUB_TOKEN"],
|
|
466
|
+
requiredVariables: imagePlan.deploymentSource?.imagePublicationRequired === false ? [] : ["TREESEED_DOCKERHUB_USERNAME"]
|
|
467
|
+
};
|
|
468
|
+
const credential = resolveGitHubCredentialForRepository(imagePlan.repository, { values: configEnv, env: options.env ?? process.env });
|
|
469
|
+
const githubClientEnv = credential.token ? { ...configEnv, TREESEED_GITHUB_TOKEN: credential.token, GH_TOKEN: credential.token, GITHUB_TOKEN: credential.token } : configEnv;
|
|
470
|
+
const report = {
|
|
471
|
+
ok: true,
|
|
472
|
+
action: execute ? "dispatch" : "plan",
|
|
473
|
+
package: imagePlan.package,
|
|
474
|
+
repository: imagePlan.repository,
|
|
475
|
+
workflow: selectedWorkflow,
|
|
476
|
+
branch: imagePlan.branch,
|
|
477
|
+
refs: imagePlan.refs,
|
|
478
|
+
deploymentSource: imagePlan.deploymentSource,
|
|
479
|
+
credential: {
|
|
480
|
+
repository: credential.repository,
|
|
481
|
+
envName: credential.envName,
|
|
482
|
+
configured: credential.configured,
|
|
483
|
+
source: credential.source,
|
|
484
|
+
fallbackUsed: credential.fallbackUsed
|
|
485
|
+
},
|
|
486
|
+
dockerHub,
|
|
487
|
+
hosting: imagePlan.hosting,
|
|
488
|
+
reconcile: {
|
|
489
|
+
lifecycle: syncConfig || execute ? ["refresh", "diff", "plan", "validate", "apply", "refresh", "verify", "persist"] : ["refresh", "diff", "plan"],
|
|
490
|
+
resources: [
|
|
491
|
+
`package-workflow:${imagePlan.package.id}`,
|
|
492
|
+
...imagePlan.deploymentSource?.imagePublicationRequired === false ? [`source-build:${imagePlan.repository}#${imagePlan.deploymentSource.commitSha}`] : imagePlan.refs.roleImages ? imagePlan.refs.roleImages.map((entry) => `package-image:${entry.imageName}`) : [`package-image:${imagePlan.refs.imageName}`]
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
if (syncConfig) {
|
|
497
|
+
const environment = imagePlan.hosting?.environment ?? "staging";
|
|
498
|
+
report.syncedConfig = {
|
|
499
|
+
environment,
|
|
500
|
+
blocked: true,
|
|
501
|
+
reason: imagePlan.deploymentSource?.imagePublicationRequired === false ? "Staging source-build policy does not sync Docker image credentials or image override variables." : "Package image config sync is reconciler-owned. Use trsd package image --sync-config so github-secret-binding and github-variable-binding resources apply through adapters.",
|
|
502
|
+
secrets: dockerHubToken ? [{ name: "TREESEED_DOCKERHUB_TOKEN", existed: null }] : [],
|
|
503
|
+
variables: dockerHubUsername ? [{ name: "TREESEED_DOCKERHUB_USERNAME", existed: null }] : []
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
if (execute) {
|
|
507
|
+
const client = createGitHubApiClient({ env: githubClientEnv });
|
|
508
|
+
report.dispatch = {
|
|
509
|
+
blocked: true,
|
|
510
|
+
reason: imagePlan.deploymentSource?.imagePublicationRequired === false ? "Staging deployment source is GitHub source build; routine development Docker image publication is disabled." : "Package image workflow dispatch is reconciler-owned. Use trsd package image --execute so github-workflow-dispatch/package-image resources apply through adapters."
|
|
511
|
+
};
|
|
512
|
+
if (imagePlan.deploymentSource?.imagePublicationRequired !== false) {
|
|
513
|
+
report.latestWorkflowRun = await getLatestGitHubWorkflowRun(imagePlan.repository, {
|
|
514
|
+
client,
|
|
515
|
+
workflow: selectedWorkflow,
|
|
516
|
+
branch: imagePlan.branch
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return { imagePlan, selectedWorkflow, dockerHub, credential, report };
|
|
521
|
+
}
|
|
522
|
+
function validateTreeseedPackageManifests(root = workspaceRoot()) {
|
|
523
|
+
return discoverTreeseedPackageAdapters(root).map((adapter) => {
|
|
524
|
+
const errors = [];
|
|
525
|
+
const warnings = [];
|
|
526
|
+
if (!adapter.manifestPath || adapter.manifestPath.endsWith("package.json")) {
|
|
527
|
+
errors.push("missing treeseed.package.yaml");
|
|
528
|
+
}
|
|
529
|
+
if (!adapter.id.trim()) errors.push("missing package id");
|
|
530
|
+
if (!adapter.name.trim()) errors.push("missing package name");
|
|
531
|
+
if (!["node-typescript", "beam-elixir-rust"].includes(adapter.kind)) {
|
|
532
|
+
errors.push(`unsupported package kind ${adapter.kind}`);
|
|
533
|
+
}
|
|
534
|
+
if (adapter.verifyCommands.local == null) {
|
|
535
|
+
errors.push("missing local verification command");
|
|
536
|
+
}
|
|
537
|
+
if (!adapter.metadata.projectArchitecture) {
|
|
538
|
+
warnings.push("package does not declare projectArchitecture metadata");
|
|
539
|
+
}
|
|
540
|
+
if (adapter.releaseChecks.length === 0) {
|
|
541
|
+
warnings.push("package declares no release checks");
|
|
542
|
+
}
|
|
543
|
+
const hasDockerArtifact = adapter.artifacts.some((artifact) => artifact.provider === "docker");
|
|
544
|
+
if (hasDockerArtifact) {
|
|
545
|
+
const deploymentSource = stringRecord(adapter.metadata.deploymentSource);
|
|
546
|
+
if (stringValue(deploymentSource.staging) !== "git") {
|
|
547
|
+
errors.push("docker package must declare deploymentSource.staging: git");
|
|
548
|
+
}
|
|
549
|
+
if (stringValue(deploymentSource.prod) !== "image") {
|
|
550
|
+
errors.push("docker package must declare deploymentSource.prod: image");
|
|
551
|
+
}
|
|
552
|
+
const architectures = stringArray(adapter.metadata.dockerImageArchitectures);
|
|
553
|
+
if (!architectures.includes("amd64") || !architectures.includes("arm64")) {
|
|
554
|
+
errors.push("docker package must declare amd64 and arm64 architectures");
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
for (const artifact of adapter.artifacts) {
|
|
558
|
+
if (artifact.provider === "docker" && !artifact.name.startsWith("treeseed/")) {
|
|
559
|
+
errors.push(`docker artifact ${artifact.name} must publish under treeseed/*`);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
packageId: adapter.id,
|
|
564
|
+
path: adapter.relativeDir,
|
|
565
|
+
manifestPath: adapter.manifestPath,
|
|
566
|
+
ok: errors.length === 0,
|
|
567
|
+
errors,
|
|
568
|
+
warnings
|
|
569
|
+
};
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
function deriveTreeseedPackageProjectResources(root = workspaceRoot(), options = {}) {
|
|
573
|
+
const team = options.team ?? "team:treeseed";
|
|
574
|
+
return discoverTreeseedPackageAdapters(root).map((adapter) => {
|
|
575
|
+
const architecture = adapter.metadata.projectArchitecture;
|
|
576
|
+
const repository = stringValue(adapter.metadata.repository);
|
|
577
|
+
if (!architecture || !repository) return null;
|
|
578
|
+
const [owner, name] = repository.split("/");
|
|
579
|
+
if (!owner || !name) return null;
|
|
580
|
+
const slug = normalizePackageSlug(adapter.id);
|
|
581
|
+
return {
|
|
582
|
+
key: `project:treeseed/${slug}`,
|
|
583
|
+
team,
|
|
584
|
+
slug,
|
|
585
|
+
name: adapter.name,
|
|
586
|
+
description: `${adapter.name} first-party package project.`,
|
|
587
|
+
kind: "package",
|
|
588
|
+
repository: {
|
|
589
|
+
role: "primary",
|
|
590
|
+
provider: "github",
|
|
591
|
+
owner,
|
|
592
|
+
name,
|
|
593
|
+
gitUrl: `https://github.com/${owner}/${name}.git`,
|
|
594
|
+
defaultBranch: "main",
|
|
595
|
+
checkoutPath: adapter.relativeDir
|
|
596
|
+
},
|
|
597
|
+
architecture,
|
|
598
|
+
metadata: {
|
|
599
|
+
packageId: adapter.id,
|
|
600
|
+
packagePath: adapter.relativeDir,
|
|
601
|
+
visibility: "public",
|
|
602
|
+
docsSiteReadiness: stringValue(adapter.metadata.docsSiteReadiness) ?? "site_not_prepared",
|
|
603
|
+
releaseOwnership: "treeseed.package.yaml"
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
}).filter((entry) => Boolean(entry));
|
|
607
|
+
}
|
|
608
|
+
function workflowNameForTemplate(adapter, template) {
|
|
609
|
+
const publishWorkflow = "publish.yml";
|
|
610
|
+
const configuredReleaseGate = stringValue(adapter.metadata.hostedVerifyWorkflow)?.replace(/^\.github\/workflows\//u, "") ?? "verify.yml";
|
|
611
|
+
if (template === "docker-image") return publishWorkflow;
|
|
612
|
+
if (template === "release-gate") {
|
|
613
|
+
return configuredReleaseGate === publishWorkflow ? "release-gate.yml" : configuredReleaseGate;
|
|
614
|
+
}
|
|
615
|
+
return publishWorkflow;
|
|
616
|
+
}
|
|
617
|
+
function renderTreeseedPackageWorkflow(adapter, template) {
|
|
618
|
+
const verifyCommand = template === "release-gate" ? adapter.verifyCommands.release ?? adapter.verifyCommands.local : adapter.verifyCommands.local;
|
|
619
|
+
const verify = verifyCommand ? formatWorkflowRunCommand(verifyCommand.command, verifyCommand.args) : "npm run verify:local";
|
|
620
|
+
const setup = resolveWorkflowSetupCommand(adapter);
|
|
621
|
+
const dockerArtifacts = adapter.artifacts.filter((artifact) => artifact.provider === "docker");
|
|
622
|
+
if (template === "npm-publish") {
|
|
623
|
+
return `name: Publish ${adapter.name}
|
|
624
|
+
|
|
625
|
+
on:
|
|
626
|
+
push:
|
|
627
|
+
tags:
|
|
628
|
+
- "*.*.*"
|
|
629
|
+
workflow_dispatch:
|
|
630
|
+
|
|
631
|
+
jobs:
|
|
632
|
+
publish:
|
|
633
|
+
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')
|
|
634
|
+
runs-on: ubuntu-latest
|
|
635
|
+
permissions:
|
|
636
|
+
contents: write
|
|
637
|
+
environment: production
|
|
638
|
+
steps:
|
|
639
|
+
- uses: actions/checkout@v4
|
|
640
|
+
with:
|
|
641
|
+
submodules: recursive
|
|
642
|
+
- uses: actions/setup-node@v4
|
|
643
|
+
with:
|
|
644
|
+
node-version: 22
|
|
645
|
+
registry-url: https://registry.npmjs.org
|
|
646
|
+
- run: ${setup}
|
|
647
|
+
- run: ${verify}
|
|
648
|
+
- run: npm publish --access public
|
|
649
|
+
env:
|
|
650
|
+
NODE_AUTH_TOKEN: \${{ secrets.NPM_TOKEN }}
|
|
651
|
+
- name: Create GitHub release
|
|
652
|
+
env:
|
|
653
|
+
GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
654
|
+
run: gh release create "\${GITHUB_REF_NAME}" --generate-notes --verify-tag
|
|
655
|
+
`;
|
|
656
|
+
}
|
|
657
|
+
if (template === "docker-image") {
|
|
658
|
+
const environment = "production";
|
|
659
|
+
const imageSetup = adapter.kind === "node-typescript" ? resolveDockerImageWorkflowSetupCommand() : null;
|
|
660
|
+
const anyTarget = dockerArtifacts.some((artifact) => typeof artifact.target === "string" && artifact.target.trim().length > 0);
|
|
661
|
+
const dockerContextPrepareCommand = isRecord(adapter.metadata.scripts) && typeof adapter.metadata.scripts["capacity-provider:build"] === "string" ? "npm run capacity-provider:build -- --prepare-only" : null;
|
|
662
|
+
const trigger = ` tags:
|
|
663
|
+
- "*.*.*"`;
|
|
664
|
+
const jobCondition = "startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')";
|
|
665
|
+
const computeTagsStep = ` - name: Compute image tags
|
|
666
|
+
id: tags
|
|
667
|
+
run: |
|
|
668
|
+
version="\${GITHUB_REF_NAME#v}"
|
|
669
|
+
echo "base=\${version}" >> "$GITHUB_OUTPUT"
|
|
670
|
+
echo "moving=" >> "$GITHUB_OUTPUT"
|
|
671
|
+
`;
|
|
672
|
+
const releaseStep = ` release:
|
|
673
|
+
needs: manifest
|
|
674
|
+
if: ${jobCondition}
|
|
675
|
+
runs-on: ubuntu-24.04
|
|
676
|
+
permissions:
|
|
677
|
+
contents: write
|
|
678
|
+
steps:
|
|
679
|
+
- uses: actions/checkout@v4
|
|
680
|
+
- name: Create GitHub release
|
|
681
|
+
env:
|
|
682
|
+
GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
683
|
+
run: gh release create "\${GITHUB_REF_NAME}" --generate-notes --verify-tag
|
|
684
|
+
`;
|
|
685
|
+
return `name: Publish Image ${adapter.name}
|
|
686
|
+
|
|
687
|
+
on:
|
|
688
|
+
workflow_dispatch:
|
|
689
|
+
push:
|
|
690
|
+
${trigger}
|
|
691
|
+
|
|
692
|
+
jobs:
|
|
693
|
+
build:
|
|
694
|
+
if: ${jobCondition}
|
|
695
|
+
runs-on: \${{ matrix.runner }}
|
|
696
|
+
permissions:
|
|
697
|
+
contents: write
|
|
698
|
+
packages: write
|
|
699
|
+
environment: ${environment}
|
|
700
|
+
strategy:
|
|
701
|
+
matrix:
|
|
702
|
+
include:
|
|
703
|
+
${dockerArtifacts.flatMap((artifact) => [
|
|
704
|
+
` - image: ${artifact.name}${anyTarget ? `
|
|
705
|
+
target: ${artifact.target ?? ""}` : ""}
|
|
706
|
+
arch: amd64
|
|
707
|
+
platform: linux/amd64
|
|
708
|
+
runner: ubuntu-24.04`,
|
|
709
|
+
` - image: ${artifact.name}${anyTarget ? `
|
|
710
|
+
target: ${artifact.target ?? ""}` : ""}
|
|
711
|
+
arch: arm64
|
|
712
|
+
platform: linux/arm64
|
|
713
|
+
runner: ubuntu-24.04-arm`
|
|
714
|
+
]).join("\n") || ` - image: treeseed/unknown
|
|
715
|
+
arch: amd64
|
|
716
|
+
platform: linux/amd64
|
|
717
|
+
runner: ubuntu-24.04`}
|
|
718
|
+
steps:
|
|
719
|
+
- uses: actions/checkout@v4
|
|
720
|
+
with:
|
|
721
|
+
submodules: recursive
|
|
722
|
+
${imageSetup ? ` - run: ${imageSetup}
|
|
723
|
+
` : ""}${dockerContextPrepareCommand ? ` - run: ${dockerContextPrepareCommand}
|
|
724
|
+
` : ""}${computeTagsStep} - uses: docker/setup-buildx-action@v3
|
|
725
|
+
- uses: docker/login-action@v3
|
|
726
|
+
with:
|
|
727
|
+
username: \${{ vars.TREESEED_DOCKERHUB_USERNAME }}
|
|
728
|
+
password: \${{ secrets.TREESEED_DOCKERHUB_TOKEN }}
|
|
729
|
+
- uses: docker/build-push-action@v6
|
|
730
|
+
with:
|
|
731
|
+
context: .
|
|
732
|
+
${anyTarget ? " target: ${{ matrix.target }}\n" : ""} platforms: \${{ matrix.platform }}
|
|
733
|
+
push: true
|
|
734
|
+
tags: \${{ matrix.image }}:\${{ steps.tags.outputs.base }}-\${{ matrix.arch }}
|
|
735
|
+
|
|
736
|
+
manifest:
|
|
737
|
+
needs: build
|
|
738
|
+
if: ${jobCondition}
|
|
739
|
+
runs-on: ubuntu-24.04
|
|
740
|
+
permissions:
|
|
741
|
+
contents: read
|
|
742
|
+
packages: write
|
|
743
|
+
environment: ${environment}
|
|
744
|
+
strategy:
|
|
745
|
+
matrix:
|
|
746
|
+
include:
|
|
747
|
+
${dockerArtifacts.map((artifact) => ` - image: ${artifact.name}`).join("\n") || " - image: treeseed/unknown"}
|
|
748
|
+
steps:
|
|
749
|
+
- uses: docker/setup-buildx-action@v3
|
|
750
|
+
- uses: docker/login-action@v3
|
|
751
|
+
with:
|
|
752
|
+
username: \${{ vars.TREESEED_DOCKERHUB_USERNAME }}
|
|
753
|
+
password: \${{ secrets.TREESEED_DOCKERHUB_TOKEN }}
|
|
754
|
+
${computeTagsStep} - name: Publish multi-architecture manifest
|
|
755
|
+
run: |
|
|
756
|
+
docker buildx imagetools create \\
|
|
757
|
+
-t "\${{ matrix.image }}:\${{ steps.tags.outputs.base }}" \\
|
|
758
|
+
"\${{ matrix.image }}:\${{ steps.tags.outputs.base }}-amd64" \\
|
|
759
|
+
"\${{ matrix.image }}:\${{ steps.tags.outputs.base }}-arm64"
|
|
760
|
+
${releaseStep}`;
|
|
761
|
+
}
|
|
762
|
+
const needsNodeSetup = adapter.kind === "node-typescript";
|
|
763
|
+
const needsBeamSetup = adapter.kind === "beam-elixir-rust";
|
|
764
|
+
return `name: Verify ${adapter.name}
|
|
765
|
+
|
|
766
|
+
on:
|
|
767
|
+
push:
|
|
768
|
+
pull_request:
|
|
769
|
+
workflow_dispatch:
|
|
770
|
+
|
|
771
|
+
jobs:
|
|
772
|
+
verify:
|
|
773
|
+
runs-on: ubuntu-latest
|
|
774
|
+
steps:
|
|
775
|
+
- uses: actions/checkout@v4
|
|
776
|
+
with:
|
|
777
|
+
submodules: recursive
|
|
778
|
+
${needsNodeSetup ? ` - uses: actions/setup-node@v4
|
|
779
|
+
with:
|
|
780
|
+
node-version: 22
|
|
781
|
+
- run: ${setup}
|
|
782
|
+
` : ""}${needsBeamSetup ? ` - uses: erlef/setup-beam@v1
|
|
783
|
+
with:
|
|
784
|
+
otp-version: "27"
|
|
785
|
+
elixir-version: "1.17.3"
|
|
786
|
+
- run: mix local.hex --force && mix local.rebar --force
|
|
787
|
+
` : ""} - run: ${verify}
|
|
788
|
+
`;
|
|
789
|
+
}
|
|
790
|
+
function resolveWorkflowSetupCommand(adapter) {
|
|
791
|
+
const scripts = adapter.metadata.scripts;
|
|
792
|
+
if (isRecord(scripts) && typeof scripts["release:setup"] === "string") {
|
|
793
|
+
return 'npm run release:setup || (echo "dependency install failed; retrying" && npm run release:setup)';
|
|
794
|
+
}
|
|
795
|
+
return 'npm ci || (echo "dependency install failed; retrying" && npm ci)';
|
|
796
|
+
}
|
|
797
|
+
function resolveDockerImageWorkflowSetupCommand() {
|
|
798
|
+
return 'npm ci --ignore-scripts || (echo "dependency install failed; retrying" && npm ci --ignore-scripts)';
|
|
799
|
+
}
|
|
800
|
+
function isRecord(value) {
|
|
801
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
802
|
+
}
|
|
803
|
+
function formatWorkflowRunCommand(command, args) {
|
|
804
|
+
return [command, ...args].map(shellQuoteWorkflowArg).join(" ");
|
|
805
|
+
}
|
|
806
|
+
function shellQuoteWorkflowArg(value) {
|
|
807
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/u.test(value)) return value;
|
|
808
|
+
return `'${value.replace(/'/gu, `'\\''`)}'`;
|
|
809
|
+
}
|
|
810
|
+
function workflowTemplatesForAdapter(adapter) {
|
|
811
|
+
const hasDocker = adapter.artifacts.some((artifact) => artifact.provider === "docker");
|
|
812
|
+
const hasNpm = adapter.artifacts.some((artifact) => artifact.provider === "npm");
|
|
813
|
+
return [
|
|
814
|
+
...hasNpm ? ["npm-publish"] : [],
|
|
815
|
+
...hasDocker ? ["docker-image"] : [],
|
|
816
|
+
"release-gate"
|
|
817
|
+
];
|
|
818
|
+
}
|
|
819
|
+
function syncTreeseedPackageWorkflows({
|
|
820
|
+
root = workspaceRoot(),
|
|
821
|
+
packageId,
|
|
822
|
+
execute = false
|
|
823
|
+
} = {}) {
|
|
824
|
+
const adapters = packageId && packageId !== "all" ? [findTreeseedPackageAdapter(root, packageId)].filter((entry) => Boolean(entry)) : discoverTreeseedPackageAdapters(root);
|
|
825
|
+
const results = [];
|
|
826
|
+
for (const adapter of adapters) {
|
|
827
|
+
for (const template of workflowTemplatesForAdapter(adapter)) {
|
|
828
|
+
const workflow = workflowNameForTemplate(adapter, template);
|
|
829
|
+
const path = resolve(adapter.dir, ".github", "workflows", workflow);
|
|
830
|
+
const rendered = renderTreeseedPackageWorkflow(adapter, template);
|
|
831
|
+
const current = existsSync(path) ? readFileSync(path, "utf8") : null;
|
|
832
|
+
const changed = current !== rendered;
|
|
833
|
+
if (execute && changed) {
|
|
834
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
835
|
+
writeFileSync(path, rendered, "utf8");
|
|
836
|
+
}
|
|
837
|
+
results.push({
|
|
838
|
+
packageId: adapter.id,
|
|
839
|
+
path,
|
|
840
|
+
workflow,
|
|
841
|
+
template,
|
|
842
|
+
exists: current != null,
|
|
843
|
+
changed,
|
|
844
|
+
written: execute && changed
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return results;
|
|
849
|
+
}
|
|
282
850
|
export {
|
|
851
|
+
deriveTreeseedPackageProjectResources,
|
|
283
852
|
discoverTreeseedPackageAdapters,
|
|
284
853
|
findTreeseedPackageAdapter,
|
|
285
854
|
packageAdapterPlanSummary,
|
|
286
855
|
planTreeseedPackageDevelopmentImage,
|
|
287
|
-
readMixProjectVersion
|
|
856
|
+
readMixProjectVersion,
|
|
857
|
+
renderTreeseedPackageWorkflow,
|
|
858
|
+
runTreeseedPackageImageWorkflow,
|
|
859
|
+
syncTreeseedPackageWorkflows,
|
|
860
|
+
validateTreeseedPackageManifests
|
|
288
861
|
};
|