@flisk-sh/flisk 1.4.0 → 1.4.1

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.
Files changed (43) hide show
  1. package/cli/dist/commands/doctor.js +62 -0
  2. package/cli/dist/commands/runtime.js +6 -3
  3. package/cli/dist/generator/template-engine.js +7 -4
  4. package/cli/dist/utils/runtime-layout.js +7 -0
  5. package/cli/dist-bundle/chunk-7HR5PVOD.js +54 -0
  6. package/cli/dist-bundle/{chunk-PVBAGX5X.js → chunk-7IXBBU27.js} +1 -1
  7. package/cli/dist-bundle/{chunk-VHFFSBVJ.js → chunk-BB5BZ37Y.js} +1 -1
  8. package/cli/dist-bundle/{chunk-D7N2GGJH.js → chunk-DUNCELUK.js} +1 -1
  9. package/cli/dist-bundle/{chunk-36SOQVAL.js → chunk-KJOCVAMQ.js} +1 -1
  10. package/cli/dist-bundle/{chunk-VMB5673O.js → chunk-L6U555CJ.js} +30 -26
  11. package/cli/dist-bundle/{chunk-HEMPQKD6.js → chunk-M2R464RM.js} +1 -1
  12. package/cli/dist-bundle/{chunk-QQEV6D74.js → chunk-RX6O3PG4.js} +1 -1
  13. package/cli/dist-bundle/{chunk-ICXF6PXA.js → chunk-SRN64OPO.js} +2 -2
  14. package/cli/dist-bundle/{chunk-5EZ4EX6U.js → chunk-TZNXL3IO.js} +1 -1
  15. package/cli/dist-bundle/{chunk-B6Q5VKL7.js → chunk-UJXR6MZ2.js} +1 -1
  16. package/cli/dist-bundle/{chunk-BWK6MPCB.js → chunk-VRESY4NR.js} +1 -1
  17. package/cli/dist-bundle/cli.js +153 -153
  18. package/cli/dist-bundle/{cold-preflight-ABU26DYW.js → cold-preflight-BBDDHWRV.js} +1 -1
  19. package/cli/dist-bundle/{demo-stage-EBIUCJBX.js → demo-stage-HIHO4VV3.js} +1 -1
  20. package/cli/dist-bundle/{open-2KSAF6M2.js → open-W3QX35R6.js} +1 -1
  21. package/cli/dist-bundle/project-FW5LL2KM.js +2 -0
  22. package/cli/dist-bundle/{services-V6Q55JR5.js → services-RGTQ2LXC.js} +1 -1
  23. package/cli/dist-bundle/{tilt-port-owner-MWJ7P6NB.js → tilt-port-owner-6DO7OJRR.js} +1 -1
  24. package/cli/package.json +1 -1
  25. package/package.json +11 -2
  26. package/runtime/platform/services/platform/proxy/service.yaml +14 -0
  27. package/cli/dist/commands/__tests__/project-e2e-helpers.js +0 -49
  28. package/cli/dist/commands/__tests__/ui-loading-screen.test.js +0 -16
  29. package/cli/dist/generator/__tests__/golden-helpers.js +0 -43
  30. package/cli/dist-bundle/chunk-763VK575.js +0 -54
  31. package/cli/dist-bundle/project-YD3C4ZV3.js +0 -2
  32. package/runtime/discovery/test_resource_snapshot.py +0 -253
  33. package/runtime/engine/assets/docker/wake-gateway/decide.test.ts +0 -177
  34. package/runtime/engine/topologies/tilt/manifest/tests/test_integration.star +0 -278
  35. package/runtime/engine/topologies/tilt/manifest/tests/test_loader_parser.star +0 -475
  36. package/runtime/engine/topologies/tilt/manifest/tests/test_manifest.star +0 -319
  37. package/runtime/engine/topologies/tilt/manifest/tests/test_validator.star +0 -472
  38. package/runtime/ext/ide-components/shared/test_config_service.py +0 -328
  39. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/bun-hoisted-symlink-fix.sh +0 -0
  40. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/infisical-entrypoint.sh +0 -0
  41. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/install-deps.sh +0 -0
  42. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/prisma-bun-client-link-fix.sh +0 -0
  43. /package/{shared-platform-engineering → runtime/shared-platform-engineering}/docker-templates/prisma-normalize-client.sh +0 -0
@@ -1,177 +0,0 @@
1
- // Copyright (c) 2026 Flisk Landscape contributors
2
- // SPDX-License-Identifier: MIT
3
- import { describe, expect, test } from "bun:test";
4
- import {
5
- COMPOSE_START_TIMEOUT_MS,
6
- EARLY_RESPONSE_MS,
7
- MAX_EARLY_RESPONSE_MS,
8
- RETRY_AFTER_SECONDS,
9
- TILT_TRIGGER_TIMEOUT_MS,
10
- decideWakeAction,
11
- earlyResponseMs,
12
- evaluateReadiness,
13
- isGatewayLivenessProbe,
14
- wakeTimeoutMs,
15
- } from "./decide";
16
-
17
- describe("decideWakeAction", () => {
18
- test("never-created resource: tilt trigger only, no Sablier start", () => {
19
- const action = decideWakeAction({
20
- resourceContainerName: "data-governance-api",
21
- resourceState: "absent",
22
- dependencies: [],
23
- });
24
- expect(action.tiltTriggerNames).toEqual(["data-governance-api"]);
25
- expect(action.useSablierStart).toBe(false);
26
- });
27
-
28
- test("previously-run, now-exited resource: both tilt trigger and Sablier start", () => {
29
- const action = decideWakeAction({
30
- resourceContainerName: "data-governance-api",
31
- resourceState: "exited",
32
- dependencies: [],
33
- });
34
- expect(action.tiltTriggerNames).toEqual(["data-governance-api"]);
35
- expect(action.useSablierStart).toBe(true);
36
- });
37
-
38
- test("created-but-not-started resource: both paths apply", () => {
39
- const action = decideWakeAction({
40
- resourceContainerName: "data-governance-api",
41
- resourceState: "created",
42
- dependencies: [],
43
- });
44
- expect(action.useSablierStart).toBe(true);
45
- });
46
-
47
- test("already running: no trigger needed", () => {
48
- const action = decideWakeAction({
49
- resourceContainerName: "data-governance-api",
50
- resourceState: "running",
51
- dependencies: [],
52
- });
53
- expect(action.tiltTriggerNames).toEqual([]);
54
- expect(action.useSablierStart).toBe(false);
55
- });
56
-
57
- test("cold dependency is triggered alongside the resource (task 1.5 finding)", () => {
58
- const action = decideWakeAction({
59
- resourceContainerName: "data-governance-api",
60
- resourceState: "absent",
61
- dependencies: [
62
- { name: "postgres", state: "running" },
63
- { name: "data-governance-api-db-migrator", state: "absent" },
64
- ],
65
- });
66
- expect(action.tiltTriggerNames).toEqual([
67
- "data-governance-api",
68
- "data-governance-api-db-migrator",
69
- ]);
70
- });
71
-
72
- test("never-created resource with compose details: started directly, not queued in Tilt", () => {
73
- const action = decideWakeAction({
74
- resourceContainerName: "data-governance-api",
75
- resourceState: "absent",
76
- dependencies: [{ name: "peer-api", state: "absent" }],
77
- hasComposeInvocation: true,
78
- });
79
- expect(action.useComposeStart).toBe(true);
80
- // Dependencies carry no compose details, so they still go through Tilt.
81
- expect(action.tiltTriggerNames).toEqual(["peer-api"]);
82
- expect(action.useSablierStart).toBe(false);
83
- });
84
-
85
- test("existing (exited) container keeps the Sablier path even with compose details", () => {
86
- const action = decideWakeAction({
87
- resourceContainerName: "data-governance-api",
88
- resourceState: "exited",
89
- dependencies: [],
90
- hasComposeInvocation: true,
91
- });
92
- expect(action.useComposeStart).toBe(false);
93
- expect(action.tiltTriggerNames).toEqual(["data-governance-api"]);
94
- expect(action.useSablierStart).toBe(true);
95
- });
96
-
97
- test("running dependency is not re-triggered", () => {
98
- const action = decideWakeAction({
99
- resourceContainerName: "data-governance-api",
100
- resourceState: "running",
101
- dependencies: [{ name: "postgres", state: "running" }],
102
- });
103
- expect(action.tiltTriggerNames).toEqual([]);
104
- });
105
- });
106
-
107
- describe("wakeTimeoutMs", () => {
108
- test("a direct compose start only waits for boot + healthcheck", () => {
109
- expect(wakeTimeoutMs(true)).toBe(COMPOSE_START_TIMEOUT_MS);
110
- });
111
-
112
- test("the tilt trigger path allows for an image build, under Bun's 255s idle cap", () => {
113
- expect(wakeTimeoutMs(false)).toBe(TILT_TRIGGER_TIMEOUT_MS);
114
- expect(TILT_TRIGGER_TIMEOUT_MS).toBeLessThan(255_000);
115
- });
116
-
117
- test("an explicit X-Wake-Timeout-Ms wins", () => {
118
- expect(wakeTimeoutMs(false, 5_000)).toBe(5_000);
119
- });
120
- });
121
-
122
- describe("earlyResponseMs", () => {
123
- test("holds a waking request for EARLY_RESPONSE_MS by default", () => {
124
- expect(earlyResponseMs()).toBe(EARLY_RESPONSE_MS);
125
- });
126
-
127
- test("the default answers well before Bun's 255s idle cap drops the connection", () => {
128
- expect(EARLY_RESPONSE_MS).toBeLessThan(255_000);
129
- });
130
-
131
- test("an explicit X-Wake-Respond-Within-Ms wins, but is capped under Bun's idle limit", () => {
132
- expect(earlyResponseMs(5_000)).toBe(5_000);
133
- expect(earlyResponseMs(600_000)).toBe(MAX_EARLY_RESPONSE_MS);
134
- expect(MAX_EARLY_RESPONSE_MS).toBeLessThan(255_000);
135
- });
136
-
137
- test("tells the caller to retry soon", () => {
138
- expect(RETRY_AFTER_SECONDS).toBeGreaterThan(0);
139
- expect(RETRY_AFTER_SECONDS * 1000).toBeLessThan(EARLY_RESPONSE_MS);
140
- });
141
- });
142
-
143
- describe("evaluateReadiness", () => {
144
- test("ready once every required name reports healthy", () => {
145
- const outcome = evaluateReadiness(["a", "b"], { a: true, b: true });
146
- expect(outcome.ready).toBe(true);
147
- expect(outcome.pending).toEqual([]);
148
- });
149
-
150
- test("not ready while some names are still unhealthy", () => {
151
- const outcome = evaluateReadiness(["a", "b"], { a: true, b: false });
152
- expect(outcome.ready).toBe(false);
153
- expect(outcome.pending).toEqual(["b"]);
154
- });
155
-
156
- test("missing entries count as not healthy", () => {
157
- const outcome = evaluateReadiness(["a", "b"], { a: true });
158
- expect(outcome.ready).toBe(false);
159
- expect(outcome.pending).toEqual(["b"]);
160
- });
161
- });
162
-
163
- describe("isGatewayLivenessProbe", () => {
164
- test("a bare GET /health from the image HEALTHCHECK is answered by the gateway", () => {
165
- expect(isGatewayLivenessProbe("GET", "/health", new Headers())).toBe(true);
166
- });
167
-
168
- test("a backend /health routed through the wake gateway is proxied, not answered", () => {
169
- const routed = new Headers({ "X-Wake-Resource": "cold-api", "X-Wake-Container": "cold-api-1" });
170
- expect(isGatewayLivenessProbe("GET", "/health", routed)).toBe(false);
171
- });
172
-
173
- test("other methods and paths are not liveness probes", () => {
174
- expect(isGatewayLivenessProbe("POST", "/health", new Headers())).toBe(false);
175
- expect(isGatewayLivenessProbe("GET", "/health/ready", new Headers())).toBe(false);
176
- });
177
- });
@@ -1,278 +0,0 @@
1
- # Copyright (c) 2026 Flisk Landscape contributors
2
- # SPDX-License-Identifier: MIT
3
- # =============================================================================
4
- # 📋 MANIFEST MODULE - INTEGRATION TESTS (Phase 4)
5
- # =============================================================================
6
- # Path: .tilt/topologies/tilt/manifest/tests/test_integration.star
7
- # Purpose: Integration tests for discovery system integration
8
- # Status: Phase 4 of manifest system refactoring
9
- # =============================================================================
10
-
11
- load("../__init__.star", "Manifest")
12
- load("../integration.star", "ManifestIntegration")
13
-
14
- # =============================================================================
15
- # TEST FRAMEWORK
16
- # =============================================================================
17
-
18
- test_results = {
19
- 'passed': 0,
20
- 'failed': 0,
21
- 'errors': [],
22
- }
23
-
24
- def assert_true(condition, message="Assertion failed"):
25
- """Assert that condition is true."""
26
- if not condition:
27
- test_results['failed'] += 1
28
- test_results['errors'].append("FAIL: " + message)
29
- else:
30
- test_results['passed'] += 1
31
-
32
- def assert_equal(expected, actual, message="Values not equal"):
33
- """Assert that expected equals actual."""
34
- if expected != actual:
35
- test_results['failed'] += 1
36
- test_results['errors'].append(
37
- "FAIL: {} - expected '{}', got '{}'".format(message, expected, actual)
38
- )
39
- else:
40
- test_results['passed'] += 1
41
-
42
- def assert_not_none(value, message="Value is None"):
43
- """Assert that value is not None."""
44
- if value == None:
45
- test_results['failed'] += 1
46
- test_results['errors'].append("FAIL: " + message)
47
- else:
48
- test_results['passed'] += 1
49
-
50
- # =============================================================================
51
- # TEST SUITE: Integration Functions
52
- # =============================================================================
53
-
54
- def _test_integration_functions():
55
- """Test integration functions are accessible."""
56
- print("🔍 Testing integration functions...")
57
-
58
- # Test via facade
59
- assert_not_none(Manifest.load_and_validate_integration, "load_and_validate_integration should be accessible")
60
- assert_not_none(Manifest.load_all_integration, "load_all_integration should be accessible")
61
- assert_not_none(Manifest.convert_to_resource, "convert_to_resource should be accessible")
62
- assert_not_none(Manifest.get_validation_summary, "get_validation_summary should be accessible")
63
- assert_not_none(Manifest.check_port_conflicts, "check_port_conflicts should be accessible")
64
- assert_not_none(Manifest.check_dependencies_valid, "check_dependencies_valid should be accessible")
65
-
66
- # Test via integration module
67
- assert_not_none(ManifestIntegration.load_and_validate, "ManifestIntegration.load_and_validate should exist")
68
- assert_not_none(ManifestIntegration.load_all, "ManifestIntegration.load_all should exist")
69
-
70
- print("✅ Integration functions accessible\n")
71
-
72
- # =============================================================================
73
- # TEST SUITE: Convert to Resource
74
- # =============================================================================
75
-
76
- def _test_convert_to_resource():
77
- """Test manifest to resource conversion."""
78
- print("🔍 Testing convert_to_resource...")
79
-
80
- # Test backend conversion
81
- backend_manifest = {
82
- 'appName': 'user-management-backend',
83
- 'appType': 'backend',
84
- 'stack': 'user',
85
- 'port': 4000,
86
- 'syncs': ['src', 'prisma'],
87
- '_resource_path': 'services/product/user/user-management-backend',
88
- '_manifest': {'runtime': 'bun'},
89
- }
90
-
91
- resource = Manifest.convert_to_resource(backend_manifest)
92
-
93
- assert_equal('user-management-backend', resource['name'], "Should preserve name")
94
- assert_equal(4000, resource['port'], "Should preserve port")
95
- assert_equal('user', resource['stack'], "Should preserve stack")
96
- assert_true('frontend' not in resource or not resource['frontend'], "Should not mark as frontend")
97
- assert_equal('services/product/user/user-management-backend', resource['_resource_path'], "Should preserve service path")
98
-
99
- # Test frontend conversion
100
- frontend_manifest = {
101
- 'appName': 'user-management-frontend',
102
- 'appType': 'frontend',
103
- 'stack': 'user',
104
- 'port': 3000,
105
- 'backendName': 'user-management-backend',
106
- '_resource_path': 'services/product/user/user-management-frontend',
107
- }
108
-
109
- resource = Manifest.convert_to_resource(frontend_manifest)
110
-
111
- assert_equal('user-management-frontend', resource['name'], "Should preserve name")
112
- assert_true(resource.get('frontend', False), "Should mark as frontend")
113
- assert_equal('user-management-backend', resource['backendName'], "Should preserve backendName")
114
-
115
- print("✅ Convert to resource tests complete\n")
116
-
117
- # =============================================================================
118
- # TEST SUITE: Validation Summary
119
- # =============================================================================
120
-
121
- def _test_validation_summary():
122
- """Test validation summary generation."""
123
- print("🔍 Testing validation summary...")
124
-
125
- manifests = [
126
- {
127
- 'appName': 'valid-service',
128
- 'appType': 'backend',
129
- 'stack': 'user',
130
- 'port': 4000,
131
- },
132
- {
133
- 'appName': 'valid-frontend',
134
- 'appType': 'frontend',
135
- 'stack': 'user',
136
- 'port': 3000,
137
- 'backendName': 'valid-service',
138
- },
139
- ]
140
-
141
- summary = Manifest.get_validation_summary(manifests)
142
-
143
- assert_equal(2, summary['total'], "Should count total manifests")
144
- assert_true('valid' in summary, "Should have valid count")
145
- assert_true('invalid' in summary, "Should have invalid count")
146
- assert_true('by_severity' in summary, "Should have severity breakdown")
147
-
148
- print("✅ Validation summary tests complete\n")
149
-
150
- # =============================================================================
151
- # TEST SUITE: Port Conflicts
152
- # =============================================================================
153
-
154
- def _test_port_conflicts():
155
- """Test port conflict detection."""
156
- print("🔍 Testing port conflict detection...")
157
-
158
- # No conflicts
159
- no_conflict = [
160
- {'appName': 'service-1', 'port': 4000},
161
- {'appName': 'service-2', 'port': 4001},
162
- {'appName': 'service-3', 'port': 4002},
163
- ]
164
-
165
- conflicts = Manifest.check_port_conflicts(no_conflict)
166
- assert_equal(0, len(conflicts), "Should find no conflicts for unique ports")
167
-
168
- # With conflicts
169
- with_conflict = [
170
- {'appName': 'service-1', 'port': 4000},
171
- {'appName': 'service-2', 'port': 4000}, # Conflict!
172
- {'appName': 'service-3', 'port': 4001},
173
- ]
174
-
175
- conflicts = Manifest.check_port_conflicts(with_conflict)
176
- assert_true(len(conflicts) > 0, "Should find port conflicts")
177
-
178
- print("✅ Port conflict tests complete\n")
179
-
180
- # =============================================================================
181
- # TEST SUITE: Dependency Validation
182
- # =============================================================================
183
-
184
- def _test_dependency_validation():
185
- """Test dependency validation across services."""
186
- print("🔍 Testing dependency validation...")
187
-
188
- manifests = [
189
- {
190
- 'appName': 'identity-backend',
191
- 'appType': 'backend',
192
- 'stack': 'identity',
193
- 'port': 4004,
194
- },
195
- {
196
- 'appName': 'user-backend',
197
- 'appType': 'backend',
198
- 'stack': 'user',
199
- 'port': 4000,
200
- 'dependsOn': ['identity-backend'], # Valid
201
- },
202
- {
203
- 'appName': 'user-frontend',
204
- 'appType': 'frontend',
205
- 'stack': 'user',
206
- 'port': 3000,
207
- 'backendName': 'user-backend', # Valid
208
- },
209
- {
210
- 'appName': 'bad-service',
211
- 'appType': 'backend',
212
- 'stack': 'user',
213
- 'port': 4001,
214
- 'dependsOn': ['nonexistent-service'], # Invalid
215
- },
216
- ]
217
-
218
- errors = Manifest.check_dependencies_valid(manifests)
219
-
220
- # Should find at least one error for nonexistent dependency
221
- assert_true(len(errors) > 0, "Should find dependency issues")
222
-
223
- print("✅ Dependency validation tests complete\n")
224
-
225
- # =============================================================================
226
- # TEST SUITE: Feature Flag
227
- # =============================================================================
228
-
229
- def _test_feature_flag():
230
- """Test the feature flag system."""
231
- print("🔍 Testing feature flag...")
232
-
233
- # Check if flag is accessible
234
- use_new = ManifestIntegration.use_new_system()
235
- assert_true(use_new != None, "Feature flag should return boolean")
236
-
237
- print("✅ Feature flag tests complete\n")
238
-
239
- # =============================================================================
240
- # MAIN
241
- # =============================================================================
242
-
243
- def run_tests():
244
- """Run all Phase 4 integration tests."""
245
- print("\n" + "="*70)
246
- print("📋 MANIFEST MODULE - PHASE 4 INTEGRATION TESTS")
247
- print("="*70 + "\n")
248
-
249
- # Run all test suites
250
- _test_integration_functions()
251
- _test_convert_to_resource()
252
- _test_validation_summary()
253
- _test_port_conflicts()
254
- _test_dependency_validation()
255
- _test_feature_flag()
256
-
257
- # Print results
258
- print("\n" + "="*70)
259
- print("📊 TEST RESULTS")
260
- print("="*70)
261
- print("✅ Passed: {}".format(test_results['passed']))
262
- print("❌ Failed: {}".format(test_results['failed']))
263
-
264
- if test_results['errors']:
265
- print("\n📝 ERRORS:")
266
- for error in test_results['errors']:
267
- print(" " + error)
268
- else:
269
- print("\n🎉 All Phase 4 integration tests passed!")
270
-
271
- print("="*70 + "\n")
272
-
273
- return test_results['failed'] == 0
274
-
275
- # Export test runner
276
- TestIntegration = struct(
277
- run=run_tests,
278
- )