@tdk-landscape/tdk-cli-core 1.3.155 → 1.3.157
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/cli/dist/commands/doctor.js +103 -1
- package/cli/dist/commands/up.js +27 -4
- package/cli/dist/generator/template-engine.js +23 -0
- package/cli/dist/utils/doctor-crashloop.js +161 -0
- package/cli/dist/utils/doctor-fix.js +231 -0
- package/cli/dist/utils/tilt-port-owner.js +49 -0
- package/cli/dist-bundle/chunk-O2SVXNG5.js +377 -0
- package/cli/dist-bundle/cli.js +320 -370
- package/cli/dist-bundle/{cold-preflight-3RDK76RY.js → cold-preflight-OQUN7OFG.js} +1 -1
- package/cli/package.json +1 -1
- package/discovery/manifest/loading.star +7 -1
- package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +5 -4
- package/engine/topologies/platform/docker/compose/compose.star +10 -5
- package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +1 -1
- package/engine/topologies/platform/docker/layers/l1_base_layers.star +1 -1
- package/engine/topologies/platform/docker/layers/l3_builder_layers.star +1 -1
- package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +14 -1
- package/engine/topologies/tilt/manifest/constants.star +1 -1
- package/package.json +1 -1
- package/cli/dist-bundle/chunk-XTSHWDDE.js +0 -322
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
|
|
2
|
-
import{
|
|
2
|
+
import{Ib as a,Jb as b,Kb as c,Lb as d,Mb as e}from"./chunk-O2SVXNG5.js";import"./chunk-42IVF3YT.js";import"./chunk-6EA4DGCY.js";export{e as assertMachineReadyOrExit,d as formatColdPreflight,a as nodeTooOld,b as requireVerifiedDockerVersions,c as runColdPreflight};
|
package/cli/package.json
CHANGED
|
@@ -218,7 +218,13 @@ def _apply_manifest_defaults(manifest, resource_path):
|
|
|
218
218
|
for key, default_value in MANIFEST_DEFAULTS.items():
|
|
219
219
|
if key not in result or result[key] == None:
|
|
220
220
|
result[key] = default_value
|
|
221
|
-
|
|
221
|
+
|
|
222
|
+
# A bring-your-own service may not speak HTTP, so only an explicit healthCheckPath gives it one. compose.star and
|
|
223
|
+
# l4_runtime_layers.star read a missing path as "no HTTP probe"; the default above would otherwise hide that.
|
|
224
|
+
# (ManifestParser.normalize applies the same rule, but `tdk up` does not load manifests through it.)
|
|
225
|
+
if result.get('appType') == 'bring-your-own' and not manifest.get('healthCheckPath'):
|
|
226
|
+
result.pop('healthCheckPath', None)
|
|
227
|
+
|
|
222
228
|
# 🎯 CEO REVIEW: Traefik-native port strategy
|
|
223
229
|
# Port is constant per appType, not dynamically assigned
|
|
224
230
|
# Traefik routes by hostname (e.g., booking.backend.{project}.local), not port
|
|
@@ -165,9 +165,10 @@ ENV BUN_OPTIONS=--smol
|
|
|
165
165
|
|
|
166
166
|
USER bun
|
|
167
167
|
|
|
168
|
-
# Backend-specific healthcheck
|
|
168
|
+
# Backend-specific healthcheck: probes the service over HTTP. The image is shared by every backend,
|
|
169
|
+
# so the port and path come from the container env (PORT is set by compose, TDK_HEALTH_PATH is optional).
|
|
169
170
|
HEALTHCHECK {hc_flags} \
|
|
170
|
-
CMD bun
|
|
171
|
+
CMD bun -e "fetch('http://127.0.0.1:'+process.env.PORT+(process.env.TDK_HEALTH_PATH||'/health')).then(r=>process.exit(r.ok?0:1),()=>process.exit(1))" || exit 1
|
|
171
172
|
|
|
172
173
|
WORKDIR /app
|
|
173
174
|
|
|
@@ -194,9 +195,9 @@ RUN addgroup -S app && adduser -S app -G app
|
|
|
194
195
|
|
|
195
196
|
USER app
|
|
196
197
|
|
|
197
|
-
# Backend-specific healthcheck (
|
|
198
|
+
# Backend-specific healthcheck: probes the service over HTTP (port and path from container env, see the Bun stage)
|
|
198
199
|
HEALTHCHECK {hc_flags} \
|
|
199
|
-
CMD node
|
|
200
|
+
CMD node -e "fetch('http://127.0.0.1:'+process.env.PORT+(process.env.TDK_HEALTH_PATH||'/health')).then(r=>process.exit(r.ok?0:1),()=>process.exit(1))" || exit 1
|
|
200
201
|
|
|
201
202
|
WORKDIR /app
|
|
202
203
|
|
|
@@ -14,6 +14,7 @@ BASE_PORT_BACKEND = 4000
|
|
|
14
14
|
# emits a fixed `EXPOSE 80` and the generated nginx.conf has a fixed `listen 80`.
|
|
15
15
|
NGINX_CONTAINER_PORT = 80
|
|
16
16
|
HEALTH_CHECK_PATH = "/health"
|
|
17
|
+
NO_HTTP_HEALTHCHECK = " healthcheck:\n disable: true\n"
|
|
17
18
|
OUTPUT = struct(AUTOGENERATED_FOLDER = ".autogenerated")
|
|
18
19
|
# === END INLINED CONSTANTS ===
|
|
19
20
|
|
|
@@ -266,11 +267,14 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
266
267
|
restart_policy = manifest.get('restart')
|
|
267
268
|
restart_policy = '"no"' if restart_policy == 'no' else restart_policy
|
|
268
269
|
|
|
270
|
+
# No HTTP server means no HTTP probe. Disable explicitly: the image HEALTHCHECK would otherwise probe a port nothing listens on.
|
|
271
|
+
no_http_healthcheck_section = NO_HTTP_HEALTHCHECK if (is_worker or health_path == None) else ""
|
|
272
|
+
# Backends with a health path get it in the env, so the shared golden image's HEALTHCHECK can probe it.
|
|
273
|
+
health_env = " - TDK_HEALTH_PATH={}\n".format(health_path) if health_path else ""
|
|
274
|
+
|
|
269
275
|
if is_worker or is_proxy_disabled_byo:
|
|
270
276
|
traefik_labels = ' - "traefik.enable=false"'
|
|
271
|
-
healthcheck_section =
|
|
272
|
-
test: ["CMD", "curl", "-f", "--max-time", "5", "http://localhost:{internal_port}{health_path}"]
|
|
273
|
-
""".format(internal_port=internal_port, health_path=health_path) + compose_healthcheck_timing()
|
|
277
|
+
healthcheck_section = no_http_healthcheck_section
|
|
274
278
|
else:
|
|
275
279
|
# Traefik's load-balancer check can be overridden separately in service.json
|
|
276
280
|
# (`traefik.healthCheck`); it defaults to the container check's path.
|
|
@@ -287,7 +291,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
287
291
|
# BYO images may not contain curl. Traefik uses its own HTTP health
|
|
288
292
|
# check labels above, so don't mark an otherwise healthy container
|
|
289
293
|
# unhealthy because the image lacks a command TDK cannot require.
|
|
290
|
-
healthcheck_section = "" if is_byo else """ healthcheck:
|
|
294
|
+
healthcheck_section = no_http_healthcheck_section if no_http_healthcheck_section else "" if is_byo else """ healthcheck:
|
|
291
295
|
test: ["CMD", "curl", "-f", "--max-time", "5", "http://localhost:{internal_port}{health_path}"]
|
|
292
296
|
""".format(internal_port=internal_port, health_path=health_path) + compose_healthcheck_timing()
|
|
293
297
|
infisical_env = get_infisical_environment_vars(as_array=True, resource_name=res_name)
|
|
@@ -307,7 +311,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
307
311
|
{infisical_env}
|
|
308
312
|
- RESOURCE_NAME={stack}
|
|
309
313
|
- PORT={port_anchor}
|
|
310
|
-
- INSTANCE_ID={instance_label}
|
|
314
|
+
{health_env} - INSTANCE_ID={instance_label}
|
|
311
315
|
- NATS_QUEUE_GROUP={nats_queue}
|
|
312
316
|
- TILT_DATABASE_URL={db_url_for_tilt}
|
|
313
317
|
- TILT_NATS_URL={nats_url}
|
|
@@ -363,6 +367,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
|
|
|
363
367
|
nats_url=nats_url,
|
|
364
368
|
traefik_labels=traefik_labels,
|
|
365
369
|
healthcheck_section=healthcheck_section,
|
|
370
|
+
health_env=health_env,
|
|
366
371
|
infisical_env=infisical_env,
|
|
367
372
|
auth_env=auth_env,
|
|
368
373
|
secrets_env=secrets_env,
|
|
@@ -9,7 +9,7 @@ Provides the foundational layers for all Dockerfiles:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
BUN_BASE = "oven/bun:1.3.11-alpine"
|
|
12
|
-
ALPINE_BASE = "alpine:3.
|
|
12
|
+
ALPINE_BASE = "alpine:3.22"
|
|
13
13
|
load('../../../../../discovery/config.star', 'GLOBAL_CONFIG')
|
|
14
14
|
|
|
15
15
|
# Load project name for dynamic golden image naming
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
# === INLINED CONSTANTS for pure extension loading ===
|
|
4
4
|
WEB_FRAMEWORK = "hono"
|
|
5
|
-
RUNTIME_CONFIG = {"bun": {"image_base": "oven/bun:1.3.11-alpine", "package_manager": "bun", "lockfile": "bun.lock", "backend_start_command": "bun run start", "frontend_start_command": "bun run dev"}, "node": {"image_base": "node:
|
|
5
|
+
RUNTIME_CONFIG = {"bun": {"image_base": "oven/bun:1.3.11-alpine", "package_manager": "bun", "lockfile": "bun.lock", "backend_start_command": "bun run start", "frontend_start_command": "bun run dev"}, "node": {"image_base": "node:22-alpine", "package_manager": "npm", "lockfile": "package-lock.json", "backend_start_command": "node dist/index.js"}}
|
|
6
6
|
OUTPUT = struct(AUTOGENERATED_FOLDER = ".autogenerated")
|
|
7
7
|
# === END INLINED CONSTANTS ===
|
|
8
8
|
|
|
@@ -107,6 +107,19 @@ def _cmd_instruction(command):
|
|
|
107
107
|
return "CMD [" + ", ".join(["\"" + part + "\"" for part in command.split()]) + "]\n"
|
|
108
108
|
|
|
109
109
|
|
|
110
|
+
def _backend_healthcheck_instruction(port, manifest = None):
|
|
111
|
+
# Probe the service over HTTP, not the runtime binary: `bun --version` passes even when the server has crashed.
|
|
112
|
+
# Workers and bring-your-own services without healthCheckPath serve no HTTP, so they get no probe (HEALTHCHECK NONE).
|
|
113
|
+
if manifest and (manifest.get('appType') == 'worker' or (manifest.get('appType') == 'bring-your-own' and not manifest.get('healthCheckPath'))):
|
|
114
|
+
return "HEALTHCHECK NONE\n"
|
|
115
|
+
health_path = manifest.get('healthCheckPath', '/health') if manifest else '/health'
|
|
116
|
+
# The Dockerfile generator passes the manifest but not the port, so the service's own port wins over the 4000 default.
|
|
117
|
+
probe_port = manifest.get('port', port) if manifest else port
|
|
118
|
+
# fetch() is built into bun, so no extra package is needed in the image. Path is schema-limited to [a-z0-9/-].
|
|
119
|
+
probe = "fetch('http://127.0.0.1:" + str(probe_port) + health_path + "').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"
|
|
120
|
+
return "HEALTHCHECK " + dockerfile_healthcheck_flags() + " CMD bun -e \"" + probe + "\" || exit 1\n"
|
|
121
|
+
|
|
122
|
+
|
|
110
123
|
def L4_generate_backend_runtime(res_path, port = BASE_PORT_BACKEND, cmd = 'bun run start', use_infisical = False, resource_name = 'service', use_golden = True, use_prisma = True, has_prisma_config = False, manifest = None):
|
|
111
124
|
"""
|
|
112
125
|
Generate the backend runtime layer for deployed services.
|
|
@@ -174,7 +187,7 @@ def L4_generate_backend_runtime(res_path, port = BASE_PORT_BACKEND, cmd = 'bun r
|
|
|
174
187
|
|
|
175
188
|
# Only add healthcheck if not using golden image (already in golden L4)
|
|
176
189
|
if not use_golden:
|
|
177
|
-
parts.append(
|
|
190
|
+
parts.append(_backend_healthcheck_instruction(port, manifest))
|
|
178
191
|
|
|
179
192
|
if use_infisical:
|
|
180
193
|
# Use InfisicalDocker generator for proper secret injection setup
|