@tdk-landscape/tdk-cli-core 1.3.14 → 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/README.md +3 -3
- 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 +62 -21
- 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/paths.js +1 -1
- package/dist/utils/paths.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,974 @@
|
|
|
1
|
+
# 📋 Manifest System Refactoring Plan
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
This document outlines a comprehensive refactoring of the manifest parsing and validation system in the TDK Landscape Tilt infrastructure. The goal is to move from scattered inline logic to a clean, modular, well-tested architecture.
|
|
6
|
+
|
|
7
|
+
**Current State:**
|
|
8
|
+
- Manifest parsing scattered across `discovery.star`, `registry.star`, and multiple generator files
|
|
9
|
+
- Validation logic inline and duplicated
|
|
10
|
+
- No clear separation between loading, parsing, and validation
|
|
11
|
+
- Schema definitions mixed with business logic
|
|
12
|
+
|
|
13
|
+
**Target State:**
|
|
14
|
+
- Dedicated `manifest/` module with clear separation of concerns
|
|
15
|
+
- Parser, validator, loader, schema, and fetch as separate modules
|
|
16
|
+
- Comprehensive attribute and value verification
|
|
17
|
+
- Backward compatibility maintained during migration
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## New Architecture
|
|
22
|
+
|
|
23
|
+
### Folder Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
.tilt/topologies/tilt/
|
|
27
|
+
├── manifest/ # NEW: Manifest system module
|
|
28
|
+
│ ├── __init__.star # Module exports and facade
|
|
29
|
+
│ ├── loader.star # File loading and I/O
|
|
30
|
+
│ ├── parser.star # JSON parsing and normalization
|
|
31
|
+
│ ├── validator.star # Schema and value validation
|
|
32
|
+
│ ├── schema.star # Schema definitions and constraints
|
|
33
|
+
│ ├── fetch.star # Remote manifest fetching (future)
|
|
34
|
+
│ ├── constants.star # Manifest-specific constants
|
|
35
|
+
│ ├── errors.star # Error types and handling
|
|
36
|
+
│ └── tests/ # Unit tests for manifest system
|
|
37
|
+
│ ├── test_loader.star
|
|
38
|
+
│ ├── test_parser.star
|
|
39
|
+
│ ├── test_validator.star
|
|
40
|
+
│ └── test_schema.star
|
|
41
|
+
│
|
|
42
|
+
├── discovery/ # EXISTING: Service discovery
|
|
43
|
+
│ ├── manifest/ # DEPRECATED: Will be moved to ../manifest/
|
|
44
|
+
│ │ └── constants.star # Will migrate to ../manifest/constants.star
|
|
45
|
+
│ ├── discovery.star # Will use new manifest module
|
|
46
|
+
│ └── registry.star # Will use new manifest module
|
|
47
|
+
│
|
|
48
|
+
└── generators/ # EXISTING: Config generators
|
|
49
|
+
└── validators.star # Will use new manifest/validator.star
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Module Specifications
|
|
55
|
+
|
|
56
|
+
### 1. `manifest/__init__.star` - Module Facade
|
|
57
|
+
|
|
58
|
+
**Purpose:** Provide a clean API surface for other modules
|
|
59
|
+
|
|
60
|
+
**Exports:**
|
|
61
|
+
```starlark
|
|
62
|
+
# Main API
|
|
63
|
+
Manifest = struct(
|
|
64
|
+
# Loader functions
|
|
65
|
+
load_from_file = loader.load_from_file,
|
|
66
|
+
load_from_path = loader.load_from_path,
|
|
67
|
+
load_all = loader.load_all,
|
|
68
|
+
|
|
69
|
+
# Parser functions
|
|
70
|
+
parse = parser.parse,
|
|
71
|
+
normalize = parser.normalize,
|
|
72
|
+
extract_resource_path = parser.extract_resource_path,
|
|
73
|
+
|
|
74
|
+
# Validator functions
|
|
75
|
+
validate = validator.validate,
|
|
76
|
+
validate_schema = validator.validate_schema,
|
|
77
|
+
validate_values = validator.validate_values,
|
|
78
|
+
validate_dependencies = validator.validate_dependencies,
|
|
79
|
+
|
|
80
|
+
# Schema access
|
|
81
|
+
schema = schema.MANIFEST_SCHEMA,
|
|
82
|
+
defaults = constants.MANIFEST_DEFAULTS,
|
|
83
|
+
constraints = schema.CONSTRAINTS,
|
|
84
|
+
|
|
85
|
+
# Error handling
|
|
86
|
+
errors = errors.MANIFEST_ERRORS,
|
|
87
|
+
is_valid = validator.is_valid,
|
|
88
|
+
get_validation_report = validator.get_validation_report,
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Usage Example:**
|
|
93
|
+
```starlark
|
|
94
|
+
load("../manifest/__init__.star", "Manifest")
|
|
95
|
+
|
|
96
|
+
# Load and validate in one call
|
|
97
|
+
result = Manifest.load_from_file("services/product/user/user-management-backend/service.json")
|
|
98
|
+
if result.error:
|
|
99
|
+
print("Failed to load manifest:", result.error)
|
|
100
|
+
else:
|
|
101
|
+
manifest = result.manifest
|
|
102
|
+
# Use validated manifest
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 2. `manifest/loader.star` - File Loading and I/O
|
|
108
|
+
|
|
109
|
+
**Purpose:** Handle all file system operations for manifest loading
|
|
110
|
+
|
|
111
|
+
**Functions:**
|
|
112
|
+
|
|
113
|
+
```starlark
|
|
114
|
+
def load_from_file(path):
|
|
115
|
+
"""
|
|
116
|
+
Load a single manifest from file path.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
path: Absolute or relative path to manifest JSON file
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
struct(manifest=None, error=None, metadata={})
|
|
123
|
+
- manifest: Parsed manifest dict or None if error
|
|
124
|
+
- error: Error message string or None
|
|
125
|
+
- metadata: Dict with load info (timestamp, file_size, path)
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
def load_from_path(resource_path):
|
|
129
|
+
"""
|
|
130
|
+
Load manifest from resource directory (auto-detects manifest file).
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
resource_path: Path to resource directory
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Same as load_from_file
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def load_all(resources_root, filters=None):
|
|
140
|
+
"""
|
|
141
|
+
Load all manifests from resources directory with optional filtering.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
resources_root: Root directory to search (e.g., "services/product")
|
|
145
|
+
filters: Optional dict of filters:
|
|
146
|
+
- appType: ['frontend', 'backend', 'library', ...]
|
|
147
|
+
- stack: ['user', 'order', ...]
|
|
148
|
+
- features: ['nats', 'prisma', ...]
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
struct(
|
|
152
|
+
manifests=[], # List of loaded manifests
|
|
153
|
+
errors=[], # List of (path, error) tuples
|
|
154
|
+
stats={ # Loading statistics
|
|
155
|
+
'total_found': N,
|
|
156
|
+
'successful': N,
|
|
157
|
+
'failed': N,
|
|
158
|
+
'filtered_out': N,
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def watch_manifest(path):
|
|
164
|
+
"""
|
|
165
|
+
Set up file watch for manifest changes (Tilt integration).
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
path: Path to manifest file
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
watch_spec for Tilt
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
def get_manifest_path(resource_path):
|
|
175
|
+
"""
|
|
176
|
+
Get the expected manifest file path for a resource directory.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
resource_path: Resource directory path
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Expected manifest file path or None
|
|
183
|
+
"""
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Implementation Notes:**
|
|
187
|
+
- Uses `read_file()` with proper error handling
|
|
188
|
+
- Caches loaded manifests to avoid redundant I/O
|
|
189
|
+
- Provides detailed error messages with context
|
|
190
|
+
- Integrates with Tilt's file watching system
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### 3. `manifest/parser.star` - JSON Parsing and Normalization
|
|
195
|
+
|
|
196
|
+
**Purpose:** Transform raw JSON into normalized, validated manifest structures
|
|
197
|
+
|
|
198
|
+
**Functions:**
|
|
199
|
+
|
|
200
|
+
```starlark
|
|
201
|
+
def parse(content, path=""):
|
|
202
|
+
"""
|
|
203
|
+
Parse JSON content into manifest dict.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
content: Raw JSON string
|
|
207
|
+
path: Optional path for error context
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
struct(manifest=None, error=None, warnings=[])
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
def normalize(manifest, resource_path=""):
|
|
214
|
+
"""
|
|
215
|
+
Normalize manifest with default values and computed fields.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
manifest: Raw parsed manifest dict
|
|
219
|
+
resource_path: Resource directory path for context
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Normalized manifest dict with all fields populated
|
|
223
|
+
|
|
224
|
+
Normalization Steps:
|
|
225
|
+
1. Apply defaults for missing fields
|
|
226
|
+
2. Compute derived fields (appType from path if missing)
|
|
227
|
+
3. Validate field types and formats
|
|
228
|
+
4. Set up internal dependencies
|
|
229
|
+
5. Compute sync paths based on features
|
|
230
|
+
6. Normalize environment variables
|
|
231
|
+
7. Set up Traefik configuration defaults
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
def extract_resource_path(manifest_path):
|
|
235
|
+
"""
|
|
236
|
+
Extract resource directory path from manifest file path.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
manifest_path: Path to manifest JSON file
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Resource directory path
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
def extract_stack(resource_path):
|
|
246
|
+
"""
|
|
247
|
+
Extract stack from resource path.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
resource_path: Resource directory path
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Stack string (e.g., 'user', 'order')
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
def determine_app_type(manifest, resource_path):
|
|
257
|
+
"""
|
|
258
|
+
Determine app type from manifest or resource path.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
manifest: Manifest dict
|
|
262
|
+
resource_path: Resource directory path
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
App type string ('frontend', 'backend', 'library', etc.)
|
|
266
|
+
"""
|
|
267
|
+
|
|
268
|
+
def compute_syncs(app_type, features):
|
|
269
|
+
"""
|
|
270
|
+
Compute default sync paths based on app type and features.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
app_type: App type string
|
|
274
|
+
features: List of feature strings
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
List of sync paths
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
def parse_traefik_config(manifest):
|
|
281
|
+
"""
|
|
282
|
+
Parse and normalize Traefik configuration.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
manifest: Manifest dict
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
Normalized Traefik config dict
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
def merge_manifests(base, overlay):
|
|
292
|
+
"""
|
|
293
|
+
Merge two manifest dicts (for inheritance patterns).
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
base: Base manifest dict
|
|
297
|
+
overlay: Overlay manifest dict
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Merged manifest dict
|
|
301
|
+
"""
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Implementation Notes:**
|
|
305
|
+
- Pure functions with no side effects
|
|
306
|
+
- Comprehensive warning system for deprecated fields
|
|
307
|
+
- Supports manifest inheritance/overlays
|
|
308
|
+
- Detailed error context with path information
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### 4. `manifest/schema.star` - Schema Definitions and Constraints
|
|
313
|
+
|
|
314
|
+
**Purpose:** Define the complete manifest schema with types, constraints, and documentation
|
|
315
|
+
|
|
316
|
+
**Schema Definition:**
|
|
317
|
+
|
|
318
|
+
```starlark
|
|
319
|
+
# Complete manifest field schema
|
|
320
|
+
MANIFEST_SCHEMA = {
|
|
321
|
+
'appName': {
|
|
322
|
+
'type': 'string',
|
|
323
|
+
'required': True,
|
|
324
|
+
'pattern': r'^[a-z][a-z0-9-]*$',
|
|
325
|
+
'min_length': 3,
|
|
326
|
+
'max_length': 50,
|
|
327
|
+
'description': 'Unique resource name (kebab-case)',
|
|
328
|
+
'example': 'user-management-backend',
|
|
329
|
+
},
|
|
330
|
+
'appType': {
|
|
331
|
+
'type': 'string',
|
|
332
|
+
'required': True,
|
|
333
|
+
'enum': ['frontend', 'backend', 'library', 'migrator', 'sdk', 'worker'],
|
|
334
|
+
'description': 'Type of application',
|
|
335
|
+
'default': 'backend',
|
|
336
|
+
},
|
|
337
|
+
'stack': {
|
|
338
|
+
'type': 'string',
|
|
339
|
+
'required': True,
|
|
340
|
+
'enum': ['user', 'staff', 'identity', 'order', 'treatment',
|
|
341
|
+
'platform', 'inventory', 'billing', 'notification', 'analytics'],
|
|
342
|
+
'description': 'Technology stack this resource belongs to',
|
|
343
|
+
},
|
|
344
|
+
'port': {
|
|
345
|
+
'type': 'integer',
|
|
346
|
+
'required': True,
|
|
347
|
+
'min': 1024,
|
|
348
|
+
'max': 65535,
|
|
349
|
+
'description': 'External resource port',
|
|
350
|
+
'constraints': 'Must be unique per resource',
|
|
351
|
+
},
|
|
352
|
+
'internalPort': {
|
|
353
|
+
'type': 'integer',
|
|
354
|
+
'required': False,
|
|
355
|
+
'default': 3000,
|
|
356
|
+
'description': 'Internal container port (usually 3000)',
|
|
357
|
+
'constant': True, # Should rarely change
|
|
358
|
+
},
|
|
359
|
+
'replicas': {
|
|
360
|
+
'type': 'integer',
|
|
361
|
+
'required': False,
|
|
362
|
+
'default': 1,
|
|
363
|
+
'min': 1,
|
|
364
|
+
'max': 5, # Reasonable limit
|
|
365
|
+
'description': 'Number of container replicas',
|
|
366
|
+
},
|
|
367
|
+
'runtime': {
|
|
368
|
+
'type': 'string',
|
|
369
|
+
'required': False,
|
|
370
|
+
'default': 'bun',
|
|
371
|
+
'enum': ['bun', 'node', 'python', 'go'],
|
|
372
|
+
'description': 'Runtime environment',
|
|
373
|
+
},
|
|
374
|
+
'features': {
|
|
375
|
+
'type': 'list',
|
|
376
|
+
'required': False,
|
|
377
|
+
'default': [],
|
|
378
|
+
'items': {
|
|
379
|
+
'type': 'string',
|
|
380
|
+
'enum': ['nats', 'prisma', 'redis', 'infisical', 'vitest',
|
|
381
|
+
'traefik', 'websocket', 'graphql', 'grpc', 'vite-node'],
|
|
382
|
+
},
|
|
383
|
+
'description': 'Feature flags for this resource',
|
|
384
|
+
},
|
|
385
|
+
'databaseName': {
|
|
386
|
+
'type': 'string',
|
|
387
|
+
'required': False,
|
|
388
|
+
'pattern': r'^[a-z][a-z0-9_]*$',
|
|
389
|
+
'description': 'PostgreSQL database name',
|
|
390
|
+
},
|
|
391
|
+
'dependsOn': {
|
|
392
|
+
'type': 'list',
|
|
393
|
+
'required': False,
|
|
394
|
+
'default': [],
|
|
395
|
+
'items': {'type': 'string'},
|
|
396
|
+
'description': 'Other resources this depends on',
|
|
397
|
+
},
|
|
398
|
+
'envVars': {
|
|
399
|
+
'type': 'dict',
|
|
400
|
+
'required': False,
|
|
401
|
+
'default': {},
|
|
402
|
+
'description': 'Environment variables',
|
|
403
|
+
},
|
|
404
|
+
'traefik': {
|
|
405
|
+
'type': 'dict',
|
|
406
|
+
'required': False,
|
|
407
|
+
'schema': {
|
|
408
|
+
'pathPrefix': {'type': 'string', 'required': True},
|
|
409
|
+
'host': {'type': 'string', 'required': False},
|
|
410
|
+
'priority': {'type': 'integer', 'required': False, 'min': 1, 'max': 1000},
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
# Frontend-specific fields
|
|
414
|
+
'backendName': {
|
|
415
|
+
'type': 'string',
|
|
416
|
+
'required': False,
|
|
417
|
+
'condition': "appType == 'frontend'", # Required for frontends
|
|
418
|
+
'description': 'Associated backend resource name',
|
|
419
|
+
},
|
|
420
|
+
'basePath': {
|
|
421
|
+
'type': 'string',
|
|
422
|
+
'required': False,
|
|
423
|
+
'condition': "appType == 'frontend'",
|
|
424
|
+
'pattern': r'^/[a-z][a-z0-9-]*$',
|
|
425
|
+
'description': 'URL base path for frontend',
|
|
426
|
+
},
|
|
427
|
+
# Advanced fields
|
|
428
|
+
'syncs': {
|
|
429
|
+
'type': 'list',
|
|
430
|
+
'required': False,
|
|
431
|
+
'description': 'Custom sync paths (auto-computed if not provided)',
|
|
432
|
+
},
|
|
433
|
+
'startCommand': {
|
|
434
|
+
'type': 'string',
|
|
435
|
+
'required': False,
|
|
436
|
+
'description': 'Custom container start command',
|
|
437
|
+
},
|
|
438
|
+
'targetPath': {
|
|
439
|
+
'type': 'string',
|
|
440
|
+
'required': False,
|
|
441
|
+
'description': 'Frontend build target path',
|
|
442
|
+
},
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
# Cross-field constraints
|
|
446
|
+
CONSTRAINTS = {
|
|
447
|
+
# Port uniqueness will be validated across all manifests
|
|
448
|
+
'port_unique': True,
|
|
449
|
+
|
|
450
|
+
# App type specific rules
|
|
451
|
+
'frontend_requires_backend': {
|
|
452
|
+
'condition': "appType == 'frontend'",
|
|
453
|
+
'requires': ['backendName', 'basePath'],
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
# Feature dependencies
|
|
457
|
+
'prisma_requires_database': {
|
|
458
|
+
'condition': "'prisma' in features",
|
|
459
|
+
'requires': ['databaseName'],
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
# Port ranges by app type
|
|
463
|
+
'port_ranges': {
|
|
464
|
+
'frontend': {'min': 3000, 'max': 3999},
|
|
465
|
+
'backend': {'min': 4000, 'max': 5999},
|
|
466
|
+
'worker': {'min': 6000, 'max': 6999},
|
|
467
|
+
},
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Functions:**
|
|
472
|
+
|
|
473
|
+
```starlark
|
|
474
|
+
def get_field_schema(field_name):
|
|
475
|
+
"""Get schema definition for a specific field."""
|
|
476
|
+
|
|
477
|
+
def validate_field_type(field_name, value):
|
|
478
|
+
"""Validate a single field's type against schema."""
|
|
479
|
+
|
|
480
|
+
def get_default_value(field_name):
|
|
481
|
+
"""Get default value for a field."""
|
|
482
|
+
|
|
483
|
+
def get_required_fields(manifest):
|
|
484
|
+
"""Get list of required fields based on manifest context."""
|
|
485
|
+
|
|
486
|
+
def get_field_constraints(field_name):
|
|
487
|
+
"""Get constraints for a specific field."""
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
### 5. `manifest/validator.star` - Comprehensive Validation
|
|
493
|
+
|
|
494
|
+
**Purpose:** Validate manifest structure, values, and cross-resource dependencies
|
|
495
|
+
|
|
496
|
+
**Validation Levels:**
|
|
497
|
+
|
|
498
|
+
```starlark
|
|
499
|
+
def validate(manifest, context=None, level='all'):
|
|
500
|
+
"""
|
|
501
|
+
Comprehensive manifest validation.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
manifest: Manifest dict to validate
|
|
505
|
+
context: Optional context dict:
|
|
506
|
+
- all_manifests: List of all manifests for cross-validation
|
|
507
|
+
- resource_path: Path for error context
|
|
508
|
+
- strict: Boolean for strict mode
|
|
509
|
+
level: Validation level
|
|
510
|
+
- 'schema': Structure and types only
|
|
511
|
+
- 'values': Value constraints
|
|
512
|
+
- 'dependencies': Cross-resource dependencies
|
|
513
|
+
- 'all': All validations (default)
|
|
514
|
+
|
|
515
|
+
Returns:
|
|
516
|
+
struct(
|
|
517
|
+
valid=True/False,
|
|
518
|
+
errors=[], # Critical errors
|
|
519
|
+
warnings=[], # Non-critical issues
|
|
520
|
+
stats={ # Validation statistics
|
|
521
|
+
'fields_checked': N,
|
|
522
|
+
'rules_passed': N,
|
|
523
|
+
'rules_failed': N,
|
|
524
|
+
}
|
|
525
|
+
)
|
|
526
|
+
"""
|
|
527
|
+
|
|
528
|
+
def validate_schema(manifest):
|
|
529
|
+
"""
|
|
530
|
+
Level 1: Schema Validation
|
|
531
|
+
- Check all required fields present
|
|
532
|
+
- Validate field types
|
|
533
|
+
- Check field formats (regex patterns)
|
|
534
|
+
- Validate enum values
|
|
535
|
+
"""
|
|
536
|
+
|
|
537
|
+
def validate_values(manifest):
|
|
538
|
+
"""
|
|
539
|
+
Level 2: Value Validation
|
|
540
|
+
- Port range validation
|
|
541
|
+
- Name format validation
|
|
542
|
+
- String length constraints
|
|
543
|
+
- Numeric range constraints
|
|
544
|
+
- Pattern matching
|
|
545
|
+
"""
|
|
546
|
+
|
|
547
|
+
def validate_cross_field(manifest):
|
|
548
|
+
"""
|
|
549
|
+
Level 3: Cross-Field Validation
|
|
550
|
+
- Frontend requires backend
|
|
551
|
+
- Prisma requires database
|
|
552
|
+
- Port conflicts with app type
|
|
553
|
+
- Dependencies valid
|
|
554
|
+
"""
|
|
555
|
+
|
|
556
|
+
def validate_dependencies(manifest, all_manifests):
|
|
557
|
+
"""
|
|
558
|
+
Level 4: Cross-Resource Validation
|
|
559
|
+
- dependsOn exist as resources
|
|
560
|
+
- No circular dependencies
|
|
561
|
+
- Backend references are valid
|
|
562
|
+
- Port uniqueness across resources
|
|
563
|
+
"""
|
|
564
|
+
|
|
565
|
+
def validate_ports_unique(manifests):
|
|
566
|
+
"""
|
|
567
|
+
Check for port conflicts across all manifests.
|
|
568
|
+
|
|
569
|
+
Returns:
|
|
570
|
+
List of port conflict errors
|
|
571
|
+
"""
|
|
572
|
+
|
|
573
|
+
def validate_naming_consistency(manifests):
|
|
574
|
+
"""
|
|
575
|
+
Check naming conventions across all resources.
|
|
576
|
+
|
|
577
|
+
Validates:
|
|
578
|
+
- Resource names follow convention: {stack}-{function}-{type}
|
|
579
|
+
- No duplicate names
|
|
580
|
+
- Consistent kebab-case
|
|
581
|
+
"""
|
|
582
|
+
|
|
583
|
+
def is_valid(manifest):
|
|
584
|
+
"""Quick check if manifest is valid (returns boolean)."""
|
|
585
|
+
|
|
586
|
+
def get_validation_report(manifest, context=None):
|
|
587
|
+
"""
|
|
588
|
+
Generate detailed validation report.
|
|
589
|
+
|
|
590
|
+
Returns:
|
|
591
|
+
Human-readable report with all issues and suggestions
|
|
592
|
+
"""
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
**Validation Rules:**
|
|
596
|
+
|
|
597
|
+
```starlark
|
|
598
|
+
VALIDATION_RULES = {
|
|
599
|
+
# Schema rules
|
|
600
|
+
'required_fields': {
|
|
601
|
+
'severity': 'error',
|
|
602
|
+
'check': lambda m: all(m.get(f) for f in get_required_fields(m)),
|
|
603
|
+
'message': 'Missing required field: {field}',
|
|
604
|
+
},
|
|
605
|
+
|
|
606
|
+
'field_types': {
|
|
607
|
+
'severity': 'error',
|
|
608
|
+
'check': _check_field_types,
|
|
609
|
+
'message': 'Field {field} has invalid type: {actual}, expected: {expected}',
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
# Value rules
|
|
613
|
+
'port_range': {
|
|
614
|
+
'severity': 'error',
|
|
615
|
+
'check': lambda m: _check_port_in_range(m),
|
|
616
|
+
'message': 'Port {port} is outside valid range for {appType}: {min}-{max}',
|
|
617
|
+
},
|
|
618
|
+
|
|
619
|
+
'name_format': {
|
|
620
|
+
'severity': 'error',
|
|
621
|
+
'check': lambda m: re.match(r'^[a-z][a-z0-9-]*$', m.get('appName', '')),
|
|
622
|
+
'message': 'Invalid appName format: {name}',
|
|
623
|
+
},
|
|
624
|
+
|
|
625
|
+
# Cross-field rules
|
|
626
|
+
'frontend_has_backend': {
|
|
627
|
+
'severity': 'error',
|
|
628
|
+
'condition': lambda m: m.get('appType') == 'frontend',
|
|
629
|
+
'check': lambda m: m.get('backendName'),
|
|
630
|
+
'message': 'Frontend {name} must specify backendName',
|
|
631
|
+
},
|
|
632
|
+
|
|
633
|
+
'prisma_has_database': {
|
|
634
|
+
'severity': 'warning',
|
|
635
|
+
'condition': lambda m: 'prisma' in m.get('features', []),
|
|
636
|
+
'check': lambda m: m.get('databaseName'),
|
|
637
|
+
'message': 'Service with prisma feature should specify databaseName',
|
|
638
|
+
},
|
|
639
|
+
|
|
640
|
+
# Cross-resource rules
|
|
641
|
+
'dependencies_exist': {
|
|
642
|
+
'severity': 'error',
|
|
643
|
+
'check': lambda m, ctx: _check_deps_exist(m, ctx.get('all_manifests', [])),
|
|
644
|
+
'message': 'Dependency {dep} does not exist as a resource',
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
'no_circular_deps': {
|
|
648
|
+
'severity': 'error',
|
|
649
|
+
'check': _check_no_circular_deps,
|
|
650
|
+
'message': 'Circular dependency detected: {path}',
|
|
651
|
+
},
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
### 6. `manifest/fetch.star` - Remote Manifest Fetching (Future)
|
|
658
|
+
|
|
659
|
+
**Purpose:** Fetch manifests from remote sources (for distributed teams or external resources)
|
|
660
|
+
|
|
661
|
+
```starlark
|
|
662
|
+
def fetch_from_git(repo_url, branch="main", path=""):
|
|
663
|
+
"""
|
|
664
|
+
Fetch manifest from git repository.
|
|
665
|
+
|
|
666
|
+
Future use case: External resource definitions
|
|
667
|
+
"""
|
|
668
|
+
|
|
669
|
+
def fetch_from_http(url):
|
|
670
|
+
"""
|
|
671
|
+
Fetch manifest from HTTP endpoint.
|
|
672
|
+
|
|
673
|
+
Future use case: Resource registry API
|
|
674
|
+
"""
|
|
675
|
+
|
|
676
|
+
def fetch_from_registry(resource_name, registry_url):
|
|
677
|
+
"""
|
|
678
|
+
Fetch manifest from resource registry.
|
|
679
|
+
|
|
680
|
+
Future use case: Centralized resource catalog
|
|
681
|
+
"""
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**Note:** This module is for future use. Initial refactoring focuses on local manifests.
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
688
|
+
### 7. `manifest/errors.star` - Error Types and Handling
|
|
689
|
+
|
|
690
|
+
**Purpose:** Standardized error handling with context
|
|
691
|
+
|
|
692
|
+
```starlark
|
|
693
|
+
# Error severity levels
|
|
694
|
+
SEVERITY = {
|
|
695
|
+
'CRITICAL': 'critical', # Must fix, system won't function
|
|
696
|
+
'ERROR': 'error', # Should fix, may cause issues
|
|
697
|
+
'WARNING': 'warning', # Should consider, non-blocking
|
|
698
|
+
'INFO': 'info', # Informational only
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
# Error categories
|
|
702
|
+
CATEGORY = {
|
|
703
|
+
'SCHEMA': 'schema',
|
|
704
|
+
'VALIDATION': 'validation',
|
|
705
|
+
'IO': 'io',
|
|
706
|
+
'PARSE': 'parse',
|
|
707
|
+
'DEPENDENCY': 'dependency',
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
def new_error(message, category, severity, context=None):
|
|
711
|
+
"""
|
|
712
|
+
Create standardized error struct.
|
|
713
|
+
|
|
714
|
+
Args:
|
|
715
|
+
message: Human-readable error message
|
|
716
|
+
category: Error category
|
|
717
|
+
severity: Error severity
|
|
718
|
+
context: Optional dict with:
|
|
719
|
+
- field: Field name if field-specific
|
|
720
|
+
- path: File path
|
|
721
|
+
- value: Invalid value
|
|
722
|
+
- suggestion: Suggested fix
|
|
723
|
+
|
|
724
|
+
Returns:
|
|
725
|
+
Error struct
|
|
726
|
+
"""
|
|
727
|
+
|
|
728
|
+
def format_error(error):
|
|
729
|
+
"""Format error for display."""
|
|
730
|
+
|
|
731
|
+
def group_errors(errors):
|
|
732
|
+
"""Group errors by category and severity."""
|
|
733
|
+
|
|
734
|
+
def has_critical_errors(errors):
|
|
735
|
+
"""Check if any critical errors exist."""
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Migration Strategy
|
|
741
|
+
|
|
742
|
+
### Phase 1: Foundation (Week 1-2)
|
|
743
|
+
|
|
744
|
+
**Goals:**
|
|
745
|
+
- Create new `manifest/` module structure
|
|
746
|
+
- Implement `constants.star`, `errors.star`, `schema.star`
|
|
747
|
+
- Write comprehensive tests
|
|
748
|
+
|
|
749
|
+
**Tasks:**
|
|
750
|
+
1. Create directory structure
|
|
751
|
+
2. Migrate `discovery/manifest/constants.star` → `manifest/constants.star`
|
|
752
|
+
3. Implement `schema.star` with complete field definitions
|
|
753
|
+
4. Implement `errors.star` with error handling
|
|
754
|
+
5. Write unit tests for schema and errors
|
|
755
|
+
|
|
756
|
+
**Backward Compatibility:**
|
|
757
|
+
- Keep `discovery/manifest/constants.star` as re-export wrapper
|
|
758
|
+
- Mark old path as deprecated in comments
|
|
759
|
+
|
|
760
|
+
### Phase 2: Core Implementation (Week 3-4)
|
|
761
|
+
|
|
762
|
+
**Goals:**
|
|
763
|
+
- Implement `loader.star` and `parser.star`
|
|
764
|
+
- Migrate loading logic from `discovery.star`
|
|
765
|
+
|
|
766
|
+
**Tasks:**
|
|
767
|
+
1. Implement `loader.star` with all loading functions
|
|
768
|
+
2. Implement `parser.star` with normalization logic
|
|
769
|
+
3. Extract parsing logic from `discovery.star`
|
|
770
|
+
4. Create comprehensive parser tests
|
|
771
|
+
5. Benchmark performance vs old implementation
|
|
772
|
+
|
|
773
|
+
**Backward Compatibility:**
|
|
774
|
+
- `discovery.star` re-exports from new module
|
|
775
|
+
- Gradual migration of consumers
|
|
776
|
+
|
|
777
|
+
### Phase 3: Validation (Week 5-6)
|
|
778
|
+
|
|
779
|
+
**Goals:**
|
|
780
|
+
- Implement comprehensive `validator.star`
|
|
781
|
+
- Replace inline validation in generators
|
|
782
|
+
|
|
783
|
+
**Tasks:**
|
|
784
|
+
1. Implement `validator.star` with all validation levels
|
|
785
|
+
2. Migrate validation from `generators/validators.star`
|
|
786
|
+
3. Add validation to manifest loading pipeline
|
|
787
|
+
4. Create validation report generator
|
|
788
|
+
5. Add CLI command to validate all manifests
|
|
789
|
+
|
|
790
|
+
**Backward Compatibility:**
|
|
791
|
+
- Old validators call new validator module
|
|
792
|
+
- Maintain same validation behavior
|
|
793
|
+
|
|
794
|
+
### Phase 4: Integration (Week 7)
|
|
795
|
+
|
|
796
|
+
**Goals:**
|
|
797
|
+
- Wire up `__init__.star` facade
|
|
798
|
+
- Migrate all consumers
|
|
799
|
+
- Clean up old code
|
|
800
|
+
|
|
801
|
+
**Tasks:**
|
|
802
|
+
1. Implement `__init__.star` with clean API
|
|
803
|
+
2. Update `discovery.star` to use new module
|
|
804
|
+
3. Update `registry.star` to use new module
|
|
805
|
+
4. Update `generators/` to use new module
|
|
806
|
+
5. Update `resources/orchestrator/` to use new module
|
|
807
|
+
6. Remove deprecated re-export files
|
|
808
|
+
7. Update all `load()` statements
|
|
809
|
+
|
|
810
|
+
### Phase 5: Cleanup (Week 8)
|
|
811
|
+
|
|
812
|
+
**Goals:**
|
|
813
|
+
- Remove deprecated code
|
|
814
|
+
- Update documentation
|
|
815
|
+
- Final testing
|
|
816
|
+
|
|
817
|
+
**Tasks:**
|
|
818
|
+
1. Remove old `discovery/manifest/` directory
|
|
819
|
+
2. Remove deprecated re-export wrappers
|
|
820
|
+
3. Update all documentation references
|
|
821
|
+
4. Run full integration tests
|
|
822
|
+
5. Update AGENTS.md with new structure
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
## Backward Compatibility Plan
|
|
827
|
+
|
|
828
|
+
### During Migration (Phases 1-4)
|
|
829
|
+
|
|
830
|
+
**Re-Export Pattern:**
|
|
831
|
+
```starlark
|
|
832
|
+
# In old file (e.g., discovery/manifest/constants.star)
|
|
833
|
+
# DEPRECATED: Use manifest/constants.star instead
|
|
834
|
+
load("../../manifest/constants.star",
|
|
835
|
+
MANIFEST_FILENAME="MANIFEST_FILENAME",
|
|
836
|
+
MANIFEST_DEFAULTS="MANIFEST_DEFAULTS",
|
|
837
|
+
# ... etc
|
|
838
|
+
)
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
**Gradual Migration:**
|
|
842
|
+
- Each consumer updated individually
|
|
843
|
+
- PRs reviewed separately
|
|
844
|
+
- No breaking changes during migration
|
|
845
|
+
|
|
846
|
+
### After Migration (Phase 5)
|
|
847
|
+
|
|
848
|
+
**Breaking Changes:**
|
|
849
|
+
- Old import paths removed
|
|
850
|
+
- Clear migration guide provided
|
|
851
|
+
- One-time update required
|
|
852
|
+
|
|
853
|
+
**Migration Guide:**
|
|
854
|
+
```starlark
|
|
855
|
+
# OLD (deprecated)
|
|
856
|
+
load("../discovery/manifest/constants.star", "MANIFEST_DEFAULTS")
|
|
857
|
+
load("../discovery/discovery.star", "_load_manifest_json")
|
|
858
|
+
|
|
859
|
+
# NEW
|
|
860
|
+
load("../manifest/__init__.star", "Manifest")
|
|
861
|
+
# Use Manifest.defaults, Manifest.load_from_file, etc.
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
## Testing Strategy
|
|
867
|
+
|
|
868
|
+
### Unit Tests
|
|
869
|
+
|
|
870
|
+
Each module has comprehensive unit tests:
|
|
871
|
+
|
|
872
|
+
```
|
|
873
|
+
manifest/tests/
|
|
874
|
+
├── test_loader.star # Test all loading scenarios
|
|
875
|
+
├── test_parser.star # Test parsing and normalization
|
|
876
|
+
├── test_validator.star # Test all validation rules
|
|
877
|
+
├── test_schema.star # Test schema definitions
|
|
878
|
+
└── test_integration.star # End-to-end integration tests
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
**Test Coverage:**
|
|
882
|
+
- Happy path: Valid manifests load correctly
|
|
883
|
+
- Error cases: Invalid manifests produce clear errors
|
|
884
|
+
- Edge cases: Empty manifests, missing fields, etc.
|
|
885
|
+
- Performance: Loading 100+ manifests efficiently
|
|
886
|
+
|
|
887
|
+
### Integration Tests
|
|
888
|
+
|
|
889
|
+
**Full Stack Test:**
|
|
890
|
+
```starlark
|
|
891
|
+
def test_full_manifest_pipeline():
|
|
892
|
+
# Load all manifests
|
|
893
|
+
result = Manifest.load_all("services/product")
|
|
894
|
+
|
|
895
|
+
# Validate all
|
|
896
|
+
for manifest in result.manifests:
|
|
897
|
+
validation = Manifest.validate(manifest, level='all')
|
|
898
|
+
assert validation.valid, validation.errors
|
|
899
|
+
|
|
900
|
+
# Check cross-resource dependencies
|
|
901
|
+
deps_validation = Manifest.validate_dependencies(
|
|
902
|
+
result.manifests
|
|
903
|
+
)
|
|
904
|
+
assert deps_validation.valid
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
---
|
|
908
|
+
|
|
909
|
+
## Benefits
|
|
910
|
+
|
|
911
|
+
### 1. **Separation of Concerns**
|
|
912
|
+
- Loading, parsing, and validation are distinct
|
|
913
|
+
- Each module has single responsibility
|
|
914
|
+
- Easier to understand and maintain
|
|
915
|
+
|
|
916
|
+
### 2. **Testability**
|
|
917
|
+
- Each module independently testable
|
|
918
|
+
- Clear inputs and outputs
|
|
919
|
+
- Mock-friendly interfaces
|
|
920
|
+
|
|
921
|
+
### 3. **Extensibility**
|
|
922
|
+
- Easy to add new validation rules
|
|
923
|
+
- Easy to support new manifest formats
|
|
924
|
+
- Easy to add remote fetching
|
|
925
|
+
|
|
926
|
+
### 4. **Developer Experience**
|
|
927
|
+
- Clear API via `__init__.star` facade
|
|
928
|
+
- Comprehensive error messages
|
|
929
|
+
- Validation reports with suggestions
|
|
930
|
+
|
|
931
|
+
### 5. **Documentation**
|
|
932
|
+
- Schema serves as living documentation
|
|
933
|
+
- Each field has description and example
|
|
934
|
+
- Constraints are explicitly defined
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
## Risk Mitigation
|
|
939
|
+
|
|
940
|
+
| Risk | Mitigation |
|
|
941
|
+
|------|------------|
|
|
942
|
+
| Breaking changes | Gradual migration with re-exports |
|
|
943
|
+
| Performance regression | Benchmark tests before/after |
|
|
944
|
+
| Validation behavior changes | Comprehensive test suite |
|
|
945
|
+
| Increased complexity | Clear module boundaries, good docs |
|
|
946
|
+
| Migration takes too long | Phased approach, each phase deliverable |
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## Success Metrics
|
|
951
|
+
|
|
952
|
+
- [ ] All 538 manifest references migrated
|
|
953
|
+
- [ ] 100% test coverage for new modules
|
|
954
|
+
- [ ] Zero breaking changes during migration
|
|
955
|
+
- [ ] Load time for 100 manifests < 1 second
|
|
956
|
+
- [ ] Validation catches 100% of invalid manifests
|
|
957
|
+
- [ ] All developers can understand new structure in < 10 minutes
|
|
958
|
+
|
|
959
|
+
---
|
|
960
|
+
|
|
961
|
+
## Next Steps
|
|
962
|
+
|
|
963
|
+
1. **Review this plan** with stakeholders
|
|
964
|
+
2. **Create Phase 1 PR** with module structure
|
|
965
|
+
3. **Set up test framework** for manifest tests
|
|
966
|
+
4. **Begin implementation** following migration phases
|
|
967
|
+
5. **Track progress** with success metrics
|
|
968
|
+
|
|
969
|
+
---
|
|
970
|
+
|
|
971
|
+
**Document Version:** 1.0
|
|
972
|
+
**Last Updated:** 2026-04-07
|
|
973
|
+
**Author:** super (with topology-engineer consultation)
|
|
974
|
+
**Reviewers:** Pending
|