@tdk-landscape/tdk-cli-core 1.3.49 → 1.3.50
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/.claude/skills/layer-autoresearch/SKILL.md +48 -0
- package/.claude/skills/tdk-troubleshoot/SKILL.md +222 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +40 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +18 -0
- package/.github/dependabot.yml +33 -0
- package/.github/pull_request_template.md +5 -0
- package/.github/workflows/ci.yml +187 -0
- package/.github/workflows/release-binaries.yml +19 -9
- package/.github/zizmor.yml +9 -0
- package/CODE_OF_CONDUCT.md +9 -0
- package/CONTRIBUTING.md +42 -0
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/SECURITY.md +17 -0
- package/benchmarks/results/container-scale-2026-09-25T20-54-49-736Z.json +45 -0
- package/benchmarks/results/container-scale-2026-09-25T21-01-20-540Z.json +150 -0
- package/benchmarks/results/container-scale-2026-09-25T21-15-01-441Z.json +73 -0
- package/benchmarks/results/container-scale-2026-09-25T22-09-01-630Z.json +77 -0
- package/benchmarks/results/container-scale-2026-09-25T22-18-28-371Z.json +202 -0
- package/cli/README.md +25 -0
- package/cli/biome.json +1 -1
- package/cli/dist/cli.d.ts +3 -0
- package/cli/dist/cli.d.ts.map +1 -0
- package/cli/dist/cli.js +64 -0
- package/cli/dist/cli.js.map +1 -0
- package/cli/dist/commands/completion.d.ts +3 -0
- package/cli/dist/commands/completion.d.ts.map +1 -0
- package/cli/dist/commands/completion.js +294 -0
- package/cli/dist/commands/completion.js.map +1 -0
- package/cli/dist/commands/config.d.ts +3 -0
- package/cli/dist/commands/config.d.ts.map +1 -0
- package/cli/dist/commands/config.js +231 -0
- package/cli/dist/commands/config.js.map +1 -0
- package/cli/dist/commands/doctor.d.ts +19 -0
- package/cli/dist/commands/doctor.d.ts.map +1 -0
- package/cli/dist/commands/doctor.js +745 -0
- package/cli/dist/commands/doctor.js.map +1 -0
- package/cli/dist/commands/down.d.ts +3 -0
- package/cli/dist/commands/down.d.ts.map +1 -0
- package/cli/dist/commands/down.js +32 -0
- package/cli/dist/commands/down.js.map +1 -0
- package/cli/dist/commands/help.d.ts +2 -0
- package/cli/dist/commands/help.d.ts.map +1 -0
- package/cli/dist/commands/help.js +138 -0
- package/cli/dist/commands/help.js.map +1 -0
- package/cli/dist/commands/networks.d.ts +3 -0
- package/cli/dist/commands/networks.d.ts.map +1 -0
- package/cli/dist/commands/networks.js +260 -0
- package/cli/dist/commands/networks.js.map +1 -0
- package/cli/dist/commands/project.d.ts +3 -0
- package/cli/dist/commands/project.d.ts.map +1 -0
- package/cli/dist/commands/project.js +370 -0
- package/cli/dist/commands/project.js.map +1 -0
- package/cli/dist/commands/projects.d.ts +3 -0
- package/cli/dist/commands/projects.d.ts.map +1 -0
- package/cli/dist/commands/projects.js +71 -0
- package/cli/dist/commands/projects.js.map +1 -0
- package/cli/dist/commands/resource.d.ts +69 -0
- package/cli/dist/commands/resource.d.ts.map +1 -0
- package/cli/dist/commands/resource.js +579 -0
- package/cli/dist/commands/resource.js.map +1 -0
- package/cli/dist/commands/resources.d.ts +3 -0
- package/cli/dist/commands/resources.d.ts.map +1 -0
- package/cli/dist/commands/resources.js +73 -0
- package/cli/dist/commands/resources.js.map +1 -0
- package/cli/dist/commands/stack.d.ts +3 -0
- package/cli/dist/commands/stack.d.ts.map +1 -0
- package/cli/dist/commands/stack.js +97 -0
- package/cli/dist/commands/stack.js.map +1 -0
- package/cli/dist/commands/stacks.d.ts +3 -0
- package/cli/dist/commands/stacks.d.ts.map +1 -0
- package/cli/dist/commands/stacks.js +43 -0
- package/cli/dist/commands/stacks.js.map +1 -0
- package/cli/dist/commands/status.d.ts +3 -0
- package/cli/dist/commands/status.d.ts.map +1 -0
- package/cli/dist/commands/status.js +71 -0
- package/cli/dist/commands/status.js.map +1 -0
- package/cli/dist/commands/ui.d.ts +3 -0
- package/cli/dist/commands/ui.d.ts.map +1 -0
- package/cli/dist/commands/ui.js +445 -0
- package/cli/dist/commands/ui.js.map +1 -0
- package/cli/dist/commands/up.d.ts +3 -0
- package/cli/dist/commands/up.d.ts.map +1 -0
- package/cli/dist/commands/up.js +124 -0
- package/cli/dist/commands/up.js.map +1 -0
- package/cli/dist/commands/upgrade.d.ts +11 -0
- package/cli/dist/commands/upgrade.d.ts.map +1 -0
- package/cli/dist/commands/upgrade.js +496 -0
- package/cli/dist/commands/upgrade.js.map +1 -0
- package/cli/dist/commands/version.d.ts +3 -0
- package/cli/dist/commands/version.d.ts.map +1 -0
- package/cli/dist/commands/version.js +9 -0
- package/cli/dist/commands/version.js.map +1 -0
- package/cli/dist/components/Accessible.d.ts +8 -0
- package/cli/dist/components/Accessible.d.ts.map +1 -0
- package/cli/dist/components/Accessible.js +10 -0
- package/cli/dist/components/Accessible.js.map +1 -0
- package/cli/dist/components/BaseTooltip.d.ts +4 -0
- package/cli/dist/components/BaseTooltip.d.ts.map +1 -0
- package/cli/dist/components/BaseTooltip.js +28 -0
- package/cli/dist/components/BaseTooltip.js.map +1 -0
- package/cli/dist/components/DetailPanel.d.ts +4 -0
- package/cli/dist/components/DetailPanel.d.ts.map +1 -0
- package/cli/dist/components/DetailPanel.js +18 -0
- package/cli/dist/components/DetailPanel.js.map +1 -0
- package/cli/dist/components/FileTree.d.ts +4 -0
- package/cli/dist/components/FileTree.d.ts.map +1 -0
- package/cli/dist/components/FileTree.js +47 -0
- package/cli/dist/components/FileTree.js.map +1 -0
- package/cli/dist/components/ResourceSelectInput.d.ts +4 -0
- package/cli/dist/components/ResourceSelectInput.d.ts.map +1 -0
- package/cli/dist/components/ResourceSelectInput.js +7 -0
- package/cli/dist/components/ResourceSelectInput.js.map +1 -0
- package/cli/dist/components/ResourceTable.d.ts +4 -0
- package/cli/dist/components/ResourceTable.d.ts.map +1 -0
- package/cli/dist/components/ResourceTable.js +18 -0
- package/cli/dist/components/ResourceTable.js.map +1 -0
- package/cli/dist/components/TabBar.d.ts +4 -0
- package/cli/dist/components/TabBar.d.ts.map +1 -0
- package/cli/dist/components/TabBar.js +17 -0
- package/cli/dist/components/TabBar.js.map +1 -0
- package/cli/dist/components/Tooltip.d.ts +12 -0
- package/cli/dist/components/Tooltip.d.ts.map +1 -0
- package/cli/dist/components/Tooltip.js +12 -0
- package/cli/dist/components/Tooltip.js.map +1 -0
- package/cli/dist/components/index.d.ts +8 -0
- package/cli/dist/components/index.d.ts.map +1 -0
- package/cli/dist/components/index.js +8 -0
- package/cli/dist/components/index.js.map +1 -0
- package/cli/dist/config/platform-standards.d.ts +159 -0
- package/cli/dist/config/platform-standards.d.ts.map +1 -0
- package/cli/dist/config/platform-standards.js +181 -0
- package/cli/dist/config/platform-standards.js.map +1 -0
- package/cli/dist/generator/extension-fetch.d.ts +25 -0
- package/cli/dist/generator/extension-fetch.d.ts.map +1 -0
- package/cli/dist/generator/extension-fetch.js +259 -0
- package/cli/dist/generator/extension-fetch.js.map +1 -0
- package/cli/dist/generator/template-engine.d.ts +62 -0
- package/cli/dist/generator/template-engine.d.ts.map +1 -0
- package/cli/dist/generator/template-engine.js +623 -0
- package/cli/dist/generator/template-engine.js.map +1 -0
- package/cli/dist/index.d.ts +11 -0
- package/cli/dist/index.d.ts.map +1 -0
- package/cli/dist/index.js +11 -0
- package/cli/dist/index.js.map +1 -0
- package/cli/dist/types/index.d.ts +257 -0
- package/cli/dist/types/index.d.ts.map +1 -0
- package/cli/dist/types/index.js +17 -0
- package/cli/dist/types/index.js.map +1 -0
- package/cli/dist/utils/cache.d.ts +19 -0
- package/cli/dist/utils/cache.d.ts.map +1 -0
- package/cli/dist/utils/cache.js +64 -0
- package/cli/dist/utils/cache.js.map +1 -0
- package/cli/dist/utils/command-helpers.d.ts +17 -0
- package/cli/dist/utils/command-helpers.d.ts.map +1 -0
- package/cli/dist/utils/command-helpers.js +41 -0
- package/cli/dist/utils/command-helpers.js.map +1 -0
- package/cli/dist/utils/constants.d.ts +53 -0
- package/cli/dist/utils/constants.d.ts.map +1 -0
- package/cli/dist/utils/constants.js +115 -0
- package/cli/dist/utils/constants.js.map +1 -0
- package/cli/dist/utils/discovery-context.d.ts +4 -0
- package/cli/dist/utils/discovery-context.d.ts.map +1 -0
- package/cli/dist/utils/discovery-context.js +39 -0
- package/cli/dist/utils/discovery-context.js.map +1 -0
- package/cli/dist/utils/docker.d.ts +4 -0
- package/cli/dist/utils/docker.d.ts.map +1 -0
- package/cli/dist/utils/docker.js +19 -0
- package/cli/dist/utils/docker.js.map +1 -0
- package/cli/dist/utils/doctor-runtime.d.ts +81 -0
- package/cli/dist/utils/doctor-runtime.d.ts.map +1 -0
- package/cli/dist/utils/doctor-runtime.js +498 -0
- package/cli/dist/utils/doctor-runtime.js.map +1 -0
- package/cli/dist/utils/env-validator.d.ts +15 -0
- package/cli/dist/utils/env-validator.d.ts.map +1 -0
- package/cli/dist/utils/env-validator.js +109 -0
- package/cli/dist/utils/env-validator.js.map +1 -0
- package/cli/dist/utils/errors.d.ts +31 -0
- package/cli/dist/utils/errors.d.ts.map +1 -0
- package/cli/dist/utils/errors.js +140 -0
- package/cli/dist/utils/errors.js.map +1 -0
- package/cli/dist/utils/file-helpers.d.ts +14 -0
- package/cli/dist/utils/file-helpers.d.ts.map +1 -0
- package/cli/dist/utils/file-helpers.js +45 -0
- package/cli/dist/utils/file-helpers.js.map +1 -0
- package/cli/dist/utils/formatting.d.ts +30 -0
- package/cli/dist/utils/formatting.d.ts.map +1 -0
- package/cli/dist/utils/formatting.js +164 -0
- package/cli/dist/utils/formatting.js.map +1 -0
- package/cli/dist/utils/paths.d.ts +3 -0
- package/cli/dist/utils/paths.d.ts.map +1 -0
- package/cli/dist/utils/paths.js +41 -0
- package/cli/dist/utils/paths.js.map +1 -0
- package/cli/dist/utils/port-assignment.d.ts +6 -0
- package/cli/dist/utils/port-assignment.d.ts.map +1 -0
- package/cli/dist/utils/port-assignment.js +81 -0
- package/cli/dist/utils/port-assignment.js.map +1 -0
- package/cli/dist/utils/project-features.d.ts +23 -0
- package/cli/dist/utils/project-features.d.ts.map +1 -0
- package/cli/dist/utils/project-features.js +98 -0
- package/cli/dist/utils/project-features.js.map +1 -0
- package/cli/dist/utils/project-templates.d.ts +7 -0
- package/cli/dist/utils/project-templates.d.ts.map +1 -0
- package/cli/dist/utils/project-templates.js +24 -0
- package/cli/dist/utils/project-templates.js.map +1 -0
- package/cli/dist/utils/prompt.d.ts +28 -0
- package/cli/dist/utils/prompt.d.ts.map +1 -0
- package/cli/dist/utils/prompt.js +79 -0
- package/cli/dist/utils/prompt.js.map +1 -0
- package/cli/dist/utils/resource-features.d.ts +29 -0
- package/cli/dist/utils/resource-features.d.ts.map +1 -0
- package/cli/dist/utils/resource-features.js +175 -0
- package/cli/dist/utils/resource-features.js.map +1 -0
- package/cli/dist/utils/service-urls.d.ts +30 -0
- package/cli/dist/utils/service-urls.d.ts.map +1 -0
- package/cli/dist/utils/service-urls.js +93 -0
- package/cli/dist/utils/service-urls.js.map +1 -0
- package/cli/dist/utils/services.d.ts +18 -0
- package/cli/dist/utils/services.d.ts.map +1 -0
- package/cli/dist/utils/services.js +292 -0
- package/cli/dist/utils/services.js.map +1 -0
- package/cli/dist/utils/stack-features.d.ts +22 -0
- package/cli/dist/utils/stack-features.d.ts.map +1 -0
- package/cli/dist/utils/stack-features.js +13 -0
- package/cli/dist/utils/stack-features.js.map +1 -0
- package/cli/dist/utils/tar.d.ts +7 -0
- package/cli/dist/utils/tar.d.ts.map +1 -0
- package/cli/dist/utils/tar.js +21 -0
- package/cli/dist/utils/tar.js.map +1 -0
- package/cli/dist/utils/tilt.d.ts +20 -0
- package/cli/dist/utils/tilt.d.ts.map +1 -0
- package/cli/dist/utils/tilt.js +95 -0
- package/cli/dist/utils/tilt.js.map +1 -0
- package/cli/dist/utils/validation.d.ts +16 -0
- package/cli/dist/utils/validation.d.ts.map +1 -0
- package/cli/dist/utils/validation.js +58 -0
- package/cli/dist/utils/validation.js.map +1 -0
- package/cli/package.json +11 -12
- package/cli/src/commands/__tests__/always-enabled-infra.test.ts +2 -8
- package/cli/src/commands/__tests__/doctor.test.ts +181 -8
- package/cli/src/commands/__tests__/phases-model.test.ts +2 -4
- package/cli/src/commands/__tests__/project-resource-features-e2e.test.ts +4 -24
- package/cli/src/commands/__tests__/saas-starter-integration.test.ts +8 -10
- package/cli/src/commands/__tests__/stack-features-e2e.test.ts +10 -4
- package/cli/src/commands/__tests__/upgrade.test.ts +23 -13
- package/cli/src/commands/doctor.ts +136 -0
- package/cli/src/commands/help.ts +13 -3
- package/cli/src/commands/project.ts +11 -14
- package/cli/src/commands/projects.ts +2 -2
- package/cli/src/commands/up.ts +13 -4
- package/cli/src/commands/upgrade.ts +11 -4
- package/cli/src/config/platform-standards.test.ts +6 -6
- package/cli/src/generator/__tests__/extension-fetch.test.ts +36 -14
- package/cli/src/generator/extension-fetch.ts +12 -5
- package/cli/src/generator/template-engine.ts +19 -21
- package/cli/src/types/index.ts +2 -0
- package/cli/src/utils/__tests__/tilt.test.ts +29 -0
- package/cli/src/utils/constants.ts +4 -0
- package/cli/src/utils/doctor-runtime.ts +67 -27
- package/cli/src/utils/env-validator.ts +2 -2
- package/cli/src/utils/project-templates.ts +2 -1
- package/cli/src/utils/prompt.ts +2 -4
- package/cli/src/utils/resource-features.ts +10 -4
- package/cli/src/utils/services.ts +2 -1
- package/cli/src/utils/tilt.ts +20 -0
- package/engine/assets/docker/wake-gateway/Dockerfile +26 -0
- package/engine/assets/docker/wake-gateway/decide.test.ts +87 -0
- package/engine/assets/docker/wake-gateway/decide.ts +75 -0
- package/engine/assets/docker/wake-gateway/server.ts +220 -0
- package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +13 -23
- package/engine/topologies/platform/docker/compose/compose.star +7 -14
- package/engine/topologies/platform/docker/compose/compose_helpers.star +1 -1
- package/engine/topologies/platform/docker/compose/traefik_standalone.star +44 -6
- package/engine/topologies/platform/docker/config/healthcheck.star +56 -0
- package/engine/topologies/platform/docker/constants.star +10 -0
- package/engine/topologies/platform/docker/layers/l1_base_layers.star +1 -1
- package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +55 -20
- package/engine/topologies/platform/docker/networking/traefik_static_routes.star +107 -0
- package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +2 -2
- package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +1 -1
- package/engine/topologies/tilt/manifest/schema.star +6 -0
- package/engine/topologies/tilt/manifest/validator.star +16 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +107 -8
- package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +12 -6
- package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +2 -1
- package/knip.json +1 -1
- package/openspec/changes/optimize-runtime-docker-layers/.openspec.yaml +3 -0
- package/openspec/changes/optimize-runtime-docker-layers/design.md +81 -0
- package/openspec/changes/optimize-runtime-docker-layers/proposal.md +44 -0
- package/openspec/changes/optimize-runtime-docker-layers/specs/runtime-container-footprint/spec.md +79 -0
- package/openspec/changes/optimize-runtime-docker-layers/tasks.md +36 -0
- package/openspec/changes/prioritized-cold-start/.openspec.yaml +4 -0
- package/openspec/changes/prioritized-cold-start/design.md +113 -0
- package/openspec/changes/prioritized-cold-start/proposal.md +40 -0
- package/openspec/changes/prioritized-cold-start/specs/on-demand-resource-startup/spec.md +92 -0
- package/openspec/changes/prioritized-cold-start/tasks.md +46 -0
- package/openspec/config.yaml +1 -0
- package/package.json +35 -5
- package/scripts/autoresearch/layer-eval.sh +65 -0
- package/scripts/benchmark/README.md +25 -0
- package/scripts/benchmark/container-scale.ts +503 -0
- package/scripts/benchmark/pre-release-gate.sh +9 -0
- package/scripts/measure-idle-footprint.sh +58 -0
- package/tests/tilt-engine/test_runtime_container_footprint.py +162 -0
- package/tests/tilt-engine/test_sablier_defer_start.py +196 -0
- package/tests/tilt-engine/test_standalone_traefik.py +38 -0
- package/tests/tilt-engine/test_traefik_static_wake_route.py +119 -0
- package/bun.lock +0 -538
package/cli/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tdk-cli-internal",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.50",
|
|
4
4
|
"description": "TDK CLI - Tilt Development Kit command line interface",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tdk",
|
|
@@ -53,25 +53,24 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"chalk": "^5.3.0",
|
|
56
|
-
"commander": "^
|
|
56
|
+
"commander": "^15.0.0",
|
|
57
57
|
"handlebars": "^4.7.8",
|
|
58
|
-
"ink": "^7.
|
|
58
|
+
"ink": "^7.1.1",
|
|
59
59
|
"ink-select-input": "^6.2.0",
|
|
60
|
-
"ora": "^
|
|
61
|
-
"react": "^19.
|
|
60
|
+
"ora": "^9.4.1",
|
|
61
|
+
"react": "^19.3.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@biomejs/biome": "^2.5.13",
|
|
65
|
-
"@types/react": "^19.
|
|
66
|
-
"@types/
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"react-devtools-core": "^6.1.1",
|
|
65
|
+
"@types/react": "^19.3.0",
|
|
66
|
+
"@types/node": "^22.0.0",
|
|
67
|
+
"knip": "^6.38.0",
|
|
68
|
+
"react-devtools-core": "^8.0.0",
|
|
70
69
|
"typescript": "^7.0.2",
|
|
71
|
-
"vite": "^
|
|
70
|
+
"vite": "^8.3.1",
|
|
72
71
|
"vitest": "^5.0.0"
|
|
73
72
|
},
|
|
74
73
|
"engines": {
|
|
75
|
-
"node": ">=
|
|
74
|
+
"node": ">=22.12.0"
|
|
76
75
|
}
|
|
77
76
|
}
|
|
@@ -45,10 +45,7 @@ describe("always_enabled_infra", () => {
|
|
|
45
45
|
enabledStacks: [],
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
|
-
always_enabled_infra: [
|
|
49
|
-
"database-management",
|
|
50
|
-
"proxy",
|
|
51
|
-
],
|
|
48
|
+
always_enabled_infra: ["database-management", "proxy"],
|
|
52
49
|
};
|
|
53
50
|
|
|
54
51
|
expect(projectConfig.always_enabled_infra).toContain("database-management");
|
|
@@ -85,10 +82,7 @@ describe("always_enabled_infra", () => {
|
|
|
85
82
|
};
|
|
86
83
|
|
|
87
84
|
// TemplateEngine uses ?? operator to default when undefined/null
|
|
88
|
-
const defaults = projectConfig.always_enabled_infra ?? [
|
|
89
|
-
"database-management",
|
|
90
|
-
"proxy",
|
|
91
|
-
];
|
|
85
|
+
const defaults = projectConfig.always_enabled_infra ?? ["database-management", "proxy"];
|
|
92
86
|
|
|
93
87
|
expect(defaults).toContain("database-management");
|
|
94
88
|
expect(defaults).toContain("proxy");
|
|
@@ -2,11 +2,6 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
-
import {
|
|
6
|
-
checkFrontendDockerPreflight,
|
|
7
|
-
checkGeneratedProjectRuntimeAssets,
|
|
8
|
-
checkStarlarkLoadExports,
|
|
9
|
-
} from "../doctor.js";
|
|
10
5
|
import {
|
|
11
6
|
checkIngressPorts,
|
|
12
7
|
checkPrivateNpmRegistry,
|
|
@@ -18,6 +13,13 @@ import {
|
|
|
18
13
|
probeContainerRuntimeError,
|
|
19
14
|
summarizeTiltBuildError,
|
|
20
15
|
} from "../../utils/doctor-runtime.js";
|
|
16
|
+
import {
|
|
17
|
+
checkDockerVersions,
|
|
18
|
+
checkFrontendDockerPreflight,
|
|
19
|
+
checkGeneratedProjectRuntimeAssets,
|
|
20
|
+
checkStarlarkLoadExports,
|
|
21
|
+
checkTypeScriptTypeDependencies,
|
|
22
|
+
} from "../doctor.js";
|
|
21
23
|
|
|
22
24
|
describe("doctor frontend Docker preflight", () => {
|
|
23
25
|
let testDir: string;
|
|
@@ -240,6 +242,9 @@ describe("doctor generated runtime asset preflight", () => {
|
|
|
240
242
|
"bun-hoisted-symlink-fix.sh",
|
|
241
243
|
"prisma-bun-client-link-fix.sh",
|
|
242
244
|
"prisma-normalize-client.sh",
|
|
245
|
+
"prisma-runtime-relink.sh",
|
|
246
|
+
"infisical-entrypoint.sh",
|
|
247
|
+
"migrate.sh",
|
|
243
248
|
]) {
|
|
244
249
|
writeFileSync(join(templateDir, file), "#!/bin/sh\n");
|
|
245
250
|
}
|
|
@@ -268,6 +273,75 @@ describe("doctor generated runtime asset preflight", () => {
|
|
|
268
273
|
});
|
|
269
274
|
});
|
|
270
275
|
|
|
276
|
+
describe("doctor TypeScript type dependency check", () => {
|
|
277
|
+
let testDir: string;
|
|
278
|
+
let originalCwd: string;
|
|
279
|
+
|
|
280
|
+
beforeEach(() => {
|
|
281
|
+
originalCwd = process.cwd();
|
|
282
|
+
testDir = join(
|
|
283
|
+
tmpdir(),
|
|
284
|
+
`tdk-doctor-types-bun-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
285
|
+
);
|
|
286
|
+
mkdirSync(testDir, { recursive: true });
|
|
287
|
+
process.chdir(testDir);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
afterEach(() => {
|
|
291
|
+
process.chdir(originalCwd);
|
|
292
|
+
if (testDir && existsSync(testDir)) {
|
|
293
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
function writeBackendResource(devDependencies: Record<string, string>) {
|
|
298
|
+
const appDir = join(testDir, "services", "finance", "cash-management-api");
|
|
299
|
+
const generatedDir = join(appDir, ".autogenerated");
|
|
300
|
+
mkdirSync(generatedDir, { recursive: true });
|
|
301
|
+
|
|
302
|
+
writeFileSync(
|
|
303
|
+
join(appDir, "service.json"),
|
|
304
|
+
JSON.stringify(
|
|
305
|
+
{
|
|
306
|
+
appName: "cash-management-api",
|
|
307
|
+
appType: "backend",
|
|
308
|
+
stack: "finance",
|
|
309
|
+
port: 4000,
|
|
310
|
+
},
|
|
311
|
+
null,
|
|
312
|
+
2,
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
writeFileSync(
|
|
316
|
+
join(appDir, "package.json"),
|
|
317
|
+
JSON.stringify({ name: "cash-management-api", devDependencies }, null, 2),
|
|
318
|
+
);
|
|
319
|
+
writeFileSync(
|
|
320
|
+
join(generatedDir, "tsconfig.docker.autogenerated.json"),
|
|
321
|
+
JSON.stringify({ compilerOptions: { types: ["bun"] } }, null, 2),
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
it('fails when a service\'s tsconfig sets "types": ["bun"] but @types/bun is not a devDependency', () => {
|
|
326
|
+
writeBackendResource({ typescript: "^5.0.0" });
|
|
327
|
+
|
|
328
|
+
const result = checkTypeScriptTypeDependencies();
|
|
329
|
+
|
|
330
|
+
expect(result.didPass).toBe(false);
|
|
331
|
+
expect(result.message).toContain("cash-management-api");
|
|
332
|
+
expect(result.message).toContain("@types/bun");
|
|
333
|
+
expect(result.fix).toContain('"@types/bun"');
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('passes when @types/bun is a devDependency alongside "types": ["bun"]', () => {
|
|
337
|
+
writeBackendResource({ typescript: "^5.0.0", "@types/bun": "^1.4.2" });
|
|
338
|
+
|
|
339
|
+
const result = checkTypeScriptTypeDependencies();
|
|
340
|
+
|
|
341
|
+
expect(result.didPass).toBe(true);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
271
345
|
describe("doctor ingress + tilt runtime checks", () => {
|
|
272
346
|
it("detects a foreign Traefik holding host port 80", () => {
|
|
273
347
|
const dockerPs = [
|
|
@@ -290,8 +364,7 @@ describe("doctor ingress + tilt runtime checks", () => {
|
|
|
290
364
|
});
|
|
291
365
|
|
|
292
366
|
it("passes when this project's Traefik owns the ingress ports", () => {
|
|
293
|
-
const dockerPs =
|
|
294
|
-
"beauty_crm_traefik\t0.0.0.0:80->80/tcp,:::80->80/tcp,0.0.0.0:443->443/tcp";
|
|
367
|
+
const dockerPs = "beauty_crm_traefik\t0.0.0.0:80->80/tcp,:::80->80/tcp,0.0.0.0:443->443/tcp";
|
|
295
368
|
const result = checkIngressPorts((() => dockerPs) as never, "beauty-crm");
|
|
296
369
|
expect(result.didPass).toBe(true);
|
|
297
370
|
expect(result.message).toContain("beauty_crm_traefik");
|
|
@@ -308,7 +381,7 @@ describe("doctor ingress + tilt runtime checks", () => {
|
|
|
308
381
|
buildHistory: [
|
|
309
382
|
{
|
|
310
383
|
error:
|
|
311
|
-
|
|
384
|
+
"Bind for 0.0.0.0:80 failed: port is already allocated\nerror: exit status 1",
|
|
312
385
|
},
|
|
313
386
|
],
|
|
314
387
|
},
|
|
@@ -337,6 +410,66 @@ describe("doctor ingress + tilt runtime checks", () => {
|
|
|
337
410
|
expect(result.fix).toMatch(/docker ps --filter publish=80|Free the conflicting/);
|
|
338
411
|
});
|
|
339
412
|
|
|
413
|
+
it("separates sablier.deferStart resources from genuinely pending ones", () => {
|
|
414
|
+
const payload = {
|
|
415
|
+
items: [
|
|
416
|
+
{
|
|
417
|
+
metadata: { name: "data-governance-api" },
|
|
418
|
+
status: { updateStatus: "none", runtimeStatus: "none" },
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
metadata: { name: "some-other-stuck-resource" },
|
|
422
|
+
status: { updateStatus: "pending", runtimeStatus: "pending" },
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
metadata: { name: "postgres" },
|
|
426
|
+
status: { updateStatus: "ok", runtimeStatus: "ok" },
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const parsed = parseTiltResourceFailures(
|
|
432
|
+
JSON.stringify(payload),
|
|
433
|
+
new Set(["data-governance-api"]),
|
|
434
|
+
);
|
|
435
|
+
expect(parsed.failures).toHaveLength(0);
|
|
436
|
+
expect(parsed.deferredCount).toBe(1);
|
|
437
|
+
expect(parsed.pendingCount).toBe(1);
|
|
438
|
+
|
|
439
|
+
const result = checkTiltResourceHealth((() => JSON.stringify(payload)) as never);
|
|
440
|
+
expect(result.didPass).toBe(true);
|
|
441
|
+
// Without an injected deferredNames set (checkTiltResourceHealth computes
|
|
442
|
+
// its own via discoverResources(), best-effort empty outside a project),
|
|
443
|
+
// this specific resource isn't classified as deferred here -- covered by
|
|
444
|
+
// the direct parseTiltResourceFailures assertions above instead.
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("does not describe deferred resources as blocked by unrelated failures", () => {
|
|
448
|
+
const payload = {
|
|
449
|
+
items: [
|
|
450
|
+
{
|
|
451
|
+
metadata: { name: "traefik" },
|
|
452
|
+
status: {
|
|
453
|
+
updateStatus: "error",
|
|
454
|
+
runtimeStatus: "unknown",
|
|
455
|
+
buildHistory: [{ error: "Bind for 0.0.0.0:80 failed: port is already allocated" }],
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
metadata: { name: "data-governance-api" },
|
|
460
|
+
status: { updateStatus: "none", runtimeStatus: "none" },
|
|
461
|
+
},
|
|
462
|
+
],
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const parsed = parseTiltResourceFailures(
|
|
466
|
+
JSON.stringify(payload),
|
|
467
|
+
new Set(["data-governance-api"]),
|
|
468
|
+
);
|
|
469
|
+
expect(parsed.deferredCount).toBe(1);
|
|
470
|
+
expect(parsed.pendingCount).toBe(0);
|
|
471
|
+
});
|
|
472
|
+
|
|
340
473
|
it("skips tilt resource check when tilt is not running", () => {
|
|
341
474
|
const result = checkTiltResourceHealth((() => {
|
|
342
475
|
throw new Error("tilt not running");
|
|
@@ -555,3 +688,43 @@ describe("doctor ingress + tilt runtime checks", () => {
|
|
|
555
688
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
556
689
|
});
|
|
557
690
|
});
|
|
691
|
+
|
|
692
|
+
describe("doctor Docker version check", () => {
|
|
693
|
+
function fakeExec(engine: string, compose: string) {
|
|
694
|
+
return ((command: string) =>
|
|
695
|
+
command.startsWith("docker compose") ? `${compose}\n` : `${engine}\n`) as never;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
it("passes on Docker Engine 25+ and Compose 2.20.2+", () => {
|
|
699
|
+
const result = checkDockerVersions(fakeExec("29.8.0", "2.39.1"));
|
|
700
|
+
|
|
701
|
+
expect(result.didPass).toBe(true);
|
|
702
|
+
expect(result.isSkipped).toBeFalsy();
|
|
703
|
+
expect(result.message).toContain("29.8.0");
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
it("fails with an upgrade hint when the engine is older than 25", () => {
|
|
707
|
+
const result = checkDockerVersions(fakeExec("24.0.7", "2.39.1"));
|
|
708
|
+
|
|
709
|
+
expect(result.didPass).toBe(false);
|
|
710
|
+
expect(result.message).toContain("Docker Engine 24.0.7");
|
|
711
|
+
expect(result.message).toContain("start_interval");
|
|
712
|
+
expect(result.fix).toContain("Update Docker");
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
it("fails when Compose is older than 2.20.2", () => {
|
|
716
|
+
const result = checkDockerVersions(fakeExec("27.1.1", "v2.20.1"));
|
|
717
|
+
|
|
718
|
+
expect(result.didPass).toBe(false);
|
|
719
|
+
expect(result.message).toContain("Docker Compose v2.20.1");
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it("skips instead of failing when versions cannot be read", () => {
|
|
723
|
+
const result = checkDockerVersions((() => {
|
|
724
|
+
throw new Error("docker not found");
|
|
725
|
+
}) as never);
|
|
726
|
+
|
|
727
|
+
expect(result.didPass).toBe(true);
|
|
728
|
+
expect(result.isSkipped).toBe(true);
|
|
729
|
+
});
|
|
730
|
+
});
|
|
@@ -75,9 +75,7 @@ describe("Project → Phase → Stack → Resource model", () => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it("deduplicates enabledStacks per phase", () => {
|
|
78
|
-
const enabledStacks = Array.from(
|
|
79
|
-
new Set(["proxy", "billing", "checkout-app", "billing"]),
|
|
80
|
-
);
|
|
78
|
+
const enabledStacks = Array.from(new Set(["proxy", "billing", "checkout-app", "billing"]));
|
|
81
79
|
|
|
82
80
|
expect(enabledStacks).toEqual(["proxy", "billing", "checkout-app"]);
|
|
83
81
|
expect(enabledStacks.filter((s) => s === "billing")).toHaveLength(1);
|
|
@@ -142,7 +140,7 @@ describe("Project → Phase → Stack → Resource model", () => {
|
|
|
142
140
|
const resourceEntries = enabledStacks.map((stack) => `"${stack}": True`);
|
|
143
141
|
const specMaster = `PRE_ALPHA_RESOURCES = {\n${resourceEntries.join(",\n")}\n}`;
|
|
144
142
|
|
|
145
|
-
expect(specMaster).toContain(
|
|
143
|
+
expect(specMaster).toContain("PRE_ALPHA_RESOURCES = {");
|
|
146
144
|
expect(specMaster).toContain('"billing": True');
|
|
147
145
|
expect(specMaster).toContain('"checkout-app": True');
|
|
148
146
|
expect(specMaster).not.toContain('"services"');
|
|
@@ -34,7 +34,7 @@ describe("project and resource feature E2E", () => {
|
|
|
34
34
|
let projectRoot = "";
|
|
35
35
|
|
|
36
36
|
afterEach(() => {
|
|
37
|
-
if (projectRoot
|
|
37
|
+
if (projectRoot?.startsWith(tmpdir())) {
|
|
38
38
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
39
39
|
}
|
|
40
40
|
});
|
|
@@ -113,9 +113,7 @@ describe("project and resource feature E2E", () => {
|
|
|
113
113
|
"prisma-normalize-client.sh",
|
|
114
114
|
]) {
|
|
115
115
|
expect(
|
|
116
|
-
existsSync(
|
|
117
|
-
join(projectRoot, "shared-platform-engineering", "docker-templates", file),
|
|
118
|
-
),
|
|
116
|
+
existsSync(join(projectRoot, "shared-platform-engineering", "docker-templates", file)),
|
|
119
117
|
).toBe(true);
|
|
120
118
|
}
|
|
121
119
|
}, 10000);
|
|
@@ -166,30 +164,12 @@ describe("project and resource feature E2E", () => {
|
|
|
166
164
|
runTdk(["project", "--yes"], projectRoot);
|
|
167
165
|
|
|
168
166
|
runTdk(
|
|
169
|
-
[
|
|
170
|
-
"resource",
|
|
171
|
-
"api",
|
|
172
|
-
"--type",
|
|
173
|
-
"backend",
|
|
174
|
-
"--stack",
|
|
175
|
-
"alpha",
|
|
176
|
-
"--path",
|
|
177
|
-
"services/alpha/api",
|
|
178
|
-
],
|
|
167
|
+
["resource", "api", "--type", "backend", "--stack", "alpha", "--path", "services/alpha/api"],
|
|
179
168
|
projectRoot,
|
|
180
169
|
"\n",
|
|
181
170
|
);
|
|
182
171
|
runTdk(
|
|
183
|
-
[
|
|
184
|
-
"resource",
|
|
185
|
-
"web",
|
|
186
|
-
"--type",
|
|
187
|
-
"frontend",
|
|
188
|
-
"--stack",
|
|
189
|
-
"alpha",
|
|
190
|
-
"--path",
|
|
191
|
-
"services/alpha/web",
|
|
192
|
-
],
|
|
172
|
+
["resource", "web", "--type", "frontend", "--stack", "alpha", "--path", "services/alpha/web"],
|
|
193
173
|
projectRoot,
|
|
194
174
|
"\n",
|
|
195
175
|
);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { describe, expect, it, beforeEach, afterEach } from "vitest";
|
|
2
1
|
import { execSync } from "node:child_process";
|
|
3
2
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
3
|
import { tmpdir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
6
5
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import {
|
|
6
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
8
7
|
|
|
9
8
|
// Get the CLI bin path dynamically
|
|
10
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -48,8 +47,7 @@ describe.skipIf(!EXTENSION_SOURCE_AVAILABLE)("saas-starter cloning and discovery
|
|
|
48
47
|
try {
|
|
49
48
|
// Safety: only delete if path is under tmpdir and contains our test marker
|
|
50
49
|
if (
|
|
51
|
-
testDir &&
|
|
52
|
-
testDir.startsWith(tmpdir()) &&
|
|
50
|
+
testDir?.startsWith(tmpdir()) &&
|
|
53
51
|
testDir.includes("tdk-saas-test-") &&
|
|
54
52
|
testDir.length > 20
|
|
55
53
|
) {
|
|
@@ -117,7 +115,7 @@ describe.skipIf(!EXTENSION_SOURCE_AVAILABLE)("saas-starter cloning and discovery
|
|
|
117
115
|
// Generate project config
|
|
118
116
|
execSync(
|
|
119
117
|
`cd "${starterRoot}" && TDK_EXTENSION_SOURCE="${EXTENSION_SOURCE}" bun "${CLI_BIN_PATH}" project --yes`,
|
|
120
|
-
{ stdio: "pipe" }
|
|
118
|
+
{ stdio: "pipe" },
|
|
121
119
|
);
|
|
122
120
|
|
|
123
121
|
// Verify project.json has services populated
|
|
@@ -148,7 +146,7 @@ describe.skipIf(!EXTENSION_SOURCE_AVAILABLE)("saas-starter cloning and discovery
|
|
|
148
146
|
|
|
149
147
|
execSync(
|
|
150
148
|
`cd "${starterRoot}" && TDK_EXTENSION_SOURCE="${EXTENSION_SOURCE}" bun ${CLI_BIN_PATH} project --yes`,
|
|
151
|
-
{ stdio: "pipe" }
|
|
149
|
+
{ stdio: "pipe" },
|
|
152
150
|
);
|
|
153
151
|
|
|
154
152
|
const specPath = join(starterRoot, ".tdk", ".tdk-out", "spec.master");
|
|
@@ -158,10 +156,10 @@ describe.skipIf(!EXTENSION_SOURCE_AVAILABLE)("saas-starter cloning and discovery
|
|
|
158
156
|
|
|
159
157
|
// Before fix: PRE_ALPHA_RESOURCES = { }
|
|
160
158
|
// After fix: PRE_ALPHA_RESOURCES = { "app": True, "billing": True, }
|
|
161
|
-
expect(specContent).toContain(
|
|
159
|
+
expect(specContent).toContain("PRE_ALPHA_RESOURCES = {");
|
|
162
160
|
expect(specContent).toMatch(/"app":\s*True/);
|
|
163
161
|
expect(specContent).toMatch(/"billing":\s*True/);
|
|
164
|
-
expect(specContent).toContain(
|
|
162
|
+
expect(specContent).toContain("FOCUS_PRE_ALPHA = list(PRE_ALPHA_RESOURCES.keys())");
|
|
165
163
|
});
|
|
166
164
|
|
|
167
165
|
/**
|
|
@@ -181,7 +179,7 @@ describe.skipIf(!EXTENSION_SOURCE_AVAILABLE)("saas-starter cloning and discovery
|
|
|
181
179
|
|
|
182
180
|
execSync(
|
|
183
181
|
`cd "${starterRoot}" && TDK_EXTENSION_SOURCE="${EXTENSION_SOURCE}" bun ${CLI_BIN_PATH} project --yes`,
|
|
184
|
-
{ stdio: "pipe" }
|
|
182
|
+
{ stdio: "pipe" },
|
|
185
183
|
);
|
|
186
184
|
|
|
187
185
|
// Doctor should pass (all master configs present)
|
|
@@ -25,7 +25,7 @@ describe("stack feature E2E", () => {
|
|
|
25
25
|
let projectRoot = "";
|
|
26
26
|
|
|
27
27
|
afterEach(() => {
|
|
28
|
-
if (projectRoot
|
|
28
|
+
if (projectRoot?.startsWith(tmpdir())) {
|
|
29
29
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
30
30
|
}
|
|
31
31
|
});
|
|
@@ -36,7 +36,9 @@ describe("stack feature E2E", () => {
|
|
|
36
36
|
const output = runTdk(["project", "--yes"], projectRoot);
|
|
37
37
|
expect(output).toContain("Generated: services/platform/database-management/docker-compose.yml");
|
|
38
38
|
|
|
39
|
-
const projectJson = JSON.parse(
|
|
39
|
+
const projectJson = JSON.parse(
|
|
40
|
+
readFileSync(join(projectRoot, ".tdk", "project.json"), "utf-8"),
|
|
41
|
+
);
|
|
40
42
|
expect(projectJson.stack_features).toBeUndefined();
|
|
41
43
|
expect(projectJson.phases.pre_alpha.enabledStacks).toContain("database-management");
|
|
42
44
|
|
|
@@ -51,7 +53,9 @@ describe("stack feature E2E", () => {
|
|
|
51
53
|
|
|
52
54
|
const compose = readFileSync(composePath, "utf-8");
|
|
53
55
|
expect(compose).toContain("Stack feature: database-management");
|
|
54
|
-
expect(compose).toContain(
|
|
56
|
+
expect(compose).toContain(
|
|
57
|
+
'Source: .tdk/project.json phases.*.enabledStacks includes "database-management"',
|
|
58
|
+
);
|
|
55
59
|
expect(compose).toContain("container_name: tdk_stack_feature_");
|
|
56
60
|
expect(compose).toContain("_postgres");
|
|
57
61
|
expect(compose).toContain("_database");
|
|
@@ -120,7 +124,9 @@ describe("stack feature E2E", () => {
|
|
|
120
124
|
|
|
121
125
|
runTdk(["project", "--yes"], projectRoot);
|
|
122
126
|
|
|
123
|
-
const projectJson = JSON.parse(
|
|
127
|
+
const projectJson = JSON.parse(
|
|
128
|
+
readFileSync(join(projectRoot, ".tdk", "project.json"), "utf-8"),
|
|
129
|
+
);
|
|
124
130
|
expect(projectJson.phases.pre_alpha.enabledStacks).toContain("billing");
|
|
125
131
|
|
|
126
132
|
const spec = readFileSync(join(projectRoot, ".tdk", ".tdk-out", "spec.master"), "utf-8");
|
|
@@ -9,6 +9,7 @@ vi.mock("node:child_process", () => ({
|
|
|
9
9
|
}));
|
|
10
10
|
|
|
11
11
|
const { upgradeViaBinary, isWritable } = await import("../upgrade.js");
|
|
12
|
+
|
|
12
13
|
import type { BinaryRelease } from "../upgrade.js";
|
|
13
14
|
|
|
14
15
|
// Regression coverage for: `tdk upgrade` used to only swap the `tdk` binary
|
|
@@ -56,7 +57,8 @@ describe("upgradeViaBinary", () => {
|
|
|
56
57
|
expect(commands.some((c) => c.startsWith("mkdir -p") && c.includes(engineDir))).toBe(true);
|
|
57
58
|
expect(
|
|
58
59
|
commands.some(
|
|
59
|
-
(c) =>
|
|
60
|
+
(c) =>
|
|
61
|
+
c.includes("tar -xzf") && c.includes(engineDir) && c.includes("--strip-components=1"),
|
|
60
62
|
),
|
|
61
63
|
).toBe(true);
|
|
62
64
|
});
|
|
@@ -77,19 +79,27 @@ describe("upgradeViaBinary", () => {
|
|
|
77
79
|
expect(tarIndex).toBeGreaterThan(engineCurlIndex);
|
|
78
80
|
});
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
chmodSync(installDir,
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
// root ignores the write-permission bit (accessSync(W_OK) legitimately
|
|
83
|
+
// returns true even on a 0o555 dir), so these checks only hold for
|
|
84
|
+
// non-root users.
|
|
85
|
+
const isRoot = process.getuid?.() === 0;
|
|
86
|
+
|
|
87
|
+
it.skipIf(isRoot)(
|
|
88
|
+
"never shells out to sudo, and fails fast without touching the network when the install dir isn't writable",
|
|
89
|
+
async () => {
|
|
90
|
+
chmodSync(installDir, 0o555);
|
|
91
|
+
try {
|
|
92
|
+
const ok = await upgradeViaBinary(tdkPath, release);
|
|
93
|
+
expect(ok).toBe(false);
|
|
94
|
+
expect(execSyncMock).not.toHaveBeenCalled();
|
|
95
|
+
expect(commandsRun().some((c) => c.includes("sudo"))).toBe(false);
|
|
96
|
+
} finally {
|
|
97
|
+
chmodSync(installDir, 0o755);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
);
|
|
91
101
|
|
|
92
|
-
it("isWritable reflects actual filesystem permissions", () => {
|
|
102
|
+
it.skipIf(isRoot)("isWritable reflects actual filesystem permissions", () => {
|
|
93
103
|
expect(isWritable(installDir)).toBe(true);
|
|
94
104
|
chmodSync(installDir, 0o555);
|
|
95
105
|
try {
|