@tdk-landscape/tdk-cli-core 1.3.15 → 1.3.22
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/Tiltfile +144 -0
- package/discovery/AGENTS.md +362 -0
- package/discovery/TILT_DISCOVERY.star +424 -0
- package/discovery/Tiltfile +58 -0
- package/discovery/config.star +258 -0
- package/discovery/constants.star +127 -0
- package/discovery/deterministic.star +211 -0
- package/discovery/discovery_daemon.star +191 -0
- package/discovery/discovery_orchestrator.star +460 -0
- package/discovery/filtering.star +5 -0
- package/discovery/identity-management-backend/service.yaml +26 -0
- package/discovery/identity-management-frontend/service.yaml +29 -0
- package/discovery/identity-sdk/service.yaml +9 -0
- package/discovery/incremental_discovery.star +213 -0
- package/discovery/indexing.star +7 -0
- package/discovery/json_manifest_scanner.star +51 -0
- package/discovery/libraries.star +46 -0
- package/discovery/loading.star +23 -0
- package/discovery/manifest/constants.star +104 -0
- package/discovery/manifest/loading.star +386 -0
- package/discovery/manifest/normalize.star +281 -0
- package/discovery/manifest/validation.star +108 -0
- package/discovery/normalization.star +11 -0
- package/discovery/registry.star +544 -0
- package/discovery/resource_snapshot.py +382 -0
- package/discovery/resource_snapshot.star +143 -0
- package/discovery/schemas.star +1 -0
- package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
- package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
- package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
- package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
- package/discovery/test_resource_snapshot.py +251 -0
- package/discovery/validation.star +78 -0
- package/discovery/versioning.star +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +11 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +1 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +36 -41
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/resource.d.ts.map +1 -1
- package/dist/commands/resource.js +51 -55
- package/dist/commands/resource.js.map +1 -1
- package/dist/commands/stack.d.ts.map +1 -1
- package/dist/commands/stack.js +22 -24
- package/dist/commands/stack.js.map +1 -1
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +1 -2
- package/dist/commands/ui.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +1 -2
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/upgrade.d.ts +8 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +59 -18
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/generator/extension-fetch.d.ts +19 -0
- package/dist/generator/extension-fetch.d.ts.map +1 -1
- package/dist/generator/extension-fetch.js +71 -5
- package/dist/generator/extension-fetch.js.map +1 -1
- package/dist/generator/template-engine.d.ts +1 -0
- package/dist/generator/template-engine.d.ts.map +1 -1
- package/dist/generator/template-engine.js +50 -6
- package/dist/generator/template-engine.js.map +1 -1
- package/dist/utils/command-helpers.d.ts.map +1 -1
- package/dist/utils/command-helpers.js +7 -9
- package/dist/utils/command-helpers.js.map +1 -1
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +1 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/errors.d.ts +2 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +6 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/project-features.d.ts.map +1 -1
- package/dist/utils/project-features.js +1 -1
- package/dist/utils/project-features.js.map +1 -1
- package/dist/utils/resource-features.d.ts.map +1 -1
- package/dist/utils/resource-features.js +2 -2
- package/dist/utils/resource-features.js.map +1 -1
- package/dist/utils/tar.js +4 -4
- package/dist/utils/tar.js.map +1 -1
- package/dist/utils/validation.d.ts +7 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +9 -0
- package/dist/utils/validation.js.map +1 -1
- package/engine/AGENTS.md +705 -0
- package/engine/README.md +29 -0
- package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
- package/engine/Tiltfile +80 -0
- package/engine/assets/docker/golden-layers.Dockerfile +221 -0
- package/engine/assets/scripts/cleanup-completed-migrator-images.sh +37 -0
- package/engine/assets/scripts/cleanup-tilt-images.sh +120 -0
- package/engine/assets/scripts/mac-m1-resource-monitor.sh +121 -0
- package/engine/config.star +3 -0
- package/engine/docs/AUTODISCOVERY_TEST.md +182 -0
- package/engine/docs/C4-ARCHITECTURE-operations.md +396 -0
- package/engine/docs/C4-ARCHITECTURE-overview.md +284 -0
- package/engine/docs/C4-ARCHITECTURE.md +17 -0
- package/engine/docs/GOLDEN_IMAGE_INTEGRATION.md +349 -0
- package/engine/docs/MANIFEST_DRIVEN_ARCHITECTURE.md +357 -0
- package/engine/docs/README.md +284 -0
- package/engine/entrypoint.star +97 -0
- package/engine/lifecycle/orchestrator.star +260 -0
- package/engine/paths.star +717 -0
- package/engine/schemas/manifest-schema.json +301 -0
- package/engine/schemas/service-schema.json +301 -0
- package/engine/scripts/README.md +89 -0
- package/engine/scripts/build-and-publish-lib.sh +205 -0
- package/engine/scripts/check-lib-publish.sh +85 -0
- package/engine/scripts/debug-container.sh +258 -0
- package/engine/scripts/generate-manifest.sh +197 -0
- package/engine/spec.master +702 -0
- package/engine/spec.master.example +341 -0
- package/engine/topologies/README.md +34 -0
- package/engine/topologies/platform/docker/AGENTS.md +59 -0
- package/engine/topologies/platform/docker/auth/auth.star +167 -0
- package/engine/topologies/platform/docker/build/golden_image.star +37 -0
- package/engine/topologies/platform/docker/build/golden_image_build.star +82 -0
- package/engine/topologies/platform/docker/build/golden_image_constants.star +93 -0
- package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +291 -0
- package/engine/topologies/platform/docker/compose/compose.star +636 -0
- package/engine/topologies/platform/docker/compose/compose_helpers.star +52 -0
- package/engine/topologies/platform/docker/compose/traefik_standalone.star +53 -0
- package/engine/topologies/platform/docker/config/bunignore.star +142 -0
- package/engine/topologies/platform/docker/config/dockerignore.star +150 -0
- package/engine/topologies/platform/docker/constants.star +170 -0
- package/engine/topologies/platform/docker/dockerfile/dockerfile.star +54 -0
- package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +73 -0
- package/engine/topologies/platform/docker/index.star +27 -0
- package/engine/topologies/platform/docker/layers/bun_helpers.star +23 -0
- package/engine/topologies/platform/docker/layers/infisical/index.star +40 -0
- package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +262 -0
- package/engine/topologies/platform/docker/layers/l1_base_layers.star +87 -0
- package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +125 -0
- package/engine/topologies/platform/docker/layers/l3_builder_layers.star +209 -0
- package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +214 -0
- package/engine/topologies/platform/docker/layers/prisma/constants.star +135 -0
- package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +96 -0
- package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +109 -0
- package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +98 -0
- package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +126 -0
- package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +161 -0
- package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +119 -0
- package/engine/topologies/platform/docker/networking/api_path_constants.star +230 -0
- package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +27 -0
- package/engine/topologies/platform/docker/networking/traefik.star +232 -0
- package/engine/topologies/platform/docker/networking/traefik_constants.star +146 -0
- package/engine/topologies/platform/docker/networking/traefik_helpers.star +160 -0
- package/engine/topologies/platform/docker/secrets/infisical.star +135 -0
- package/engine/topologies/platform/net/proxy.star +4 -0
- package/engine/topologies/platform/registries/local.star +4 -0
- package/engine/topologies/platform/security/secrets.star +239 -0
- package/engine/topologies/platform/state/relational.star +4 -0
- package/engine/topologies/tilt/common/AGENTS.md +59 -0
- package/engine/topologies/tilt/common/utils.star +364 -0
- package/engine/topologies/tilt/common/utils_debug.star +69 -0
- package/engine/topologies/tilt/common/utils_deterministic.star +168 -0
- package/engine/topologies/tilt/common/utils_docker_networks.star +46 -0
- package/engine/topologies/tilt/common/utils_env.star +43 -0
- package/engine/topologies/tilt/common/utils_output.star +97 -0
- package/engine/topologies/tilt/config/AGENTS.md +68 -0
- package/engine/topologies/tilt/config/defaults.star +3 -0
- package/engine/topologies/tilt/config/feature_flags.star +10 -0
- package/engine/topologies/tilt/config/global.star +55 -0
- package/engine/topologies/tilt/config/profiles.star +382 -0
- package/engine/topologies/tilt/generators/agents_md.star +62 -0
- package/engine/topologies/tilt/generators/api_gateway.star +145 -0
- package/engine/topologies/tilt/generators/index.star +124 -0
- package/engine/topologies/tilt/generators/infisical/README.md +424 -0
- package/engine/topologies/tilt/generators/infisical/examples.star +312 -0
- package/engine/topologies/tilt/generators/infisical/index.star +57 -0
- package/engine/topologies/tilt/generators/infisical/machine_identity.star +420 -0
- package/engine/topologies/tilt/generators/infisical/organization.star +534 -0
- package/engine/topologies/tilt/generators/infisical/path_manager.star +476 -0
- package/engine/topologies/tilt/generators/infisical/secrets_generator.star +420 -0
- package/engine/topologies/tilt/generators/nginx_conf.star +143 -0
- package/engine/topologies/tilt/generators/npmrc.star +111 -0
- package/engine/topologies/tilt/generators/tsconfig.star +23 -0
- package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +71 -0
- package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +124 -0
- package/engine/topologies/tilt/generators/typescript/common.star +7 -0
- package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +76 -0
- package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +110 -0
- package/engine/topologies/tilt/generators/typescript/include.star +23 -0
- package/engine/topologies/tilt/generators/typescript/playwright_config.star +40 -0
- package/engine/topologies/tilt/generators/typescript/prisma_config.star +49 -0
- package/engine/topologies/tilt/generators/validators.star +853 -0
- package/engine/topologies/tilt/generators/vite/backend.star +78 -0
- package/engine/topologies/tilt/generators/vite/frontend.star +98 -0
- package/engine/topologies/tilt/generators/vite/generators.star +43 -0
- package/engine/topologies/tilt/generators/vite/helpers.star +244 -0
- package/engine/topologies/tilt/generators/vite/library.star +65 -0
- package/engine/topologies/tilt/generators/vite/sdk.star +73 -0
- package/engine/topologies/tilt/generators/vite/templates.star +737 -0
- package/engine/topologies/tilt/generators/vite_config.star +22 -0
- package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
- package/engine/topologies/tilt/manifest/README.md +693 -0
- package/engine/topologies/tilt/manifest/__init__.star +218 -0
- package/engine/topologies/tilt/manifest/constants.star +252 -0
- package/engine/topologies/tilt/manifest/errors.star +266 -0
- package/engine/topologies/tilt/manifest/integration.star +339 -0
- package/engine/topologies/tilt/manifest/json_to_yaml.py +54 -0
- package/engine/topologies/tilt/manifest/loader.star +214 -0
- package/engine/topologies/tilt/manifest/mapper.star +227 -0
- package/engine/topologies/tilt/manifest/parser.star +400 -0
- package/engine/topologies/tilt/manifest/schema.star +462 -0
- package/engine/topologies/tilt/manifest/tests/test_integration.star +276 -0
- package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +397 -0
- package/engine/topologies/tilt/manifest/tests/test_manifest.star +316 -0
- package/engine/topologies/tilt/manifest/tests/test_validator.star +470 -0
- package/engine/topologies/tilt/manifest/validator.star +717 -0
- package/engine/topologies/tilt/manifest/yaml_to_json.py +18 -0
- package/engine/topologies/tilt/resources/AGENTS.md +71 -0
- package/engine/topologies/tilt/resources/conditions.star +3 -0
- package/engine/topologies/tilt/resources/databases.star +244 -0
- package/engine/topologies/tilt/resources/declaration.star +3 -0
- package/engine/topologies/tilt/resources/deps.star +3 -0
- package/engine/topologies/tilt/resources/infra-loader.star +437 -0
- package/engine/topologies/tilt/resources/libs.star +30 -0
- package/engine/topologies/tilt/resources/libs_discovery.star +102 -0
- package/engine/topologies/tilt/resources/libs_paths.star +79 -0
- package/engine/topologies/tilt/resources/libs_resource_definition.star +151 -0
- package/engine/topologies/tilt/resources/libs_setup.star +164 -0
- package/engine/topologies/tilt/resources/libs_tsconfig.star +37 -0
- package/engine/topologies/tilt/resources/orchestrator/apply.star +77 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +431 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +81 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +148 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +36 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +44 -0
- package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +164 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +21 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +134 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/env.star +258 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +169 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +524 -0
- package/engine/topologies/tilt/resources/orchestrator/helpers.star +33 -0
- package/engine/topologies/tilt/resources/orchestrator.star +54 -0
- package/engine/topologies/tilt/resources/ordering.star +3 -0
- package/engine/topologies/tilt/resources/triggers.star +3 -0
- package/engine/topologies/tilt/resources/watchers.star +299 -0
- package/engine/where-things-live.star +717 -0
- package/ext/Tiltfile +66 -0
- package/ext/ide-components/README.md +219 -0
- package/ext/ide-components/code_executor/server.py +268 -0
- package/ext/ide-components/code_viewer/server.py +206 -0
- package/ext/ide-components/config_inspector/server.py +1050 -0
- package/ext/ide-components/file_browser/server.py +285 -0
- package/ext/ide-components/shared/config_service.py +469 -0
- package/ext/ide-components/shared/file_utils.py +298 -0
- package/ext/ide-components/shared/http_utils.py +232 -0
- package/ext/ide-components/shared/static/styles.css +1334 -0
- package/ext/ide-components/shared/syntax_highlighter.py +140 -0
- package/ext/ide-components/shared/template_engine.py +123 -0
- package/ext/ide-components/shared/templates/base.html +121 -0
- package/ext/ide-components/shared/test_config_service.py +326 -0
- package/ext/ide-components/shared/tilt_integration.py +158 -0
- package/ext/ui-enhancements/cron-status-server.sh +49 -0
- package/ext/ui-enhancements/cron-status-tracker.sh +146 -0
- package/ext/ui-enhancements/extension.yaml +36 -0
- package/ext/ui-enhancements/tiltfile.py +99 -0
- package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
- package/ext/ui-enhancements/ui/help-panel.css +279 -0
- package/ext/ui-enhancements/ui/icons.css +125 -0
- package/ext/ui-enhancements/ui/tooltips.css +114 -0
- package/package.json +13 -9
- package/specs/specs/TILT_SERVICE_DEFAULTS.star +205 -0
- package/specs/specs/TILT_TECH_STACK.star +159 -0
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# 🛡️ VALIDATORS - Pre-Flight Validation Generators
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# These generators run BEFORE services start to catch issues early
|
|
5
|
+
# They prevent vibe-coding failures by enforcing constraints at build time
|
|
6
|
+
# =============================================================================
|
|
7
|
+
|
|
8
|
+
# === INLINED CONSTANTS for pure extension loading ===
|
|
9
|
+
BASE_PORT_FRONTEND = 3000
|
|
10
|
+
# === END INLINED CONSTANTS ===
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
Validators Architecture:
|
|
15
|
+
1. docker_path_validator - Ensures path aliases work in Docker context
|
|
16
|
+
2. dependency_validator - Ensures all declared dependencies exist
|
|
17
|
+
3. db_readiness_validator - Validates database credentials before startup
|
|
18
|
+
4. package_publish_validator - Ensures shared packages are published
|
|
19
|
+
5. env_var_validator - Validates all required environment variables
|
|
20
|
+
6. resource_health_validator - Pre-flight health checks
|
|
21
|
+
7. shared_package_copier - Copies shared packages to Docker context
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
load("../common/utils.star", "Utils")
|
|
25
|
+
load("../../platform/docker/constants.star", "PlatformDockerConstants")
|
|
26
|
+
load("../manifest/constants.star", "GENERATED_CONFIG_FILENAMES")
|
|
27
|
+
|
|
28
|
+
load("../common/utils.star", "LIBRARY_ROOTS")
|
|
29
|
+
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# 1. Docker Path Alias Validator
|
|
32
|
+
# =============================================================================
|
|
33
|
+
|
|
34
|
+
def validate_docker_path_aliases(resource_path, manifest, library_roots):
|
|
35
|
+
"""
|
|
36
|
+
Validates that TypeScript path aliases in Docker tsconfig will resolve correctly.
|
|
37
|
+
|
|
38
|
+
Problem: Docker builds fail when tsconfig has path aliases to shared packages
|
|
39
|
+
that aren't copied to the Docker context.
|
|
40
|
+
|
|
41
|
+
Solution:
|
|
42
|
+
- Warn about path aliases that point outside Docker context
|
|
43
|
+
- Recommend removing internal_deps from Docker tsconfig
|
|
44
|
+
- Suggest using node_modules resolution instead
|
|
45
|
+
|
|
46
|
+
Returns: (is_valid, warnings, fixes)
|
|
47
|
+
"""
|
|
48
|
+
warnings = []
|
|
49
|
+
fixes = []
|
|
50
|
+
|
|
51
|
+
resource_name = manifest.get("appName", "unknown")
|
|
52
|
+
app_type = manifest.get("appType", "backend")
|
|
53
|
+
|
|
54
|
+
# Check if this is a frontend service (most affected)
|
|
55
|
+
if app_type == "frontend":
|
|
56
|
+
# Check for internal dependencies that would break Docker build
|
|
57
|
+
package_json_path = resource_path + "/package.json"
|
|
58
|
+
if os.path.exists(package_json_path):
|
|
59
|
+
package_json = read_json(package_json_path)
|
|
60
|
+
deps = package_json.get("dependencies", {})
|
|
61
|
+
|
|
62
|
+
internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
|
|
63
|
+
# Build list manually (Starlark doesn't support list comprehensions with if)
|
|
64
|
+
internal_deps = []
|
|
65
|
+
for name in deps.keys():
|
|
66
|
+
if name.startswith(internal_scope):
|
|
67
|
+
internal_deps.append(name)
|
|
68
|
+
|
|
69
|
+
if internal_deps:
|
|
70
|
+
warnings.append({
|
|
71
|
+
"level": "error",
|
|
72
|
+
"message": "Frontend '{}' has internal deps that will fail Docker build".format(resource_name),
|
|
73
|
+
"details": "The following packages use path aliases that won't resolve in Docker:",
|
|
74
|
+
"packages": internal_deps,
|
|
75
|
+
"impact": "Build will fail with 'Module not found' errors",
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
fixes.append({
|
|
79
|
+
"action": "Remove path aliases from Docker tsconfig",
|
|
80
|
+
"generator": "typescript/frontend_tsconfig.star",
|
|
81
|
+
"change": "Set internal_deps=None when is_docker=True",
|
|
82
|
+
"rationale": "Docker builds should resolve from node_modules, not source paths",
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
# Count errors manually (Starlark doesn't support list comprehensions with if)
|
|
86
|
+
error_count = 0
|
|
87
|
+
for w in warnings:
|
|
88
|
+
if w["level"] == "error":
|
|
89
|
+
error_count += 1
|
|
90
|
+
is_valid = error_count == 0
|
|
91
|
+
|
|
92
|
+
return struct(
|
|
93
|
+
is_valid=is_valid,
|
|
94
|
+
warnings=warnings,
|
|
95
|
+
fixes=fixes,
|
|
96
|
+
resource_name=resource_name,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def generate_docker_path_validation_report(resource_path, manifest, write_fn=None):
|
|
100
|
+
"""
|
|
101
|
+
Generates a validation report for Docker path aliases.
|
|
102
|
+
Called during config-gen to catch issues before Docker build.
|
|
103
|
+
"""
|
|
104
|
+
result = validate_docker_path_aliases(resource_path, manifest, LIBRARY_ROOTS)
|
|
105
|
+
|
|
106
|
+
if not result.is_valid:
|
|
107
|
+
report = {
|
|
108
|
+
"timestamp": "now",
|
|
109
|
+
"service": result.resource_name,
|
|
110
|
+
"status": "FAILED",
|
|
111
|
+
"warnings": result.warnings,
|
|
112
|
+
"fixes": result.fixes,
|
|
113
|
+
"recommendation": "Regenerate tsconfig without Docker path aliases",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if write_fn:
|
|
117
|
+
write_fn("docker-path-validation.json", Utils.encode_json(report))
|
|
118
|
+
|
|
119
|
+
# Also print to Tilt UI
|
|
120
|
+
print("⚠️ Docker Path Validation Failed for {}".format(result.resource_name))
|
|
121
|
+
for warning in result.warnings:
|
|
122
|
+
print(" ❌ {}: {}".format(warning["level"].upper(), warning["message"]))
|
|
123
|
+
for fix in result.fixes:
|
|
124
|
+
print(" 💡 Fix: {}".format(fix["action"]))
|
|
125
|
+
|
|
126
|
+
return report
|
|
127
|
+
|
|
128
|
+
return {"status": "PASSED", "service": result.resource_name}
|
|
129
|
+
|
|
130
|
+
# =============================================================================
|
|
131
|
+
# 2. Dependency Graph Validator
|
|
132
|
+
# =============================================================================
|
|
133
|
+
|
|
134
|
+
def validate_dependency_graph(resource_path, manifest, all_services):
|
|
135
|
+
"""
|
|
136
|
+
Validates that all declared dependencies actually exist.
|
|
137
|
+
|
|
138
|
+
Problem: Services declare dependencies on libraries that don't exist,
|
|
139
|
+
causing Tilt warnings and runtime failures.
|
|
140
|
+
|
|
141
|
+
Solution:
|
|
142
|
+
- Check all @{npm_scope}/* dependencies exist in library_roots
|
|
143
|
+
- Check dependsOn in manifest exist as services
|
|
144
|
+
- Generate missing dependency report
|
|
145
|
+
|
|
146
|
+
Returns: (is_valid, missing_deps, suggestions)
|
|
147
|
+
"""
|
|
148
|
+
missing_deps = []
|
|
149
|
+
warnings = []
|
|
150
|
+
|
|
151
|
+
resource_name = manifest.get("appName", "unknown")
|
|
152
|
+
|
|
153
|
+
# Check package.json dependencies
|
|
154
|
+
package_json_path = resource_path + "/package.json"
|
|
155
|
+
if os.path.exists(package_json_path):
|
|
156
|
+
package_json = read_json(package_json_path)
|
|
157
|
+
deps = package_json.get("dependencies", {})
|
|
158
|
+
dev_deps = package_json.get("devDependencies", {})
|
|
159
|
+
all_deps = dict(deps, **dev_deps)
|
|
160
|
+
|
|
161
|
+
internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
|
|
162
|
+
|
|
163
|
+
for dep_name in all_deps.keys():
|
|
164
|
+
if dep_name.startswith(internal_scope):
|
|
165
|
+
lib_name = dep_name.replace(internal_scope, "")
|
|
166
|
+
|
|
167
|
+
# Check if library exists in known library directories
|
|
168
|
+
found = False
|
|
169
|
+
for lib_type, lib_root in LIBRARY_ROOTS.items():
|
|
170
|
+
lib_path = "{}/{}".format(lib_root, lib_name)
|
|
171
|
+
if os.path.exists(lib_path):
|
|
172
|
+
found = True
|
|
173
|
+
break
|
|
174
|
+
|
|
175
|
+
if not found:
|
|
176
|
+
missing_deps.append({
|
|
177
|
+
"name": dep_name,
|
|
178
|
+
"type": "library",
|
|
179
|
+
"source": "package.json",
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
# Check manifest dependsOn
|
|
183
|
+
internal_deps = manifest.get("dependsOn", [])
|
|
184
|
+
for dep in internal_deps:
|
|
185
|
+
dep_exists = False
|
|
186
|
+
for svc in all_services:
|
|
187
|
+
# Check service name/stack match (supports legacy 'stack' field)
|
|
188
|
+
svc_stack = svc.get("stack") or svc.get("stack")
|
|
189
|
+
if svc.get("name") == dep or svc_stack == dep:
|
|
190
|
+
dep_exists = True
|
|
191
|
+
break
|
|
192
|
+
# Check if any resource within the service matches
|
|
193
|
+
for resource in svc.get("resources", []):
|
|
194
|
+
if resource.get("name") == dep:
|
|
195
|
+
dep_exists = True
|
|
196
|
+
break
|
|
197
|
+
if dep_exists:
|
|
198
|
+
break
|
|
199
|
+
|
|
200
|
+
if not dep_exists:
|
|
201
|
+
missing_deps.append({
|
|
202
|
+
"name": dep,
|
|
203
|
+
"type": "service",
|
|
204
|
+
"source": "service.json dependsOn",
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
is_valid = len(missing_deps) == 0
|
|
208
|
+
|
|
209
|
+
return struct(
|
|
210
|
+
is_valid=is_valid,
|
|
211
|
+
missing_deps=missing_deps,
|
|
212
|
+
resource_name=resource_name,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def generate_dependency_validation_report(resource_path, manifest, all_services, write_fn=None):
|
|
216
|
+
"""
|
|
217
|
+
Generates a validation report for service dependencies.
|
|
218
|
+
"""
|
|
219
|
+
result = validate_dependency_graph(resource_path, manifest, all_services)
|
|
220
|
+
|
|
221
|
+
if not result.is_valid:
|
|
222
|
+
report = {
|
|
223
|
+
"timestamp": "now",
|
|
224
|
+
"service": result.resource_name,
|
|
225
|
+
"status": "FAILED",
|
|
226
|
+
"missing_dependencies": result.missing_deps,
|
|
227
|
+
"recommendation": "Create missing libraries or update dependencies",
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if write_fn:
|
|
231
|
+
write_fn("dependency-validation.json", Utils.encode_json(report))
|
|
232
|
+
|
|
233
|
+
print("⚠️ Dependency Validation Failed for {}".format(result.resource_name))
|
|
234
|
+
for dep in result.missing_deps:
|
|
235
|
+
print(" ❌ Missing {}: {} (from {})".format(
|
|
236
|
+
dep["type"], dep["name"], dep["source"]
|
|
237
|
+
))
|
|
238
|
+
|
|
239
|
+
return report
|
|
240
|
+
|
|
241
|
+
return {"status": "PASSED", "service": result.resource_name}
|
|
242
|
+
|
|
243
|
+
# =============================================================================
|
|
244
|
+
# 3. Database Readiness Validator
|
|
245
|
+
# =============================================================================
|
|
246
|
+
|
|
247
|
+
def validate_database_readiness(resource_name, db_name, db_config):
|
|
248
|
+
"""
|
|
249
|
+
Validates database configuration before service startup.
|
|
250
|
+
|
|
251
|
+
Problem: Services fail to start because database credentials are wrong,
|
|
252
|
+
database doesn't exist, or connection fails.
|
|
253
|
+
|
|
254
|
+
Solution:
|
|
255
|
+
- Check DATABASE_URL is properly formed
|
|
256
|
+
- Validate database credentials format
|
|
257
|
+
- Ensure database name matches manifest
|
|
258
|
+
- Generate proper connection string
|
|
259
|
+
|
|
260
|
+
Returns: (is_valid, connection_string, errors)
|
|
261
|
+
"""
|
|
262
|
+
errors = []
|
|
263
|
+
|
|
264
|
+
# Validate database name
|
|
265
|
+
if not db_name:
|
|
266
|
+
errors.append({
|
|
267
|
+
"field": "databaseName",
|
|
268
|
+
"error": "No database name specified in manifest",
|
|
269
|
+
"fix": "Add 'databaseName' to service.json",
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
# Validate database config
|
|
273
|
+
if not db_config:
|
|
274
|
+
errors.append({
|
|
275
|
+
"field": "database",
|
|
276
|
+
"error": "No database configuration found",
|
|
277
|
+
"fix": "Check GLOBAL_CONFIG.database in discovery/config.star",
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
# Build connection string
|
|
281
|
+
connection_string = None
|
|
282
|
+
if db_name and db_config:
|
|
283
|
+
host = db_config.get("host", "localhost")
|
|
284
|
+
port = db_config.get("port", 5432)
|
|
285
|
+
user = db_config.get("user", "postgres")
|
|
286
|
+
# ⚠️ SECURITY: No default password - must be explicitly provided
|
|
287
|
+
password = db_config.get("password")
|
|
288
|
+
|
|
289
|
+
if not password:
|
|
290
|
+
errors.append({
|
|
291
|
+
"field": "database.password",
|
|
292
|
+
"error": "Database password is required but not provided",
|
|
293
|
+
"fix": "Set DB_PASSWORD or POSTGRES_PASSWORD environment variable",
|
|
294
|
+
})
|
|
295
|
+
else:
|
|
296
|
+
connection_string = "postgresql://{}:{}@{}:{}/{}".format(
|
|
297
|
+
user, password, host, port, db_name
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
is_valid = len(errors) == 0
|
|
301
|
+
|
|
302
|
+
return struct(
|
|
303
|
+
is_valid=is_valid,
|
|
304
|
+
connection_string=connection_string,
|
|
305
|
+
errors=errors,
|
|
306
|
+
resource_name=resource_name,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def generate_db_readiness_check(resource_name, db_name, db_config, write_fn=None):
|
|
310
|
+
"""
|
|
311
|
+
Generates database readiness validation and entrypoint script.
|
|
312
|
+
"""
|
|
313
|
+
result = validate_database_readiness(resource_name, db_name, db_config)
|
|
314
|
+
|
|
315
|
+
if not result.is_valid:
|
|
316
|
+
report = {
|
|
317
|
+
"timestamp": "now",
|
|
318
|
+
"service": resource_name,
|
|
319
|
+
"status": "FAILED",
|
|
320
|
+
"errors": result.errors,
|
|
321
|
+
"recommendation": "Fix database configuration in manifest",
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if write_fn:
|
|
325
|
+
write_fn("db-readiness-validation.json", Utils.encode_json(report))
|
|
326
|
+
|
|
327
|
+
print("⚠️ Database Validation Failed for {}".format(resource_name))
|
|
328
|
+
for error in result.errors:
|
|
329
|
+
print(" ❌ {}: {}".format(error["field"], error["error"]))
|
|
330
|
+
|
|
331
|
+
return report
|
|
332
|
+
|
|
333
|
+
# Generate connection string report
|
|
334
|
+
if write_fn:
|
|
335
|
+
write_fn("db-connection-string.txt", result.connection_string)
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
"status": "PASSED",
|
|
339
|
+
"service": resource_name,
|
|
340
|
+
"connection_string": result.connection_string,
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
# =============================================================================
|
|
344
|
+
# 4. Package Publish Validator
|
|
345
|
+
# =============================================================================
|
|
346
|
+
|
|
347
|
+
def validate_package_publishing(resource_path, manifest, verdaccio_url):
|
|
348
|
+
"""
|
|
349
|
+
Validates that all @{npm_scope} dependencies are published to Verdaccio.
|
|
350
|
+
|
|
351
|
+
Problem: Docker builds fail because shared packages aren't published,
|
|
352
|
+
causing 'npm package not found' errors.
|
|
353
|
+
|
|
354
|
+
Solution:
|
|
355
|
+
- Check each @{npm_scope} dependency exists in Verdaccio
|
|
356
|
+
- Compare local package version with published version
|
|
357
|
+
- Warn if local is newer than published
|
|
358
|
+
|
|
359
|
+
Returns: (is_valid, unpublished_packages, version_mismatches)
|
|
360
|
+
"""
|
|
361
|
+
unpublished = []
|
|
362
|
+
version_mismatches = []
|
|
363
|
+
|
|
364
|
+
resource_name = manifest.get("appName", "unknown")
|
|
365
|
+
|
|
366
|
+
package_json_path = resource_path + "/package.json"
|
|
367
|
+
if not os.path.exists(package_json_path):
|
|
368
|
+
return struct(
|
|
369
|
+
is_valid=True,
|
|
370
|
+
unpublished_packages=[],
|
|
371
|
+
version_mismatches=[],
|
|
372
|
+
resource_name=resource_name,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
package_json = read_json(package_json_path)
|
|
376
|
+
deps = package_json.get("dependencies", {})
|
|
377
|
+
|
|
378
|
+
internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
|
|
379
|
+
|
|
380
|
+
for dep_name, dep_version in deps.items():
|
|
381
|
+
if not dep_name.startswith(internal_scope):
|
|
382
|
+
continue
|
|
383
|
+
|
|
384
|
+
lib_name = dep_name.replace(internal_scope, "")
|
|
385
|
+
|
|
386
|
+
# Check if package exists in Verdaccio
|
|
387
|
+
# (This would be an actual HTTP check in real implementation)
|
|
388
|
+
# For now, we check if library source exists
|
|
389
|
+
found = False
|
|
390
|
+
for lib_root in LIBRARY_ROOTS.values():
|
|
391
|
+
lib_path = "{}/{}".format(lib_root, lib_name)
|
|
392
|
+
if os.path.exists(lib_path):
|
|
393
|
+
found = True
|
|
394
|
+
|
|
395
|
+
# Check local package.json version
|
|
396
|
+
lib_package_path = "{}/package.json".format(lib_path)
|
|
397
|
+
if os.path.exists(lib_package_path):
|
|
398
|
+
lib_package = read_json(lib_package_path)
|
|
399
|
+
local_version = lib_package.get("version", "0.0.0")
|
|
400
|
+
|
|
401
|
+
# Parse requested version
|
|
402
|
+
requested_version = dep_version.replace("^", "").replace("~", "")
|
|
403
|
+
|
|
404
|
+
if local_version != requested_version:
|
|
405
|
+
version_mismatches.append({
|
|
406
|
+
"package": dep_name,
|
|
407
|
+
"requested": requested_version,
|
|
408
|
+
"local": local_version,
|
|
409
|
+
})
|
|
410
|
+
break
|
|
411
|
+
|
|
412
|
+
if not found:
|
|
413
|
+
unpublished.append(dep_name)
|
|
414
|
+
|
|
415
|
+
is_valid = len(unpublished) == 0
|
|
416
|
+
|
|
417
|
+
return struct(
|
|
418
|
+
is_valid=is_valid,
|
|
419
|
+
unpublished_packages=unpublished,
|
|
420
|
+
version_mismatches=version_mismatches,
|
|
421
|
+
resource_name=resource_name,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
def generate_package_publish_report(resource_path, manifest, verdaccio_url, write_fn=None):
|
|
425
|
+
"""
|
|
426
|
+
Generates a report of package publishing status.
|
|
427
|
+
"""
|
|
428
|
+
result = validate_package_publishing(resource_path, manifest, verdaccio_url)
|
|
429
|
+
|
|
430
|
+
if not result.is_valid or result.version_mismatches:
|
|
431
|
+
report = {
|
|
432
|
+
"timestamp": "now",
|
|
433
|
+
"service": result.resource_name,
|
|
434
|
+
"status": "WARNING" if not result.is_valid else "VERSION_MISMATCH",
|
|
435
|
+
"unpublished_packages": result.unpublished_packages,
|
|
436
|
+
"version_mismatches": result.version_mismatches,
|
|
437
|
+
"recommendation": "Run 'bun run publish:all' to publish packages",
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if write_fn:
|
|
441
|
+
write_fn("package-publish-validation.json", Utils.encode_json(report))
|
|
442
|
+
|
|
443
|
+
if not result.is_valid:
|
|
444
|
+
print("⚠️ Package Publishing Validation Failed for {}".format(result.resource_name))
|
|
445
|
+
for pkg in result.unpublished_packages:
|
|
446
|
+
print(" ❌ Package not found: {}".format(pkg))
|
|
447
|
+
|
|
448
|
+
if result.version_mismatches:
|
|
449
|
+
print("⚠️ Version Mismatches for {}".format(result.resource_name))
|
|
450
|
+
for mismatch in result.version_mismatches:
|
|
451
|
+
print(" ⚡ {}: requested {} but local is {}".format(
|
|
452
|
+
mismatch["package"],
|
|
453
|
+
mismatch["requested"],
|
|
454
|
+
mismatch["local"]
|
|
455
|
+
))
|
|
456
|
+
|
|
457
|
+
return report
|
|
458
|
+
|
|
459
|
+
return {"status": "PASSED", "service": result.resource_name}
|
|
460
|
+
|
|
461
|
+
# =============================================================================
|
|
462
|
+
# 5. Environment Variable Validator
|
|
463
|
+
# =============================================================================
|
|
464
|
+
|
|
465
|
+
def validate_environment_variables(resource_path, manifest, required_vars):
|
|
466
|
+
"""
|
|
467
|
+
Validates that all required environment variables are defined.
|
|
468
|
+
|
|
469
|
+
Problem: Services fail at runtime because environment variables are missing.
|
|
470
|
+
|
|
471
|
+
Solution:
|
|
472
|
+
- Define required vars in manifest
|
|
473
|
+
- Check .env files exist
|
|
474
|
+
- Validate variables are set in Tilt context
|
|
475
|
+
|
|
476
|
+
Returns: (is_valid, missing_vars, env_files)
|
|
477
|
+
"""
|
|
478
|
+
missing_vars = []
|
|
479
|
+
env_files = []
|
|
480
|
+
|
|
481
|
+
resource_name = manifest.get("appName", "unknown")
|
|
482
|
+
|
|
483
|
+
# Check for .env files
|
|
484
|
+
for env_file in [".env", ".env.local", ".env.docker"]:
|
|
485
|
+
env_path = "{}/{}".format(resource_path, env_file)
|
|
486
|
+
if os.path.exists(env_path):
|
|
487
|
+
env_files.append(env_file)
|
|
488
|
+
|
|
489
|
+
# Check required variables
|
|
490
|
+
manifest_required = manifest.get("requiredEnvVars", [])
|
|
491
|
+
all_required = list(set(required_vars + manifest_required))
|
|
492
|
+
|
|
493
|
+
for var in all_required:
|
|
494
|
+
if not os.environ.get(var):
|
|
495
|
+
missing_vars.append(var)
|
|
496
|
+
|
|
497
|
+
is_valid = len(missing_vars) == 0
|
|
498
|
+
|
|
499
|
+
return struct(
|
|
500
|
+
is_valid=is_valid,
|
|
501
|
+
missing_vars=missing_vars,
|
|
502
|
+
env_files=env_files,
|
|
503
|
+
resource_name=resource_name,
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
def generate_env_validation_report(resource_path, manifest, required_vars, write_fn=None):
|
|
507
|
+
"""
|
|
508
|
+
Generates environment variable validation report.
|
|
509
|
+
"""
|
|
510
|
+
result = validate_environment_variables(resource_path, manifest, required_vars)
|
|
511
|
+
|
|
512
|
+
if not result.is_valid:
|
|
513
|
+
report = {
|
|
514
|
+
"timestamp": "now",
|
|
515
|
+
"service": result.resource_name,
|
|
516
|
+
"status": "FAILED",
|
|
517
|
+
"missing_variables": result.missing_vars,
|
|
518
|
+
"env_files_found": result.env_files,
|
|
519
|
+
"recommendation": "Set missing environment variables or add .env file",
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if write_fn:
|
|
523
|
+
write_fn("env-validation.json", Utils.encode_json(report))
|
|
524
|
+
|
|
525
|
+
print("⚠️ Environment Variable Validation Failed for {}".format(result.resource_name))
|
|
526
|
+
for var in result.missing_vars:
|
|
527
|
+
print(" ❌ Missing: {}".format(var))
|
|
528
|
+
|
|
529
|
+
return report
|
|
530
|
+
|
|
531
|
+
return {
|
|
532
|
+
"status": "PASSED",
|
|
533
|
+
"service": result.resource_name,
|
|
534
|
+
"env_files": result.env_files,
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
# =============================================================================
|
|
538
|
+
# 6. Service Health Pre-Flight Validator
|
|
539
|
+
# =============================================================================
|
|
540
|
+
|
|
541
|
+
def generate_resource_health_check(resource_name, resource_path, manifest, checks):
|
|
542
|
+
"""
|
|
543
|
+
Generates a comprehensive pre-flight health check script.
|
|
544
|
+
|
|
545
|
+
Runs before service starts to validate:
|
|
546
|
+
- File structure is correct
|
|
547
|
+
- Required files exist
|
|
548
|
+
- Dependencies are resolvable
|
|
549
|
+
- Ports are available
|
|
550
|
+
|
|
551
|
+
Returns: health_check_script (bash)
|
|
552
|
+
"""
|
|
553
|
+
app_type = manifest.get("appType", "backend")
|
|
554
|
+
|
|
555
|
+
health_checks = []
|
|
556
|
+
|
|
557
|
+
# Check 1: Required files exist
|
|
558
|
+
required_files = {
|
|
559
|
+
"backend": ["package.json", "prisma/schema.prisma"],
|
|
560
|
+
"frontend": ["package.json", "index.html", "src/main.tsx"],
|
|
561
|
+
"library": ["package.json"],
|
|
562
|
+
}.get(app_type, ["package.json"])
|
|
563
|
+
|
|
564
|
+
for req_file in required_files:
|
|
565
|
+
health_checks.append('''
|
|
566
|
+
if [ ! -f "{}" ]; then
|
|
567
|
+
echo "❌ Missing required file: {}"
|
|
568
|
+
exit 1
|
|
569
|
+
fi
|
|
570
|
+
'''.format(req_file, req_file))
|
|
571
|
+
|
|
572
|
+
# Check 2: Package.json is valid JSON
|
|
573
|
+
health_checks.append('''
|
|
574
|
+
if ! cat package.json | head -1 > /dev/null 2>&1; then
|
|
575
|
+
echo "❌ package.json is not valid"
|
|
576
|
+
exit 1
|
|
577
|
+
fi
|
|
578
|
+
''')
|
|
579
|
+
|
|
580
|
+
# Check 3: Port availability (for local dev)
|
|
581
|
+
port = manifest.get("port", BASE_PORT_FRONTEND)
|
|
582
|
+
health_checks.append('''
|
|
583
|
+
# Check if port is already in use
|
|
584
|
+
if command -v lsof > /dev/null 2>&1; then
|
|
585
|
+
if lsof -Pi :{} -sTCP:LISTEN -t >/dev/null 2>&1; then
|
|
586
|
+
echo "⚠️ Port {} is already in use"
|
|
587
|
+
fi
|
|
588
|
+
fi
|
|
589
|
+
'''.format(port, port))
|
|
590
|
+
|
|
591
|
+
# Combine into script
|
|
592
|
+
script = '''#!/bin/bash
|
|
593
|
+
# Auto-generated health check for {}
|
|
594
|
+
# Generated: {}
|
|
595
|
+
|
|
596
|
+
echo "🔍 Running pre-flight health checks for {}..."
|
|
597
|
+
|
|
598
|
+
{}
|
|
599
|
+
|
|
600
|
+
echo "✅ All health checks passed for {}"
|
|
601
|
+
'''.format(
|
|
602
|
+
resource_name,
|
|
603
|
+
"now",
|
|
604
|
+
resource_name,
|
|
605
|
+
"\n".join(health_checks),
|
|
606
|
+
resource_name
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
return script
|
|
610
|
+
|
|
611
|
+
def generate_health_check_resource(resource_path, resource_name, manifest, write_fn=None):
|
|
612
|
+
"""
|
|
613
|
+
Generates health check files and optionally writes them.
|
|
614
|
+
"""
|
|
615
|
+
checks = {} # Could be expanded with more check types
|
|
616
|
+
|
|
617
|
+
script = generate_resource_health_check(resource_name, resource_path, manifest, checks)
|
|
618
|
+
|
|
619
|
+
if write_fn:
|
|
620
|
+
write_fn("health-check.sh", script)
|
|
621
|
+
|
|
622
|
+
return script
|
|
623
|
+
|
|
624
|
+
# =============================================================================
|
|
625
|
+
# 7. Shared Package Copier (for Docker Context)
|
|
626
|
+
# =============================================================================
|
|
627
|
+
|
|
628
|
+
def generate_shared_package_copy_list(resource_path, manifest):
|
|
629
|
+
"""
|
|
630
|
+
Generates a list of shared packages that need to be copied to Docker context.
|
|
631
|
+
|
|
632
|
+
Problem: Frontend builds fail because shared packages are referenced via
|
|
633
|
+
path aliases but not available in Docker build context.
|
|
634
|
+
|
|
635
|
+
Solution: Copy required shared packages to service directory before Docker build.
|
|
636
|
+
|
|
637
|
+
Returns: list of {source, destination, package_name} dicts
|
|
638
|
+
"""
|
|
639
|
+
packages_to_copy = []
|
|
640
|
+
|
|
641
|
+
resource_name = manifest.get("appName", "unknown")
|
|
642
|
+
|
|
643
|
+
package_json_path = resource_path + "/package.json"
|
|
644
|
+
if not os.path.exists(package_json_path):
|
|
645
|
+
return packages_to_copy
|
|
646
|
+
|
|
647
|
+
package_json = read_json(package_json_path)
|
|
648
|
+
deps = package_json.get("dependencies", {})
|
|
649
|
+
|
|
650
|
+
internal_scope = "@" + PlatformDockerConstants.PROJECT_NAME + "/"
|
|
651
|
+
|
|
652
|
+
for dep_name in deps.keys():
|
|
653
|
+
if not dep_name.startswith(internal_scope):
|
|
654
|
+
continue
|
|
655
|
+
|
|
656
|
+
lib_name = dep_name.replace(internal_scope, "")
|
|
657
|
+
|
|
658
|
+
# Find library source path
|
|
659
|
+
for lib_root in LIBRARY_ROOTS.values():
|
|
660
|
+
lib_path = "{}/{}".format(lib_root, lib_name)
|
|
661
|
+
if os.path.exists(lib_path):
|
|
662
|
+
# Destination: .docker-shared-packages/{lib_name}
|
|
663
|
+
dest = ".docker-shared-packages/{}".format(lib_name)
|
|
664
|
+
|
|
665
|
+
packages_to_copy.append({
|
|
666
|
+
"source": lib_path,
|
|
667
|
+
"destination": dest,
|
|
668
|
+
"package_name": dep_name,
|
|
669
|
+
"lib_name": lib_name,
|
|
670
|
+
})
|
|
671
|
+
break
|
|
672
|
+
|
|
673
|
+
return packages_to_copy
|
|
674
|
+
|
|
675
|
+
def generate_docker_shared_packages_config(resource_path, manifest, write_fn=None):
|
|
676
|
+
"""
|
|
677
|
+
Generates configuration for copying shared packages to Docker context.
|
|
678
|
+
|
|
679
|
+
This creates a JSON file that can be used by a local_resource to copy
|
|
680
|
+
packages before Docker build.
|
|
681
|
+
"""
|
|
682
|
+
packages = generate_shared_package_copy_list(resource_path, manifest)
|
|
683
|
+
|
|
684
|
+
config = {
|
|
685
|
+
"timestamp": "now",
|
|
686
|
+
"service": manifest.get("appName", "unknown"),
|
|
687
|
+
"packages": packages,
|
|
688
|
+
"copy_script": "#!/bin/bash\n# Copy shared packages to Docker context\n" + "\n".join([
|
|
689
|
+
"mkdir -p {dest} && cp -r {src}/* {dest}/".format(
|
|
690
|
+
src=p["source"],
|
|
691
|
+
dest=p["destination"]
|
|
692
|
+
)
|
|
693
|
+
for p in packages
|
|
694
|
+
]) if packages else "# No shared packages to copy",
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
if write_fn:
|
|
698
|
+
write_fn("docker-shared-packages.json", Utils.encode_json(config))
|
|
699
|
+
|
|
700
|
+
return config
|
|
701
|
+
|
|
702
|
+
# =============================================================================
|
|
703
|
+
# Master Validation Orchestrator
|
|
704
|
+
# =============================================================================
|
|
705
|
+
|
|
706
|
+
def run_all_validations(resource_path, manifest, all_services, global_config, write_fn=None):
|
|
707
|
+
"""
|
|
708
|
+
Runs all validators and generates a comprehensive report.
|
|
709
|
+
|
|
710
|
+
This is the main entry point called during config-gen.
|
|
711
|
+
"""
|
|
712
|
+
reports = {}
|
|
713
|
+
all_valid = True
|
|
714
|
+
|
|
715
|
+
# 1. Docker Path Validation
|
|
716
|
+
reports["docker_paths"] = generate_docker_path_validation_report(
|
|
717
|
+
resource_path, manifest, write_fn
|
|
718
|
+
)
|
|
719
|
+
if reports["docker_paths"].get("status") == "FAILED":
|
|
720
|
+
all_valid = False
|
|
721
|
+
|
|
722
|
+
# 2. Dependency Validation
|
|
723
|
+
reports["dependencies"] = generate_dependency_validation_report(
|
|
724
|
+
resource_path, manifest, all_services, write_fn
|
|
725
|
+
)
|
|
726
|
+
if reports["dependencies"].get("status") == "FAILED":
|
|
727
|
+
all_valid = False
|
|
728
|
+
|
|
729
|
+
# 3. Database Validation
|
|
730
|
+
db_config = global_config.get("database", {})
|
|
731
|
+
db_name = manifest.get("databaseName", "")
|
|
732
|
+
reports["database"] = generate_db_readiness_check(
|
|
733
|
+
manifest.get("appName"), db_name, db_config, write_fn
|
|
734
|
+
)
|
|
735
|
+
if reports["database"].get("status") == "FAILED":
|
|
736
|
+
all_valid = False
|
|
737
|
+
|
|
738
|
+
# 4. Package Publishing Validation
|
|
739
|
+
verdaccio_url = global_config.get("verdaccio_url_local", PlatformDockerConstants.VERDACCIO_URL_LOCAL)
|
|
740
|
+
reports["packages"] = generate_package_publish_report(
|
|
741
|
+
resource_path, manifest, verdaccio_url, write_fn
|
|
742
|
+
)
|
|
743
|
+
# Warnings don't fail validation
|
|
744
|
+
|
|
745
|
+
# 5. Environment Variable Validation
|
|
746
|
+
required_vars = ["VERDACCIO_URL_DOCKER", "TILT_ENV"]
|
|
747
|
+
reports["environment"] = generate_env_validation_report(
|
|
748
|
+
resource_path, manifest, required_vars, write_fn
|
|
749
|
+
)
|
|
750
|
+
if reports["environment"].get("status") == "FAILED":
|
|
751
|
+
all_valid = False
|
|
752
|
+
|
|
753
|
+
# 6. Health Check Script
|
|
754
|
+
reports["health_check"] = generate_health_check_resource(
|
|
755
|
+
resource_path, manifest.get("appName"), manifest, write_fn
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
# 7. Shared Package Copy Config
|
|
759
|
+
reports["shared_packages"] = generate_docker_shared_packages_config(
|
|
760
|
+
resource_path, manifest, write_fn
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
# Master Report
|
|
764
|
+
# Count passed, failed, and warnings using regular loops (Starlark doesn't support generator expressions)
|
|
765
|
+
passed_count = 0
|
|
766
|
+
failed_count = 0
|
|
767
|
+
warnings_count = 0
|
|
768
|
+
for r in reports.values():
|
|
769
|
+
if type(r) == "dict":
|
|
770
|
+
status = r.get("status")
|
|
771
|
+
if status == "PASSED":
|
|
772
|
+
passed_count += 1
|
|
773
|
+
elif status == "FAILED":
|
|
774
|
+
failed_count += 1
|
|
775
|
+
elif status == "WARNING":
|
|
776
|
+
warnings_count += 1
|
|
777
|
+
|
|
778
|
+
master_report = {
|
|
779
|
+
"service": manifest.get("appName", "unknown"),
|
|
780
|
+
"overall_status": "PASSED" if all_valid else "FAILED",
|
|
781
|
+
"reports": reports,
|
|
782
|
+
"summary": {
|
|
783
|
+
"validations_run": 7,
|
|
784
|
+
"passed": passed_count,
|
|
785
|
+
"failed": failed_count,
|
|
786
|
+
"warnings": warnings_count,
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if write_fn:
|
|
791
|
+
write_fn("validation-master-report.json", Utils.encode_json(master_report))
|
|
792
|
+
|
|
793
|
+
# Print compact validation summary
|
|
794
|
+
resource_name = manifest.get("appName", "unknown")
|
|
795
|
+
|
|
796
|
+
# Build compact validation summary - only show failures prominently
|
|
797
|
+
failed_validations = []
|
|
798
|
+
passed_count = 0
|
|
799
|
+
unknown_count = 0
|
|
800
|
+
|
|
801
|
+
for name, report in reports.items():
|
|
802
|
+
if type(report) == "dict":
|
|
803
|
+
status = report.get("status", "UNKNOWN")
|
|
804
|
+
if status == "FAILED":
|
|
805
|
+
failed_validations.append(name)
|
|
806
|
+
elif status == "PASSED":
|
|
807
|
+
passed_count += 1
|
|
808
|
+
elif status == "UNKNOWN":
|
|
809
|
+
unknown_count += 1
|
|
810
|
+
|
|
811
|
+
# Print compact summary
|
|
812
|
+
if all_valid:
|
|
813
|
+
# All passed - just show summary line
|
|
814
|
+
print("✅ {}: {} validations passed".format(resource_name, passed_count))
|
|
815
|
+
else:
|
|
816
|
+
# Some failed - show service and failures
|
|
817
|
+
print("❌ {}: {} validation(s) failed".format(resource_name, len(failed_validations)))
|
|
818
|
+
for failed in failed_validations:
|
|
819
|
+
print(" ❌ {}".format(failed))
|
|
820
|
+
|
|
821
|
+
# Show warnings/unknown only in verbose mode
|
|
822
|
+
is_verbose = os.environ.get('TILT_LOG_LEVEL') == 'verbose'
|
|
823
|
+
if is_verbose and unknown_count > 0:
|
|
824
|
+
print(" ○ {} not checked".format(unknown_count))
|
|
825
|
+
|
|
826
|
+
return master_report
|
|
827
|
+
|
|
828
|
+
# =============================================================================
|
|
829
|
+
# Exports
|
|
830
|
+
# =============================================================================
|
|
831
|
+
|
|
832
|
+
Validators = struct(
|
|
833
|
+
# Individual validators
|
|
834
|
+
validate_docker_path_aliases=validate_docker_path_aliases,
|
|
835
|
+
validate_dependency_graph=validate_dependency_graph,
|
|
836
|
+
validate_database_readiness=validate_database_readiness,
|
|
837
|
+
validate_package_publishing=validate_package_publishing,
|
|
838
|
+
validate_environment_variables=validate_environment_variables,
|
|
839
|
+
|
|
840
|
+
# Report generators
|
|
841
|
+
generate_docker_path_validation_report=generate_docker_path_validation_report,
|
|
842
|
+
generate_dependency_validation_report=generate_dependency_validation_report,
|
|
843
|
+
generate_db_readiness_check=generate_db_readiness_check,
|
|
844
|
+
generate_package_publish_report=generate_package_publish_report,
|
|
845
|
+
generate_env_validation_report=generate_env_validation_report,
|
|
846
|
+
generate_health_check_resource=generate_health_check_resource,
|
|
847
|
+
generate_docker_shared_packages_config=generate_docker_shared_packages_config,
|
|
848
|
+
|
|
849
|
+
# Master orchestrator
|
|
850
|
+
run_all_validations=run_all_validations,
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
GLOBAL_CONFIG = {}
|