@tdk-landscape/tdk-cli-core 1.3.53 → 1.3.55
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 +9 -0
- package/README.md +1 -1
- package/cli/dist/commands/doctor.js +21 -3
- package/cli/dist/commands/upgrade.js +7 -7
- package/cli/dist/generator/extension-fetch.js +16 -9
- package/cli/dist/utils/spinner.js +39 -0
- package/cli/package.json +1 -2
- package/package.json +16 -2
- package/.claude/skills/layer-autoresearch/SKILL.md +0 -48
- package/.claude/skills/tdk-troubleshoot/SKILL.md +0 -222
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -40
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -18
- package/.github/ISSUE_TEMPLATE/premium_license.yml +0 -43
- package/.github/dependabot.yml +0 -33
- package/.github/pull_request_template.md +0 -5
- package/.github/workflows/ci.yml +0 -200
- package/.github/workflows/release-binaries.yml +0 -139
- package/.github/zizmor.yml +0 -9
- package/.pre-commit-config.yaml +0 -57
- package/CODE_OF_CONDUCT.md +0 -9
- package/CONTRIBUTING.md +0 -42
- package/Makefile +0 -92
- package/SECURITY.md +0 -17
- package/benchmarks/results/container-scale-2026-09-25T20-54-49-736Z.json +0 -45
- package/benchmarks/results/container-scale-2026-09-25T21-01-20-540Z.json +0 -150
- package/benchmarks/results/container-scale-2026-09-25T21-15-01-441Z.json +0 -73
- package/benchmarks/results/container-scale-2026-09-25T22-09-01-630Z.json +0 -77
- package/benchmarks/results/container-scale-2026-09-25T22-18-28-371Z.json +0 -202
- package/cli/AGENTS.md +0 -390
- package/cli/DESIGN.md +0 -735
- package/cli/README.md +0 -292
- package/cli/biome.json +0 -40
- package/cli/dependency-graph.svg +0 -1135
- package/cli/dist/cli.d.ts +0 -3
- package/cli/dist/cli.d.ts.map +0 -1
- package/cli/dist/cli.js.map +0 -1
- package/cli/dist/commands/completion.d.ts +0 -3
- package/cli/dist/commands/completion.d.ts.map +0 -1
- package/cli/dist/commands/completion.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -3
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -19
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/down.d.ts +0 -3
- package/cli/dist/commands/down.d.ts.map +0 -1
- package/cli/dist/commands/down.js.map +0 -1
- package/cli/dist/commands/help.d.ts +0 -2
- package/cli/dist/commands/help.d.ts.map +0 -1
- package/cli/dist/commands/help.js.map +0 -1
- package/cli/dist/commands/networks.d.ts +0 -3
- package/cli/dist/commands/networks.d.ts.map +0 -1
- package/cli/dist/commands/networks.js.map +0 -1
- package/cli/dist/commands/project.d.ts +0 -9
- package/cli/dist/commands/project.d.ts.map +0 -1
- package/cli/dist/commands/project.js.map +0 -1
- package/cli/dist/commands/projects.d.ts +0 -3
- package/cli/dist/commands/projects.d.ts.map +0 -1
- package/cli/dist/commands/projects.js.map +0 -1
- package/cli/dist/commands/resource.d.ts +0 -69
- package/cli/dist/commands/resource.d.ts.map +0 -1
- package/cli/dist/commands/resource.js.map +0 -1
- package/cli/dist/commands/resources.d.ts +0 -3
- package/cli/dist/commands/resources.d.ts.map +0 -1
- package/cli/dist/commands/resources.js.map +0 -1
- package/cli/dist/commands/stack.d.ts +0 -3
- package/cli/dist/commands/stack.d.ts.map +0 -1
- package/cli/dist/commands/stack.js.map +0 -1
- package/cli/dist/commands/stacks.d.ts +0 -3
- package/cli/dist/commands/stacks.d.ts.map +0 -1
- package/cli/dist/commands/stacks.js.map +0 -1
- package/cli/dist/commands/status.d.ts +0 -3
- package/cli/dist/commands/status.d.ts.map +0 -1
- package/cli/dist/commands/status.js.map +0 -1
- package/cli/dist/commands/ui.d.ts +0 -3
- package/cli/dist/commands/ui.d.ts.map +0 -1
- package/cli/dist/commands/ui.js.map +0 -1
- package/cli/dist/commands/up.d.ts +0 -3
- package/cli/dist/commands/up.d.ts.map +0 -1
- package/cli/dist/commands/up.js.map +0 -1
- package/cli/dist/commands/upgrade.d.ts +0 -14
- package/cli/dist/commands/upgrade.d.ts.map +0 -1
- package/cli/dist/commands/upgrade.js.map +0 -1
- package/cli/dist/commands/version.d.ts +0 -3
- package/cli/dist/commands/version.d.ts.map +0 -1
- package/cli/dist/commands/version.js.map +0 -1
- package/cli/dist/components/Accessible.d.ts +0 -8
- package/cli/dist/components/Accessible.d.ts.map +0 -1
- package/cli/dist/components/Accessible.js.map +0 -1
- package/cli/dist/components/BaseTooltip.d.ts +0 -4
- package/cli/dist/components/BaseTooltip.d.ts.map +0 -1
- package/cli/dist/components/BaseTooltip.js.map +0 -1
- package/cli/dist/components/DetailPanel.d.ts +0 -4
- package/cli/dist/components/DetailPanel.d.ts.map +0 -1
- package/cli/dist/components/DetailPanel.js.map +0 -1
- package/cli/dist/components/FileTree.d.ts +0 -4
- package/cli/dist/components/FileTree.d.ts.map +0 -1
- package/cli/dist/components/FileTree.js.map +0 -1
- package/cli/dist/components/ResourceSelectInput.d.ts +0 -4
- package/cli/dist/components/ResourceSelectInput.d.ts.map +0 -1
- package/cli/dist/components/ResourceSelectInput.js.map +0 -1
- package/cli/dist/components/ResourceTable.d.ts +0 -4
- package/cli/dist/components/ResourceTable.d.ts.map +0 -1
- package/cli/dist/components/ResourceTable.js.map +0 -1
- package/cli/dist/components/TabBar.d.ts +0 -4
- package/cli/dist/components/TabBar.d.ts.map +0 -1
- package/cli/dist/components/TabBar.js.map +0 -1
- package/cli/dist/components/Tooltip.d.ts +0 -12
- package/cli/dist/components/Tooltip.d.ts.map +0 -1
- package/cli/dist/components/Tooltip.js.map +0 -1
- package/cli/dist/components/index.d.ts +0 -8
- package/cli/dist/components/index.d.ts.map +0 -1
- package/cli/dist/components/index.js.map +0 -1
- package/cli/dist/config/platform-standards.d.ts +0 -159
- package/cli/dist/config/platform-standards.d.ts.map +0 -1
- package/cli/dist/config/platform-standards.js.map +0 -1
- package/cli/dist/generator/extension-fetch.d.ts +0 -25
- package/cli/dist/generator/extension-fetch.d.ts.map +0 -1
- package/cli/dist/generator/extension-fetch.js.map +0 -1
- package/cli/dist/generator/template-engine.d.ts +0 -62
- package/cli/dist/generator/template-engine.d.ts.map +0 -1
- package/cli/dist/generator/template-engine.js.map +0 -1
- package/cli/dist/index.d.ts +0 -11
- package/cli/dist/index.d.ts.map +0 -1
- package/cli/dist/index.js.map +0 -1
- package/cli/dist/types/index.d.ts +0 -257
- package/cli/dist/types/index.d.ts.map +0 -1
- package/cli/dist/types/index.js.map +0 -1
- package/cli/dist/utils/cache.d.ts +0 -19
- package/cli/dist/utils/cache.d.ts.map +0 -1
- package/cli/dist/utils/cache.js.map +0 -1
- package/cli/dist/utils/command-helpers.d.ts +0 -17
- package/cli/dist/utils/command-helpers.d.ts.map +0 -1
- package/cli/dist/utils/command-helpers.js.map +0 -1
- package/cli/dist/utils/constants.d.ts +0 -53
- package/cli/dist/utils/constants.d.ts.map +0 -1
- package/cli/dist/utils/constants.js.map +0 -1
- package/cli/dist/utils/discovery-context.d.ts +0 -4
- package/cli/dist/utils/discovery-context.d.ts.map +0 -1
- package/cli/dist/utils/discovery-context.js.map +0 -1
- package/cli/dist/utils/docker.d.ts +0 -4
- package/cli/dist/utils/docker.d.ts.map +0 -1
- package/cli/dist/utils/docker.js.map +0 -1
- package/cli/dist/utils/doctor-runtime.d.ts +0 -81
- package/cli/dist/utils/doctor-runtime.d.ts.map +0 -1
- package/cli/dist/utils/doctor-runtime.js.map +0 -1
- package/cli/dist/utils/env-validator.d.ts +0 -15
- package/cli/dist/utils/env-validator.d.ts.map +0 -1
- package/cli/dist/utils/env-validator.js.map +0 -1
- package/cli/dist/utils/errors.d.ts +0 -31
- package/cli/dist/utils/errors.d.ts.map +0 -1
- package/cli/dist/utils/errors.js.map +0 -1
- package/cli/dist/utils/file-helpers.d.ts +0 -14
- package/cli/dist/utils/file-helpers.d.ts.map +0 -1
- package/cli/dist/utils/file-helpers.js.map +0 -1
- package/cli/dist/utils/formatting.d.ts +0 -30
- package/cli/dist/utils/formatting.d.ts.map +0 -1
- package/cli/dist/utils/formatting.js.map +0 -1
- package/cli/dist/utils/paths.d.ts +0 -3
- package/cli/dist/utils/paths.d.ts.map +0 -1
- package/cli/dist/utils/paths.js.map +0 -1
- package/cli/dist/utils/port-assignment.d.ts +0 -6
- package/cli/dist/utils/port-assignment.d.ts.map +0 -1
- package/cli/dist/utils/port-assignment.js.map +0 -1
- package/cli/dist/utils/project-features.d.ts +0 -23
- package/cli/dist/utils/project-features.d.ts.map +0 -1
- package/cli/dist/utils/project-features.js.map +0 -1
- package/cli/dist/utils/project-templates.d.ts +0 -7
- package/cli/dist/utils/project-templates.d.ts.map +0 -1
- package/cli/dist/utils/project-templates.js.map +0 -1
- package/cli/dist/utils/prompt.d.ts +0 -28
- package/cli/dist/utils/prompt.d.ts.map +0 -1
- package/cli/dist/utils/prompt.js.map +0 -1
- package/cli/dist/utils/resource-features.d.ts +0 -29
- package/cli/dist/utils/resource-features.d.ts.map +0 -1
- package/cli/dist/utils/resource-features.js.map +0 -1
- package/cli/dist/utils/service-urls.d.ts +0 -30
- package/cli/dist/utils/service-urls.d.ts.map +0 -1
- package/cli/dist/utils/service-urls.js.map +0 -1
- package/cli/dist/utils/services.d.ts +0 -18
- package/cli/dist/utils/services.d.ts.map +0 -1
- package/cli/dist/utils/services.js.map +0 -1
- package/cli/dist/utils/stack-features.d.ts +0 -22
- package/cli/dist/utils/stack-features.d.ts.map +0 -1
- package/cli/dist/utils/stack-features.js.map +0 -1
- package/cli/dist/utils/tar.d.ts +0 -7
- package/cli/dist/utils/tar.d.ts.map +0 -1
- package/cli/dist/utils/tar.js.map +0 -1
- package/cli/dist/utils/tilt.d.ts +0 -20
- package/cli/dist/utils/tilt.d.ts.map +0 -1
- package/cli/dist/utils/tilt.js.map +0 -1
- package/cli/dist/utils/validation.d.ts +0 -16
- package/cli/dist/utils/validation.d.ts.map +0 -1
- package/cli/dist/utils/validation.js.map +0 -1
- package/cli/knip.json +0 -6
- package/cli/pnpm-lock.yaml +0 -2305
- package/cli/pnpm-workspace.yaml +0 -2
- package/cli/src/cli.ts +0 -72
- package/cli/src/commands/__tests__/always-enabled-infra.test.ts +0 -109
- package/cli/src/commands/__tests__/config.test.ts +0 -146
- package/cli/src/commands/__tests__/doctor.test.ts +0 -730
- package/cli/src/commands/__tests__/error-handling.test.ts +0 -78
- package/cli/src/commands/__tests__/phases-model.test.ts +0 -161
- package/cli/src/commands/__tests__/project-resource-features-e2e.test.ts +0 -187
- package/cli/src/commands/__tests__/project.test.ts +0 -68
- package/cli/src/commands/__tests__/resource.test.ts +0 -226
- package/cli/src/commands/__tests__/saas-starter-integration.test.ts +0 -194
- package/cli/src/commands/__tests__/stack-features-e2e.test.ts +0 -135
- package/cli/src/commands/__tests__/upgrade.test.ts +0 -198
- package/cli/src/commands/completion.ts +0 -300
- package/cli/src/commands/config.ts +0 -299
- package/cli/src/commands/doctor.ts +0 -926
- package/cli/src/commands/down.ts +0 -37
- package/cli/src/commands/help.ts +0 -143
- package/cli/src/commands/networks-design.md +0 -80
- package/cli/src/commands/networks.ts +0 -332
- package/cli/src/commands/project.ts +0 -456
- package/cli/src/commands/projects.ts +0 -82
- package/cli/src/commands/resource.ts +0 -652
- package/cli/src/commands/resources.ts +0 -95
- package/cli/src/commands/stack.ts +0 -128
- package/cli/src/commands/stacks.ts +0 -52
- package/cli/src/commands/status.ts +0 -88
- package/cli/src/commands/ui.tsx +0 -843
- package/cli/src/commands/up.ts +0 -169
- package/cli/src/commands/upgrade.ts +0 -628
- package/cli/src/commands/version.ts +0 -9
- package/cli/src/components/Accessible.tsx +0 -21
- package/cli/src/components/BaseTooltip.tsx +0 -66
- package/cli/src/components/DetailPanel.tsx +0 -146
- package/cli/src/components/FileTree.tsx +0 -89
- package/cli/src/components/ResourceSelectInput.tsx +0 -30
- package/cli/src/components/ResourceTable.tsx +0 -78
- package/cli/src/components/TabBar.tsx +0 -53
- package/cli/src/components/Tooltip.tsx +0 -11
- package/cli/src/components/index.ts +0 -7
- package/cli/src/config/platform-standards.test.ts +0 -11
- package/cli/src/config/platform-standards.ts +0 -196
- package/cli/src/generator/__tests__/extension-fetch.test.ts +0 -242
- package/cli/src/generator/__tests__/template-engine.test.ts +0 -70
- package/cli/src/generator/extension-fetch.ts +0 -286
- package/cli/src/generator/template-engine.ts +0 -752
- package/cli/src/index.ts +0 -86
- package/cli/src/templates.d.ts +0 -4
- package/cli/src/types/index.ts +0 -353
- package/cli/src/utils/__tests__/cache.test.ts +0 -98
- package/cli/src/utils/__tests__/formatting.test.ts +0 -170
- package/cli/src/utils/__tests__/paths.test.ts +0 -180
- package/cli/src/utils/__tests__/port-assignment.test.ts +0 -121
- package/cli/src/utils/__tests__/service-urls.test.ts +0 -174
- package/cli/src/utils/__tests__/services.test.ts +0 -531
- package/cli/src/utils/__tests__/tilt.test.ts +0 -172
- package/cli/src/utils/__tests__/validation.test.ts +0 -148
- package/cli/src/utils/cache.ts +0 -76
- package/cli/src/utils/command-helpers.ts +0 -54
- package/cli/src/utils/constants.ts +0 -130
- package/cli/src/utils/discovery-context.ts +0 -49
- package/cli/src/utils/docker.ts +0 -20
- package/cli/src/utils/doctor-runtime.ts +0 -644
- package/cli/src/utils/env-validator.ts +0 -139
- package/cli/src/utils/errors.ts +0 -168
- package/cli/src/utils/file-helpers.ts +0 -62
- package/cli/src/utils/formatting.ts +0 -215
- package/cli/src/utils/paths.ts +0 -53
- package/cli/src/utils/port-assignment.ts +0 -106
- package/cli/src/utils/project-features.ts +0 -118
- package/cli/src/utils/project-templates.ts +0 -29
- package/cli/src/utils/prompt.ts +0 -128
- package/cli/src/utils/resource-features.ts +0 -215
- package/cli/src/utils/service-urls.ts +0 -124
- package/cli/src/utils/services.ts +0 -364
- package/cli/src/utils/stack-features.ts +0 -30
- package/cli/src/utils/tar.ts +0 -24
- package/cli/src/utils/tilt.ts +0 -133
- package/cli/src/utils/validation.ts +0 -67
- package/cli/tsconfig.json +0 -25
- package/cli/tsconfig.typecheck.json +0 -8
- package/docs/FEATURES.md +0 -281
- package/docs/demo.svg +0 -217
- package/engine/docs/AUTODISCOVERY_TEST.md +0 -182
- package/engine/docs/C4-ARCHITECTURE-operations.md +0 -396
- package/engine/docs/C4-ARCHITECTURE-overview.md +0 -284
- package/engine/docs/C4-ARCHITECTURE.md +0 -17
- package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +0 -349
- package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +0 -357
- package/engine/docs/README.md +0 -284
- package/install.sh +0 -19
- package/knip.json +0 -10
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/.openspec.yaml +0 -2
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/design.md +0 -102
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/proposal.md +0 -31
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-notifications/spec.md +0 -48
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-orchestration/spec.md +0 -63
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/specs/vscode-tdk-troubleshooting/spec.md +0 -56
- package/openspec/changes/add-vscode-tdk-troubleshooter-plugin/tasks.md +0 -61
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/design.md +0 -114
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/proposal.md +0 -32
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/manifest-field-migration/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/resource-terminology-standard/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/specs/stack-terminology-standard/spec.md +0 -20
- package/openspec/changes/archive/2026-04-28-rename-domain-to-stack-service-to-resource/tasks.md +0 -194
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/design.md +0 -111
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/proposal.md +0 -33
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/function-naming-alignment/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/optional-parameter-patterns/spec.md +0 -18
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-documentation/spec.md +0 -16
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-naming-consistency/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/specs/parameter-ordering-standard/spec.md +0 -12
- package/openspec/changes/archive/2026-04-28-star-files-parameter-fixes/tasks.md +0 -194
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/design.md +0 -84
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/proposal.md +0 -31
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/codebase-audit/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/dead-code-cleanup/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/test-gap-fill/spec.md +0 -23
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/specs/todo-resolution/spec.md +0 -27
- package/openspec/changes/archive/2026-04-29-scan-repo-gaps-fix/tasks.md +0 -39
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/design.md +0 -80
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/proposal.md +0 -40
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/spec.md +0 -52
- package/openspec/changes/archive/2026-06-25-landscape-consolidation/tasks.md +0 -51
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/design.md +0 -43
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/proposal.md +0 -29
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/specs/self-contained-generated-projects/spec.md +0 -67
- package/openspec/changes/archive/2026-09-17-fix-generated-stack-boot/tasks.md +0 -27
- package/openspec/changes/optimize-runtime-docker-layers/.openspec.yaml +0 -3
- package/openspec/changes/optimize-runtime-docker-layers/design.md +0 -81
- package/openspec/changes/optimize-runtime-docker-layers/proposal.md +0 -44
- package/openspec/changes/optimize-runtime-docker-layers/specs/runtime-container-footprint/spec.md +0 -79
- package/openspec/changes/optimize-runtime-docker-layers/tasks.md +0 -36
- package/openspec/changes/prioritized-cold-start/.openspec.yaml +0 -4
- package/openspec/changes/prioritized-cold-start/design.md +0 -137
- package/openspec/changes/prioritized-cold-start/proposal.md +0 -41
- package/openspec/changes/prioritized-cold-start/specs/on-demand-resource-startup/spec.md +0 -98
- package/openspec/changes/prioritized-cold-start/tasks.md +0 -69
- package/openspec/config.yaml +0 -1
- package/openspec/specs/manifest-field-migration/spec.md +0 -24
- package/openspec/specs/resource-terminology-standard/spec.md +0 -24
- package/openspec/specs/self-contained-generated-projects/spec.md +0 -67
- package/openspec/specs/stack-terminology-standard/spec.md +0 -24
- package/platform/services/platform/proxy/service.yaml +0 -14
- package/scripts/audit-codebase.sh +0 -213
- package/scripts/autoresearch/layer-eval.sh +0 -65
- package/scripts/benchmark/README.md +0 -25
- package/scripts/benchmark/container-scale.ts +0 -503
- package/scripts/benchmark/pre-release-gate.sh +0 -9
- package/scripts/install-git-hooks.sh +0 -14
- package/scripts/measure-idle-footprint.sh +0 -58
- package/scripts/record-demo.sh +0 -43
- package/scripts/release-binaries.sh +0 -97
- package/scripts/setup-pre-commit.sh +0 -33
- package/scripts/stage-npm-engine.sh +0 -36
- package/tests/tilt-engine/__init__.py +0 -5
- package/tests/tilt-engine/conftest.py +0 -182
- package/tests/tilt-engine/fixtures/appointment-frontend-service.json +0 -11
- package/tests/tilt-engine/fixtures/identity-backend-service.json +0 -12
- package/tests/tilt-engine/fixtures/invalid-service.json +0 -4
- package/tests/tilt-engine/test_agents_md_generator.py +0 -341
- package/tests/tilt-engine/test_agents_md_integration.py +0 -378
- package/tests/tilt-engine/test_cache_operations.py +0 -181
- package/tests/tilt-engine/test_cache_persistence.py +0 -142
- package/tests/tilt-engine/test_code_executor.py +0 -152
- package/tests/tilt-engine/test_code_viewer.py +0 -127
- package/tests/tilt-engine/test_compose_port_anchors.py +0 -310
- package/tests/tilt-engine/test_config_inspector.py +0 -162
- package/tests/tilt-engine/test_daemon_focus_mode.py +0 -89
- package/tests/tilt-engine/test_daemon_polling.py +0 -122
- package/tests/tilt-engine/test_daemon_registration.py +0 -115
- package/tests/tilt-engine/test_daemon_validation.py +0 -107
- package/tests/tilt-engine/test_docker_generator_bugs.py +0 -493
- package/tests/tilt-engine/test_docker_prune.py +0 -119
- package/tests/tilt-engine/test_dockerignore_path_bug.py +0 -82
- package/tests/tilt-engine/test_file_browser.py +0 -193
- package/tests/tilt-engine/test_frontend_basepath_manifest.py +0 -27
- package/tests/tilt-engine/test_health_dependencies.py +0 -130
- package/tests/tilt-engine/test_health_endpoints.py +0 -118
- package/tests/tilt-engine/test_health_tilt_ui.py +0 -85
- package/tests/tilt-engine/test_runtime_container_footprint.py +0 -162
- package/tests/tilt-engine/test_sablier_defer_start.py +0 -237
- package/tests/tilt-engine/test_safety_aliases.py +0 -84
- package/tests/tilt-engine/test_snapshot_diff.py +0 -136
- package/tests/tilt-engine/test_snapshot_persistence.py +0 -163
- package/tests/tilt-engine/test_snapshot_scanning.py +0 -123
- package/tests/tilt-engine/test_standalone_project_boot.py +0 -61
- package/tests/tilt-engine/test_standalone_traefik.py +0 -160
- package/tests/tilt-engine/test_traefik_static_wake_route.py +0 -187
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Regression test for the sibling-service dockerignore collision bug.
|
|
3
|
-
|
|
4
|
-
manifest_resource.star computed the .dockerignore path for a resource's
|
|
5
|
-
Dockerfile by taking `resource_path.rsplit('/', 1)[0]` (stripping the last
|
|
6
|
-
path segment) before appending the resource's relative `dockerfile` field.
|
|
7
|
-
`resource_path` is already the resource's own directory (e.g.
|
|
8
|
-
"services/app/dashboard-api"), so stripping a segment lands one level up, at
|
|
9
|
-
the shared STACK directory (e.g. "services/app") instead.
|
|
10
|
-
|
|
11
|
-
Two sibling services in the same stack (e.g. dashboard-api and dashboard-app
|
|
12
|
-
under services/app) then both write to the same shared path
|
|
13
|
-
("services/app/.autogenerated/Dockerfile.app.autogenerated.dockerignore")
|
|
14
|
-
with different content (backend vs frontend dockerignore rules). Since the
|
|
15
|
-
two writers keep overwriting each other every Tiltfile load, the file is
|
|
16
|
-
never stable, Tilt sees it change on every run, and reloads the Tiltfile
|
|
17
|
-
forever - an infinite restart loop.
|
|
18
|
-
|
|
19
|
-
The fix drops the `.rsplit('/', 1)[0]` so the dockerignore path always sits
|
|
20
|
-
next to its own Dockerfile, matching how the Dockerfile path itself (and how
|
|
21
|
-
_register_docker_build in apply_compose_resource_registration.star resolves
|
|
22
|
-
a resource's `dockerfile` field) is computed.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
import re
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
|
|
28
|
-
import pytest
|
|
29
|
-
|
|
30
|
-
pytestmark = [pytest.mark.fast, pytest.mark.generator]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@pytest.fixture
|
|
34
|
-
def manifest_resource_path() -> Path:
|
|
35
|
-
return (
|
|
36
|
-
Path(__file__).parent.parent.parent
|
|
37
|
-
/ "engine"
|
|
38
|
-
/ "topologies"
|
|
39
|
-
/ "tilt"
|
|
40
|
-
/ "resources"
|
|
41
|
-
/ "orchestrator"
|
|
42
|
-
/ "generators"
|
|
43
|
-
/ "manifest_resource.star"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def test_file_exists(manifest_resource_path: Path):
|
|
48
|
-
assert manifest_resource_path.exists(), f"Not found: {manifest_resource_path}"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def test_dockerignore_path_is_not_stripped_to_parent_directory(manifest_resource_path: Path):
|
|
52
|
-
"""The buggy `resource_path.rsplit('/', 1)[0]` pattern must not reappear in code."""
|
|
53
|
-
code_lines = [
|
|
54
|
-
line
|
|
55
|
-
for line in manifest_resource_path.read_text().splitlines()
|
|
56
|
-
if not line.strip().startswith("#")
|
|
57
|
-
]
|
|
58
|
-
code = "\n".join(code_lines)
|
|
59
|
-
assert "resource_path.rsplit(" not in code, (
|
|
60
|
-
"dockerignore path must be resolved relative to the resource's own "
|
|
61
|
-
"directory (resource_path), not a parent stripped via rsplit"
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def test_dockerignore_path_matches_dockerfile_path(manifest_resource_path: Path):
|
|
66
|
-
"""Both the logged file-list builder and the actual writer must use the
|
|
67
|
-
same resource_path-relative join for the dockerignore path."""
|
|
68
|
-
content = manifest_resource_path.read_text()
|
|
69
|
-
|
|
70
|
-
matches = re.findall(
|
|
71
|
-
r'dockerfile_path = ([^\n]+)',
|
|
72
|
-
content,
|
|
73
|
-
)
|
|
74
|
-
assert matches, "Expected at least one dockerfile_path assignment"
|
|
75
|
-
for expr in matches:
|
|
76
|
-
assert expr.strip() == 'resource_path + "/" + dockerfile_rel_path', (
|
|
77
|
-
f"dockerfile_path must join resource_path directly, got: {expr}"
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if __name__ == "__main__":
|
|
82
|
-
pytest.main([__file__, "-v"])
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for file browser component.
|
|
3
|
-
Tests the file listing, navigation, and security features.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
import os
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from unittest.mock import Mock, patch
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@pytest.mark.ide
|
|
13
|
-
class TestFileBrowser:
|
|
14
|
-
"""Tests for file browser functionality."""
|
|
15
|
-
|
|
16
|
-
def test_root_directory_listing(self, temp_dir):
|
|
17
|
-
"""
|
|
18
|
-
Scenario: Root directory listing
|
|
19
|
-
WHEN a user requests `GET /` from the file browser
|
|
20
|
-
THEN it SHALL return HTML with the root directory listing
|
|
21
|
-
AND it SHALL include directories and files with icons (📁, 📄)
|
|
22
|
-
"""
|
|
23
|
-
# Create test structure
|
|
24
|
-
(temp_dir / "services").mkdir()
|
|
25
|
-
(temp_dir / "README.md").write_text("# Project")
|
|
26
|
-
(temp_dir / "package.json").write_text('{"name": "test"}')
|
|
27
|
-
|
|
28
|
-
# Simulate file browser response
|
|
29
|
-
entries = self._get_directory_listing(temp_dir, temp_dir)
|
|
30
|
-
|
|
31
|
-
# Verify structure
|
|
32
|
-
assert len(entries) >= 2, "Should list directories and files"
|
|
33
|
-
|
|
34
|
-
# Check for icons
|
|
35
|
-
dir_entry = next((e for e in entries if e["name"] == "services"), None)
|
|
36
|
-
assert dir_entry is not None, "Should list services directory"
|
|
37
|
-
assert "📁" in dir_entry.get("icon", ""), "Directories should have folder icon"
|
|
38
|
-
|
|
39
|
-
def test_subdirectory_navigation(self, temp_dir):
|
|
40
|
-
"""
|
|
41
|
-
Scenario: Subdirectory navigation
|
|
42
|
-
WHEN a user requests `GET /?path=.tdk/.tdk-out` from the file browser
|
|
43
|
-
THEN it SHALL return HTML with the subdirectory listing
|
|
44
|
-
AND breadcrumb links SHALL allow navigation to parent directories
|
|
45
|
-
"""
|
|
46
|
-
# Create nested structure
|
|
47
|
-
nested_dir = temp_dir / ".tdk" / ".tdk-out" / "snapshots"
|
|
48
|
-
nested_dir.mkdir(parents=True)
|
|
49
|
-
(nested_dir / "file.txt").write_text("content")
|
|
50
|
-
|
|
51
|
-
# Simulate navigation
|
|
52
|
-
entries = self._get_directory_listing(nested_dir, temp_dir)
|
|
53
|
-
|
|
54
|
-
assert len(entries) == 1, "Should list the file in subdirectory"
|
|
55
|
-
assert entries[0]["name"] == "file.txt"
|
|
56
|
-
|
|
57
|
-
# Verify breadcrumb paths
|
|
58
|
-
breadcrumbs = self._get_breadcrumbs(nested_dir, temp_dir)
|
|
59
|
-
assert len(breadcrumbs) > 0, "Should have breadcrumbs"
|
|
60
|
-
assert breadcrumbs[0]["name"] == "root", "First breadcrumb should be root"
|
|
61
|
-
|
|
62
|
-
def test_file_metadata_display(self, temp_dir):
|
|
63
|
-
"""
|
|
64
|
-
Scenario: File metadata display
|
|
65
|
-
WHEN a directory listing includes a file
|
|
66
|
-
THEN it SHALL display file size in human-readable format
|
|
67
|
-
AND it SHALL display modification time in readable format
|
|
68
|
-
"""
|
|
69
|
-
# Create test file
|
|
70
|
-
test_file = temp_dir / "test.txt"
|
|
71
|
-
test_file.write_text("Hello, World!" * 100) # ~1.3KB
|
|
72
|
-
|
|
73
|
-
import time
|
|
74
|
-
mtime = time.time()
|
|
75
|
-
os.utime(test_file, (mtime, mtime))
|
|
76
|
-
|
|
77
|
-
# Get metadata
|
|
78
|
-
metadata = self._get_file_metadata(test_file)
|
|
79
|
-
|
|
80
|
-
assert "size" in metadata
|
|
81
|
-
assert "size_formatted" in metadata
|
|
82
|
-
assert "mtime" in metadata
|
|
83
|
-
assert "mtime_formatted" in metadata
|
|
84
|
-
|
|
85
|
-
# Check size formatting (should be human-readable)
|
|
86
|
-
assert "B" in metadata["size_formatted"] or "KB" in metadata["size_formatted"]
|
|
87
|
-
|
|
88
|
-
def test_path_traversal_protection(self, temp_dir):
|
|
89
|
-
"""
|
|
90
|
-
Scenario: Path traversal protection
|
|
91
|
-
WHEN a user requests `GET /?path=../../../etc/passwd` from the file browser
|
|
92
|
-
THEN it SHALL return `403 Forbidden`
|
|
93
|
-
AND it SHALL NOT expose files outside the project root
|
|
94
|
-
"""
|
|
95
|
-
# Try to access outside project root
|
|
96
|
-
malicious_path = "../../../etc/passwd"
|
|
97
|
-
|
|
98
|
-
# Verify path would escape project root
|
|
99
|
-
from pathlib import Path
|
|
100
|
-
resolved = (temp_dir / malicious_path).resolve()
|
|
101
|
-
|
|
102
|
-
is_within_root = str(resolved).startswith(str(temp_dir.resolve()))
|
|
103
|
-
|
|
104
|
-
assert not is_within_root, "Path traversal attempt should be detected"
|
|
105
|
-
|
|
106
|
-
# Security check: should reject paths outside root
|
|
107
|
-
is_safe = self._is_safe_path(malicious_path, temp_dir)
|
|
108
|
-
assert not is_safe, "Path outside root should be rejected"
|
|
109
|
-
|
|
110
|
-
def test_file_size_limit(self, temp_dir):
|
|
111
|
-
"""
|
|
112
|
-
Scenario: File size limit
|
|
113
|
-
WHEN a user attempts to access a file larger than 1MB
|
|
114
|
-
THEN it SHALL return `413 Payload Too Large`
|
|
115
|
-
AND it SHALL include a helpful error message
|
|
116
|
-
"""
|
|
117
|
-
# Create large file (1.5MB)
|
|
118
|
-
large_file = temp_dir / "large.bin"
|
|
119
|
-
large_file.write_bytes(b"0" * (1024 * 1024 + 512 * 1024)) # 1.5MB
|
|
120
|
-
|
|
121
|
-
file_size = large_file.stat().st_size
|
|
122
|
-
max_size = 1024 * 1024 # 1MB
|
|
123
|
-
|
|
124
|
-
assert file_size > max_size, "Test file should be larger than limit"
|
|
125
|
-
|
|
126
|
-
# Check size limit
|
|
127
|
-
is_within_limit = file_size <= max_size
|
|
128
|
-
assert not is_within_limit, "File should exceed size limit"
|
|
129
|
-
|
|
130
|
-
def _get_directory_listing(self, path: Path, root: Path) -> list:
|
|
131
|
-
"""Helper to simulate directory listing."""
|
|
132
|
-
if not path.exists():
|
|
133
|
-
return []
|
|
134
|
-
|
|
135
|
-
entries = []
|
|
136
|
-
for item in sorted(path.iterdir()):
|
|
137
|
-
entry = {
|
|
138
|
-
"name": item.name,
|
|
139
|
-
"is_dir": item.is_dir(),
|
|
140
|
-
"icon": "📁" if item.is_dir() else "📄"
|
|
141
|
-
}
|
|
142
|
-
entries.append(entry)
|
|
143
|
-
return entries
|
|
144
|
-
|
|
145
|
-
def _get_breadcrumbs(self, path: Path, root: Path) -> list:
|
|
146
|
-
"""Helper to generate breadcrumbs."""
|
|
147
|
-
breadcrumbs = [{"name": "root", "path": "."}]
|
|
148
|
-
|
|
149
|
-
rel_path = path.relative_to(root)
|
|
150
|
-
current = root
|
|
151
|
-
|
|
152
|
-
for part in rel_path.parts:
|
|
153
|
-
current = current / part
|
|
154
|
-
breadcrumbs.append({"name": part, "path": str(current.relative_to(root))})
|
|
155
|
-
|
|
156
|
-
return breadcrumbs
|
|
157
|
-
|
|
158
|
-
def _get_file_metadata(self, path: Path) -> dict:
|
|
159
|
-
"""Helper to get file metadata."""
|
|
160
|
-
stat = path.stat()
|
|
161
|
-
size = stat.st_size
|
|
162
|
-
|
|
163
|
-
# Format size
|
|
164
|
-
if size < 1024:
|
|
165
|
-
size_formatted = f"{size} B"
|
|
166
|
-
elif size < 1024 * 1024:
|
|
167
|
-
size_formatted = f"{size / 1024:.1f} KB"
|
|
168
|
-
else:
|
|
169
|
-
size_formatted = f"{size / (1024 * 1024):.1f} MB"
|
|
170
|
-
|
|
171
|
-
import time
|
|
172
|
-
from datetime import datetime
|
|
173
|
-
|
|
174
|
-
mtime = stat.st_mtime
|
|
175
|
-
mtime_formatted = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
"size": size,
|
|
179
|
-
"size_formatted": size_formatted,
|
|
180
|
-
"mtime": mtime,
|
|
181
|
-
"mtime_formatted": mtime_formatted
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
def _is_safe_path(self, path_str: str, root: Path) -> bool:
|
|
185
|
-
"""Check if path is safe (within project root)."""
|
|
186
|
-
try:
|
|
187
|
-
requested_path = (root / path_str).resolve()
|
|
188
|
-
root_resolved = root.resolve()
|
|
189
|
-
|
|
190
|
-
# Check if resolved path is within root
|
|
191
|
-
return str(requested_path).startswith(str(root_resolved))
|
|
192
|
-
except (ValueError, RuntimeError):
|
|
193
|
-
return False
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ROOT = Path(__file__).resolve().parents[2]
|
|
6
|
-
EXAMPLE_ROOT = ROOT.parent / "tdk-restaurant-example"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def test_frontend_service_manifests_define_explicit_base_paths():
|
|
10
|
-
expected = {
|
|
11
|
-
"reservation-app": "/reservation-app",
|
|
12
|
-
"floor-app": "/floor-app",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
for app_name, expected_base_path in expected.items():
|
|
16
|
-
service_path = (
|
|
17
|
-
EXAMPLE_ROOT
|
|
18
|
-
/ "services"
|
|
19
|
-
/ ("guest" if app_name == "reservation-app" else "operations")
|
|
20
|
-
/ app_name
|
|
21
|
-
/ "service.json"
|
|
22
|
-
)
|
|
23
|
-
payload = json.loads(service_path.read_text())
|
|
24
|
-
|
|
25
|
-
assert payload["basePath"] == expected_base_path, (
|
|
26
|
-
f"{app_name} should generate the app route as {expected_base_path} instead of the stack default"
|
|
27
|
-
)
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for health dependency checks.
|
|
3
|
-
Tests that services report correct health status for their dependencies.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@pytest.mark.health
|
|
11
|
-
class TestHealthDependencies:
|
|
12
|
-
"""Tests for dependency health checking."""
|
|
13
|
-
|
|
14
|
-
def test_database_health_check_success(self):
|
|
15
|
-
"""
|
|
16
|
-
Scenario: Database health check
|
|
17
|
-
WHEN a service has a database dependency configured with `createDatabaseHealthCheck`
|
|
18
|
-
AND the database is accessible
|
|
19
|
-
THEN `/health/ready` SHALL return `status: "ready"` with `database: "healthy"`
|
|
20
|
-
"""
|
|
21
|
-
# Simulate successful database check
|
|
22
|
-
db_check_result = {"healthy": True, "latency_ms": 5}
|
|
23
|
-
|
|
24
|
-
health_response = {
|
|
25
|
-
"status": "ready",
|
|
26
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"database": "healthy" if db_check_result["healthy"] else "unhealthy"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
assert health_response["status"] == "ready"
|
|
33
|
-
assert health_response["dependencies"]["database"] == "healthy"
|
|
34
|
-
|
|
35
|
-
def test_database_health_check_failure(self):
|
|
36
|
-
"""
|
|
37
|
-
Scenario: Database health check failure
|
|
38
|
-
WHEN a service has a database dependency but the database is unreachable
|
|
39
|
-
THEN `/health/ready` SHALL return `status: "not_ready"` with `database: "unhealthy"`
|
|
40
|
-
AND the response SHALL include error details
|
|
41
|
-
"""
|
|
42
|
-
# Simulate failed database check
|
|
43
|
-
db_check_result = {"healthy": False, "error": "Connection refused"}
|
|
44
|
-
|
|
45
|
-
health_response = {
|
|
46
|
-
"status": "not_ready",
|
|
47
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"database": "unhealthy",
|
|
50
|
-
"database_error": db_check_result["error"]
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
assert health_response["status"] == "not_ready"
|
|
55
|
-
assert health_response["dependencies"]["database"] == "unhealthy"
|
|
56
|
-
assert "database_error" in health_response["dependencies"]
|
|
57
|
-
|
|
58
|
-
def test_multiple_dependency_statuses(self):
|
|
59
|
-
"""
|
|
60
|
-
Scenario: Multiple dependencies
|
|
61
|
-
WHEN a service has database and cache dependencies
|
|
62
|
-
AND database is healthy but cache is unhealthy
|
|
63
|
-
THEN `/health/ready` SHALL return `status: "not_ready"`
|
|
64
|
-
AND the response SHALL include status for each dependency
|
|
65
|
-
"""
|
|
66
|
-
# Simulate mixed dependency health
|
|
67
|
-
dependencies = {
|
|
68
|
-
"database": {"healthy": True, "latency_ms": 5},
|
|
69
|
-
"cache": {"healthy": False, "error": "Timeout"},
|
|
70
|
-
"nats": {"healthy": True, "latency_ms": 2}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
# Service is not ready if any dependency is unhealthy
|
|
74
|
-
all_healthy = all(d["healthy"] for d in dependencies.values())
|
|
75
|
-
|
|
76
|
-
health_response = {
|
|
77
|
-
"status": "ready" if all_healthy else "not_ready",
|
|
78
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
79
|
-
"dependencies": {
|
|
80
|
-
name: "healthy" if data["healthy"] else "unhealthy"
|
|
81
|
-
for name, data in dependencies.items()
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
assert health_response["status"] == "not_ready"
|
|
86
|
-
assert health_response["dependencies"]["database"] == "healthy"
|
|
87
|
-
assert health_response["dependencies"]["cache"] == "unhealthy"
|
|
88
|
-
assert health_response["dependencies"]["nats"] == "healthy"
|
|
89
|
-
|
|
90
|
-
def test_all_dependencies_healthy(self):
|
|
91
|
-
"""Test when all dependencies are healthy."""
|
|
92
|
-
dependencies = {
|
|
93
|
-
"database": {"healthy": True},
|
|
94
|
-
"cache": {"healthy": True},
|
|
95
|
-
"nats": {"healthy": True}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
all_healthy = all(d["healthy"] for d in dependencies.values())
|
|
99
|
-
|
|
100
|
-
assert all_healthy, "All dependencies should be healthy"
|
|
101
|
-
|
|
102
|
-
health_response = {
|
|
103
|
-
"status": "ready",
|
|
104
|
-
"dependencies": {
|
|
105
|
-
name: "healthy" for name in dependencies.keys()
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
assert health_response["status"] == "ready"
|
|
110
|
-
|
|
111
|
-
def test_dependency_latency_reporting(self):
|
|
112
|
-
"""Test that dependency health checks include latency."""
|
|
113
|
-
dependencies = {
|
|
114
|
-
"database": {"healthy": True, "latency_ms": 5},
|
|
115
|
-
"cache": {"healthy": True, "latency_ms": 2}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
health_response = {
|
|
119
|
-
"status": "ready",
|
|
120
|
-
"dependencies": {
|
|
121
|
-
name: {
|
|
122
|
-
"status": "healthy" if data["healthy"] else "unhealthy",
|
|
123
|
-
"latency_ms": data.get("latency_ms", 0)
|
|
124
|
-
}
|
|
125
|
-
for name, data in dependencies.items()
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
assert health_response["dependencies"]["database"]["latency_ms"] == 5
|
|
130
|
-
assert health_response["dependencies"]["cache"]["latency_ms"] == 2
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for health endpoint response structure.
|
|
3
|
-
Tests the /health, /health/live, and /health/ready endpoints.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@pytest.mark.health
|
|
11
|
-
class TestHealthEndpoints:
|
|
12
|
-
"""Tests for health check endpoint structure."""
|
|
13
|
-
|
|
14
|
-
def test_overall_health_endpoint_structure(self, mock_health_response):
|
|
15
|
-
"""
|
|
16
|
-
Scenario: Overall health endpoint
|
|
17
|
-
WHEN a service with health checks receives a request to `GET /health`
|
|
18
|
-
THEN it SHALL return JSON with fields: `status`, `service`, `version`, `timestamp`, `uptime`, `dependencies`
|
|
19
|
-
AND `status` SHALL be one of: `healthy`, `unhealthy`, `degraded`
|
|
20
|
-
"""
|
|
21
|
-
required_fields = ["status", "service", "version", "timestamp", "uptime", "dependencies"]
|
|
22
|
-
|
|
23
|
-
for field in required_fields:
|
|
24
|
-
assert field in mock_health_response, f"Response missing required field: {field}"
|
|
25
|
-
|
|
26
|
-
assert mock_health_response["status"] in ["healthy", "unhealthy", "degraded"]
|
|
27
|
-
|
|
28
|
-
def test_liveness_probe_endpoint(self):
|
|
29
|
-
"""
|
|
30
|
-
Scenario: Liveness probe endpoint
|
|
31
|
-
WHEN a service receives a request to `GET /health/live`
|
|
32
|
-
THEN it SHALL return JSON with `status: "alive"` or `status: "dead"`
|
|
33
|
-
AND `timestamp` SHALL be ISO8601 format
|
|
34
|
-
"""
|
|
35
|
-
liveness_response = {
|
|
36
|
-
"status": "alive",
|
|
37
|
-
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
assert "status" in liveness_response
|
|
41
|
-
assert liveness_response["status"] in ["alive", "dead"]
|
|
42
|
-
assert "timestamp" in liveness_response
|
|
43
|
-
|
|
44
|
-
# Verify ISO8601 format (contains T and timezone info)
|
|
45
|
-
timestamp = liveness_response["timestamp"]
|
|
46
|
-
assert "T" in timestamp, "Timestamp should be ISO8601 format"
|
|
47
|
-
|
|
48
|
-
def test_readiness_probe_endpoint(self):
|
|
49
|
-
"""
|
|
50
|
-
Scenario: Readiness probe endpoint
|
|
51
|
-
WHEN a service receives a request to `GET /health/ready`
|
|
52
|
-
THEN it SHALL return JSON with `status: "ready"` or `status: "not_ready"`
|
|
53
|
-
AND if `not_ready`, it SHALL include `dependencies` object with failing dependency names
|
|
54
|
-
"""
|
|
55
|
-
# Test ready state
|
|
56
|
-
ready_response = {
|
|
57
|
-
"status": "ready",
|
|
58
|
-
"timestamp": datetime.now(timezone.utc).isoformat()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
assert ready_response["status"] in ["ready", "not_ready"]
|
|
62
|
-
|
|
63
|
-
# Test not_ready state with dependencies
|
|
64
|
-
not_ready_response = {
|
|
65
|
-
"status": "not_ready",
|
|
66
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
67
|
-
"dependencies": {
|
|
68
|
-
"database": "unhealthy",
|
|
69
|
-
"cache": "healthy"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
assert not_ready_response["status"] == "not_ready"
|
|
74
|
-
assert "dependencies" in not_ready_response
|
|
75
|
-
assert "database" in not_ready_response["dependencies"]
|
|
76
|
-
|
|
77
|
-
def test_health_status_values(self):
|
|
78
|
-
"""Test that health status values are from allowed set."""
|
|
79
|
-
valid_statuses = ["healthy", "unhealthy", "degraded", "ready", "not_ready", "alive", "dead"]
|
|
80
|
-
|
|
81
|
-
test_responses = [
|
|
82
|
-
{"status": "healthy"},
|
|
83
|
-
{"status": "unhealthy"},
|
|
84
|
-
{"status": "degraded"},
|
|
85
|
-
{"status": "ready"},
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
for response in test_responses:
|
|
89
|
-
assert response["status"] in valid_statuses, f"Invalid status: {response['status']}"
|
|
90
|
-
|
|
91
|
-
def test_health_response_includes_version(self):
|
|
92
|
-
"""Test that health response includes service version."""
|
|
93
|
-
response = {
|
|
94
|
-
"status": "healthy",
|
|
95
|
-
"service": "test-service",
|
|
96
|
-
"version": "1.0.0",
|
|
97
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
98
|
-
"uptime": 3600,
|
|
99
|
-
"dependencies": {}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
assert "version" in response
|
|
103
|
-
assert response["version"] == "1.0.0"
|
|
104
|
-
|
|
105
|
-
def test_health_response_includes_uptime(self):
|
|
106
|
-
"""Test that health response includes uptime in seconds."""
|
|
107
|
-
response = {
|
|
108
|
-
"status": "healthy",
|
|
109
|
-
"service": "test-service",
|
|
110
|
-
"version": "1.0.0",
|
|
111
|
-
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
112
|
-
"uptime": 3600,
|
|
113
|
-
"dependencies": {}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
assert "uptime" in response
|
|
117
|
-
assert isinstance(response["uptime"], (int, float))
|
|
118
|
-
assert response["uptime"] >= 0
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for health status in Tilt UI.
|
|
3
|
-
Tests the mapping from health responses to Tilt UI indicators.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@pytest.mark.health
|
|
10
|
-
class TestHealthTiltUI:
|
|
11
|
-
"""Tests for Tilt UI health status display."""
|
|
12
|
-
|
|
13
|
-
def test_ready_resource_shows_green(self, mock_tilt_ui_status):
|
|
14
|
-
"""
|
|
15
|
-
Scenario: Ready service shows green
|
|
16
|
-
WHEN `/health/ready` returns `200 OK` with `status: "ready"`
|
|
17
|
-
THEN the Tilt UI SHALL display the resource as **Ready** (green indicator)
|
|
18
|
-
"""
|
|
19
|
-
# Simulate a ready health check response
|
|
20
|
-
health_response = {"status": "ready"}
|
|
21
|
-
http_status = 200
|
|
22
|
-
|
|
23
|
-
# Determine Tilt UI status
|
|
24
|
-
if http_status == 200 and health_response.get("status") == "ready":
|
|
25
|
-
tilt_status = mock_tilt_ui_status["ready"]
|
|
26
|
-
|
|
27
|
-
assert tilt_status["indicator"] == "green"
|
|
28
|
-
assert tilt_status["status"] == "Ready"
|
|
29
|
-
|
|
30
|
-
def test_starting_resource_shows_yellow(self, mock_tilt_ui_status):
|
|
31
|
-
"""
|
|
32
|
-
Scenario: Starting service shows yellow
|
|
33
|
-
WHEN `/health/ready` returns `503 Service Unavailable` but `/health/live` returns `200`
|
|
34
|
-
THEN the Tilt UI SHALL display the resource as **Starting** (yellow indicator)
|
|
35
|
-
"""
|
|
36
|
-
# Simulate starting state (live but not ready)
|
|
37
|
-
live_response = {"status": "alive"}
|
|
38
|
-
ready_response = {"status": "not_ready"}
|
|
39
|
-
live_http_status = 200
|
|
40
|
-
ready_http_status = 503
|
|
41
|
-
|
|
42
|
-
# Determine Tilt UI status
|
|
43
|
-
if (live_http_status == 200 and live_response.get("status") == "alive" and
|
|
44
|
-
ready_http_status == 503):
|
|
45
|
-
tilt_status = mock_tilt_ui_status["starting"]
|
|
46
|
-
|
|
47
|
-
assert tilt_status["indicator"] == "yellow"
|
|
48
|
-
assert tilt_status["status"] == "Starting"
|
|
49
|
-
|
|
50
|
-
def test_error_resource_shows_red(self, mock_tilt_ui_status):
|
|
51
|
-
"""
|
|
52
|
-
Scenario: Error service shows red
|
|
53
|
-
WHEN `/health/live` fails or returns non-200
|
|
54
|
-
THEN the Tilt UI SHALL display the resource as **Error** (red indicator)
|
|
55
|
-
"""
|
|
56
|
-
# Simulate error state (live failing)
|
|
57
|
-
live_http_status = 500
|
|
58
|
-
|
|
59
|
-
# Determine Tilt UI status
|
|
60
|
-
if live_http_status != 200:
|
|
61
|
-
tilt_status = mock_tilt_ui_status["error"]
|
|
62
|
-
|
|
63
|
-
assert tilt_status["indicator"] == "red"
|
|
64
|
-
assert tilt_status["status"] == "Error"
|
|
65
|
-
|
|
66
|
-
def test_health_status_mapping(self):
|
|
67
|
-
"""Test the complete health status to Tilt UI mapping."""
|
|
68
|
-
test_cases = [
|
|
69
|
-
# (live_status, ready_status, live_http, ready_http, expected_indicator, expected_status)
|
|
70
|
-
("alive", "ready", 200, 200, "green", "Ready"),
|
|
71
|
-
("alive", "not_ready", 200, 503, "yellow", "Starting"),
|
|
72
|
-
("dead", "ready", 500, 200, "red", "Error"),
|
|
73
|
-
("dead", "not_ready", 500, 503, "red", "Error"),
|
|
74
|
-
]
|
|
75
|
-
|
|
76
|
-
for live_status, ready_status, live_http, ready_http, expected_indicator, expected_status in test_cases:
|
|
77
|
-
if live_http != 200:
|
|
78
|
-
actual_indicator, actual_status = "red", "Error"
|
|
79
|
-
elif ready_http != 200:
|
|
80
|
-
actual_indicator, actual_status = "yellow", "Starting"
|
|
81
|
-
else:
|
|
82
|
-
actual_indicator, actual_status = "green", "Ready"
|
|
83
|
-
|
|
84
|
-
assert actual_indicator == expected_indicator, f"Failed for case: {live_status}, {ready_status}"
|
|
85
|
-
assert actual_status == expected_status, f"Failed for case: {live_status}, {ready_status}"
|