@envsync-cloud/deploy-core 0.8.7
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 +19 -0
- package/dist/index.d.ts +286 -0
- package/dist/index.js +278 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# EnvSync Deploy Core
|
|
2
|
+
|
|
3
|
+
Shared deployment primitives for edition-aware packaging.
|
|
4
|
+
|
|
5
|
+
This package is the extraction target for logic currently living in
|
|
6
|
+
`packages/deploy-cli` so both:
|
|
7
|
+
|
|
8
|
+
- `@envsync-cloud/deploy` for OSS
|
|
9
|
+
- `@envsync-cloud/deploy-cli` for Enterprise
|
|
10
|
+
|
|
11
|
+
can share release rendering, topology defaults, and runtime-config generation.
|
|
12
|
+
|
|
13
|
+
Current exports:
|
|
14
|
+
|
|
15
|
+
- config file loading for YAML or JSON
|
|
16
|
+
- edition-aware topology validation
|
|
17
|
+
- runtime env generation
|
|
18
|
+
- frontend artifact planning for OSS vs Enterprise
|
|
19
|
+
- release artifact planning for npm, NPM Packages, and container images
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
type DeployEdition = "oss" | "enterprise";
|
|
4
|
+
declare class DeployPlanError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
declare const deployConfigSchema: z.ZodObject<{
|
|
8
|
+
edition: z.ZodOptional<z.ZodEnum<["oss", "enterprise"]>>;
|
|
9
|
+
source: z.ZodDefault<z.ZodObject<{
|
|
10
|
+
repo_url: z.ZodDefault<z.ZodString>;
|
|
11
|
+
ref: z.ZodDefault<z.ZodString>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
repo_url: string;
|
|
14
|
+
ref: string;
|
|
15
|
+
}, {
|
|
16
|
+
repo_url?: string | undefined;
|
|
17
|
+
ref?: string | undefined;
|
|
18
|
+
}>>;
|
|
19
|
+
release: z.ZodDefault<z.ZodObject<{
|
|
20
|
+
version: z.ZodDefault<z.ZodString>;
|
|
21
|
+
channel: z.ZodDefault<z.ZodString>;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
version: string;
|
|
24
|
+
channel: string;
|
|
25
|
+
}, {
|
|
26
|
+
version?: string | undefined;
|
|
27
|
+
channel?: string | undefined;
|
|
28
|
+
}>>;
|
|
29
|
+
domain: z.ZodDefault<z.ZodObject<{
|
|
30
|
+
root_domain: z.ZodDefault<z.ZodString>;
|
|
31
|
+
acme_email: z.ZodDefault<z.ZodString>;
|
|
32
|
+
}, "strip", z.ZodTypeAny, {
|
|
33
|
+
root_domain: string;
|
|
34
|
+
acme_email: string;
|
|
35
|
+
}, {
|
|
36
|
+
root_domain?: string | undefined;
|
|
37
|
+
acme_email?: string | undefined;
|
|
38
|
+
}>>;
|
|
39
|
+
services: z.ZodDefault<z.ZodObject<{
|
|
40
|
+
stack_name: z.ZodDefault<z.ZodString>;
|
|
41
|
+
api_port: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
management_api_port: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
public_http_port: z.ZodDefault<z.ZodNumber>;
|
|
44
|
+
public_https_port: z.ZodDefault<z.ZodNumber>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
stack_name: string;
|
|
47
|
+
api_port: number;
|
|
48
|
+
management_api_port: number;
|
|
49
|
+
public_http_port: number;
|
|
50
|
+
public_https_port: number;
|
|
51
|
+
}, {
|
|
52
|
+
stack_name?: string | undefined;
|
|
53
|
+
api_port?: number | undefined;
|
|
54
|
+
management_api_port?: number | undefined;
|
|
55
|
+
public_http_port?: number | undefined;
|
|
56
|
+
public_https_port?: number | undefined;
|
|
57
|
+
}>>;
|
|
58
|
+
images: z.ZodDefault<z.ZodObject<{
|
|
59
|
+
api: z.ZodDefault<z.ZodString>;
|
|
60
|
+
management_api: z.ZodDefault<z.ZodString>;
|
|
61
|
+
web: z.ZodDefault<z.ZodString>;
|
|
62
|
+
enterprise_web: z.ZodDefault<z.ZodString>;
|
|
63
|
+
landing: z.ZodDefault<z.ZodString>;
|
|
64
|
+
keycloak: z.ZodDefault<z.ZodString>;
|
|
65
|
+
clickstack: z.ZodDefault<z.ZodString>;
|
|
66
|
+
otel_agent: z.ZodDefault<z.ZodString>;
|
|
67
|
+
}, "strip", z.ZodTypeAny, {
|
|
68
|
+
api: string;
|
|
69
|
+
management_api: string;
|
|
70
|
+
web: string;
|
|
71
|
+
enterprise_web: string;
|
|
72
|
+
landing: string;
|
|
73
|
+
keycloak: string;
|
|
74
|
+
clickstack: string;
|
|
75
|
+
otel_agent: string;
|
|
76
|
+
}, {
|
|
77
|
+
api?: string | undefined;
|
|
78
|
+
management_api?: string | undefined;
|
|
79
|
+
web?: string | undefined;
|
|
80
|
+
enterprise_web?: string | undefined;
|
|
81
|
+
landing?: string | undefined;
|
|
82
|
+
keycloak?: string | undefined;
|
|
83
|
+
clickstack?: string | undefined;
|
|
84
|
+
otel_agent?: string | undefined;
|
|
85
|
+
}>>;
|
|
86
|
+
features: z.ZodDefault<z.ZodObject<{
|
|
87
|
+
management_api: z.ZodOptional<z.ZodBoolean>;
|
|
88
|
+
management_web: z.ZodOptional<z.ZodBoolean>;
|
|
89
|
+
landing: z.ZodOptional<z.ZodBoolean>;
|
|
90
|
+
}, "strip", z.ZodTypeAny, {
|
|
91
|
+
management_api?: boolean | undefined;
|
|
92
|
+
landing?: boolean | undefined;
|
|
93
|
+
management_web?: boolean | undefined;
|
|
94
|
+
}, {
|
|
95
|
+
management_api?: boolean | undefined;
|
|
96
|
+
landing?: boolean | undefined;
|
|
97
|
+
management_web?: boolean | undefined;
|
|
98
|
+
}>>;
|
|
99
|
+
observability: z.ZodDefault<z.ZodObject<{
|
|
100
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
101
|
+
public_obs: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
}, "strip", z.ZodTypeAny, {
|
|
103
|
+
enabled?: boolean | undefined;
|
|
104
|
+
public_obs?: boolean | undefined;
|
|
105
|
+
}, {
|
|
106
|
+
enabled?: boolean | undefined;
|
|
107
|
+
public_obs?: boolean | undefined;
|
|
108
|
+
}>>;
|
|
109
|
+
license: z.ZodDefault<z.ZodObject<{
|
|
110
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
111
|
+
server_url: z.ZodOptional<z.ZodString>;
|
|
112
|
+
key: z.ZodOptional<z.ZodString>;
|
|
113
|
+
install_fingerprint: z.ZodOptional<z.ZodString>;
|
|
114
|
+
lease_ttl_seconds: z.ZodDefault<z.ZodNumber>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
lease_ttl_seconds: number;
|
|
117
|
+
required?: boolean | undefined;
|
|
118
|
+
server_url?: string | undefined;
|
|
119
|
+
key?: string | undefined;
|
|
120
|
+
install_fingerprint?: string | undefined;
|
|
121
|
+
}, {
|
|
122
|
+
required?: boolean | undefined;
|
|
123
|
+
server_url?: string | undefined;
|
|
124
|
+
key?: string | undefined;
|
|
125
|
+
install_fingerprint?: string | undefined;
|
|
126
|
+
lease_ttl_seconds?: number | undefined;
|
|
127
|
+
}>>;
|
|
128
|
+
frontend: z.ZodDefault<z.ZodObject<{
|
|
129
|
+
dashboard_variant: z.ZodOptional<z.ZodEnum<["oss", "enterprise"]>>;
|
|
130
|
+
include_manage_subtree: z.ZodOptional<z.ZodBoolean>;
|
|
131
|
+
}, "strip", z.ZodTypeAny, {
|
|
132
|
+
dashboard_variant?: "oss" | "enterprise" | undefined;
|
|
133
|
+
include_manage_subtree?: boolean | undefined;
|
|
134
|
+
}, {
|
|
135
|
+
dashboard_variant?: "oss" | "enterprise" | undefined;
|
|
136
|
+
include_manage_subtree?: boolean | undefined;
|
|
137
|
+
}>>;
|
|
138
|
+
}, "strip", z.ZodTypeAny, {
|
|
139
|
+
source: {
|
|
140
|
+
repo_url: string;
|
|
141
|
+
ref: string;
|
|
142
|
+
};
|
|
143
|
+
release: {
|
|
144
|
+
version: string;
|
|
145
|
+
channel: string;
|
|
146
|
+
};
|
|
147
|
+
domain: {
|
|
148
|
+
root_domain: string;
|
|
149
|
+
acme_email: string;
|
|
150
|
+
};
|
|
151
|
+
services: {
|
|
152
|
+
stack_name: string;
|
|
153
|
+
api_port: number;
|
|
154
|
+
management_api_port: number;
|
|
155
|
+
public_http_port: number;
|
|
156
|
+
public_https_port: number;
|
|
157
|
+
};
|
|
158
|
+
images: {
|
|
159
|
+
api: string;
|
|
160
|
+
management_api: string;
|
|
161
|
+
web: string;
|
|
162
|
+
enterprise_web: string;
|
|
163
|
+
landing: string;
|
|
164
|
+
keycloak: string;
|
|
165
|
+
clickstack: string;
|
|
166
|
+
otel_agent: string;
|
|
167
|
+
};
|
|
168
|
+
features: {
|
|
169
|
+
management_api?: boolean | undefined;
|
|
170
|
+
landing?: boolean | undefined;
|
|
171
|
+
management_web?: boolean | undefined;
|
|
172
|
+
};
|
|
173
|
+
observability: {
|
|
174
|
+
enabled?: boolean | undefined;
|
|
175
|
+
public_obs?: boolean | undefined;
|
|
176
|
+
};
|
|
177
|
+
license: {
|
|
178
|
+
lease_ttl_seconds: number;
|
|
179
|
+
required?: boolean | undefined;
|
|
180
|
+
server_url?: string | undefined;
|
|
181
|
+
key?: string | undefined;
|
|
182
|
+
install_fingerprint?: string | undefined;
|
|
183
|
+
};
|
|
184
|
+
frontend: {
|
|
185
|
+
dashboard_variant?: "oss" | "enterprise" | undefined;
|
|
186
|
+
include_manage_subtree?: boolean | undefined;
|
|
187
|
+
};
|
|
188
|
+
edition?: "oss" | "enterprise" | undefined;
|
|
189
|
+
}, {
|
|
190
|
+
edition?: "oss" | "enterprise" | undefined;
|
|
191
|
+
source?: {
|
|
192
|
+
repo_url?: string | undefined;
|
|
193
|
+
ref?: string | undefined;
|
|
194
|
+
} | undefined;
|
|
195
|
+
release?: {
|
|
196
|
+
version?: string | undefined;
|
|
197
|
+
channel?: string | undefined;
|
|
198
|
+
} | undefined;
|
|
199
|
+
domain?: {
|
|
200
|
+
root_domain?: string | undefined;
|
|
201
|
+
acme_email?: string | undefined;
|
|
202
|
+
} | undefined;
|
|
203
|
+
services?: {
|
|
204
|
+
stack_name?: string | undefined;
|
|
205
|
+
api_port?: number | undefined;
|
|
206
|
+
management_api_port?: number | undefined;
|
|
207
|
+
public_http_port?: number | undefined;
|
|
208
|
+
public_https_port?: number | undefined;
|
|
209
|
+
} | undefined;
|
|
210
|
+
images?: {
|
|
211
|
+
api?: string | undefined;
|
|
212
|
+
management_api?: string | undefined;
|
|
213
|
+
web?: string | undefined;
|
|
214
|
+
enterprise_web?: string | undefined;
|
|
215
|
+
landing?: string | undefined;
|
|
216
|
+
keycloak?: string | undefined;
|
|
217
|
+
clickstack?: string | undefined;
|
|
218
|
+
otel_agent?: string | undefined;
|
|
219
|
+
} | undefined;
|
|
220
|
+
features?: {
|
|
221
|
+
management_api?: boolean | undefined;
|
|
222
|
+
landing?: boolean | undefined;
|
|
223
|
+
management_web?: boolean | undefined;
|
|
224
|
+
} | undefined;
|
|
225
|
+
observability?: {
|
|
226
|
+
enabled?: boolean | undefined;
|
|
227
|
+
public_obs?: boolean | undefined;
|
|
228
|
+
} | undefined;
|
|
229
|
+
license?: {
|
|
230
|
+
required?: boolean | undefined;
|
|
231
|
+
server_url?: string | undefined;
|
|
232
|
+
key?: string | undefined;
|
|
233
|
+
install_fingerprint?: string | undefined;
|
|
234
|
+
lease_ttl_seconds?: number | undefined;
|
|
235
|
+
} | undefined;
|
|
236
|
+
frontend?: {
|
|
237
|
+
dashboard_variant?: "oss" | "enterprise" | undefined;
|
|
238
|
+
include_manage_subtree?: boolean | undefined;
|
|
239
|
+
} | undefined;
|
|
240
|
+
}>;
|
|
241
|
+
type DeployConfig = z.infer<typeof deployConfigSchema>;
|
|
242
|
+
interface FrontendArtifactPlan {
|
|
243
|
+
id: "dashboard" | "management" | "landing";
|
|
244
|
+
package_name: string;
|
|
245
|
+
build_command: string;
|
|
246
|
+
mount_path: string;
|
|
247
|
+
included: boolean;
|
|
248
|
+
merged_into_dashboard?: boolean;
|
|
249
|
+
image: string | null;
|
|
250
|
+
}
|
|
251
|
+
interface ServicePlan {
|
|
252
|
+
id: string;
|
|
253
|
+
enabled: boolean;
|
|
254
|
+
tier: "core" | "enterprise" | "optional";
|
|
255
|
+
reason: string;
|
|
256
|
+
image: string | null;
|
|
257
|
+
}
|
|
258
|
+
interface ReleaseArtifactPlan {
|
|
259
|
+
npm_packages: Array<{
|
|
260
|
+
name: string;
|
|
261
|
+
registry: "npm" | "github-packages";
|
|
262
|
+
edition: DeployEdition;
|
|
263
|
+
publish: boolean;
|
|
264
|
+
}>;
|
|
265
|
+
container_images: Array<{
|
|
266
|
+
name: string;
|
|
267
|
+
image: string;
|
|
268
|
+
build_target: string;
|
|
269
|
+
edition: "shared" | DeployEdition;
|
|
270
|
+
}>;
|
|
271
|
+
}
|
|
272
|
+
interface DeploymentPlan {
|
|
273
|
+
edition: DeployEdition;
|
|
274
|
+
config: DeployConfig;
|
|
275
|
+
services: ServicePlan[];
|
|
276
|
+
frontend: FrontendArtifactPlan[];
|
|
277
|
+
runtime_env: Record<string, string>;
|
|
278
|
+
release_artifacts: ReleaseArtifactPlan;
|
|
279
|
+
warnings: string[];
|
|
280
|
+
}
|
|
281
|
+
declare function readDeployConfigFile(filePath: string): any;
|
|
282
|
+
declare function createDeploymentPlan(rawConfig: unknown, forcedEdition?: DeployEdition): DeploymentPlan;
|
|
283
|
+
declare function loadDeploymentPlanFromFile(filePath: string, forcedEdition?: DeployEdition): DeploymentPlan;
|
|
284
|
+
declare function formatDeploymentPlan(plan: DeploymentPlan, format?: "json" | "yaml"): string;
|
|
285
|
+
|
|
286
|
+
export { type DeployConfig, type DeployEdition, DeployPlanError, type DeploymentPlan, type FrontendArtifactPlan, type ReleaseArtifactPlan, type ServicePlan, createDeploymentPlan, formatDeploymentPlan, loadDeploymentPlanFromFile, readDeployConfigFile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import YAML from "yaml";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var DeployPlanError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "DeployPlanError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var deployConfigSchema = z.object({
|
|
13
|
+
edition: z.enum(["oss", "enterprise"]).optional(),
|
|
14
|
+
source: z.object({
|
|
15
|
+
repo_url: z.string().default("https://github.com/EnvSync-Cloud/envsync.git"),
|
|
16
|
+
ref: z.string().default("main")
|
|
17
|
+
}).default({}),
|
|
18
|
+
release: z.object({
|
|
19
|
+
version: z.string().default("0.8.7"),
|
|
20
|
+
channel: z.string().default("stable")
|
|
21
|
+
}).default({}),
|
|
22
|
+
domain: z.object({
|
|
23
|
+
root_domain: z.string().default("example.com"),
|
|
24
|
+
acme_email: z.string().default("ops@example.com")
|
|
25
|
+
}).default({}),
|
|
26
|
+
services: z.object({
|
|
27
|
+
stack_name: z.string().default("envsync"),
|
|
28
|
+
api_port: z.number().int().positive().default(4e3),
|
|
29
|
+
management_api_port: z.number().int().positive().default(4001),
|
|
30
|
+
public_http_port: z.number().int().positive().default(80),
|
|
31
|
+
public_https_port: z.number().int().positive().default(443)
|
|
32
|
+
}).default({}),
|
|
33
|
+
images: z.object({
|
|
34
|
+
api: z.string().default("ghcr.io/envsync-cloud/envsync-api:stable"),
|
|
35
|
+
management_api: z.string().default("ghcr.io/envsync-cloud/envsync-management-api:stable"),
|
|
36
|
+
web: z.string().default("ghcr.io/envsync-cloud/envsync-web-oss-static:stable"),
|
|
37
|
+
enterprise_web: z.string().default("ghcr.io/envsync-cloud/envsync-web-static:stable"),
|
|
38
|
+
landing: z.string().default("ghcr.io/envsync-cloud/envsync-landing-static:stable"),
|
|
39
|
+
keycloak: z.string().default("envsync-keycloak:stable"),
|
|
40
|
+
clickstack: z.string().default("ghcr.io/envsync-cloud/clickstack:stable"),
|
|
41
|
+
otel_agent: z.string().default("otel/opentelemetry-collector-contrib:latest")
|
|
42
|
+
}).default({}),
|
|
43
|
+
features: z.object({
|
|
44
|
+
management_api: z.boolean().optional(),
|
|
45
|
+
management_web: z.boolean().optional(),
|
|
46
|
+
landing: z.boolean().optional()
|
|
47
|
+
}).default({}),
|
|
48
|
+
observability: z.object({
|
|
49
|
+
enabled: z.boolean().optional(),
|
|
50
|
+
public_obs: z.boolean().optional()
|
|
51
|
+
}).default({}),
|
|
52
|
+
license: z.object({
|
|
53
|
+
required: z.boolean().optional(),
|
|
54
|
+
server_url: z.string().optional(),
|
|
55
|
+
key: z.string().optional(),
|
|
56
|
+
install_fingerprint: z.string().optional(),
|
|
57
|
+
lease_ttl_seconds: z.number().int().positive().default(300)
|
|
58
|
+
}).default({}),
|
|
59
|
+
frontend: z.object({
|
|
60
|
+
dashboard_variant: z.enum(["oss", "enterprise"]).optional(),
|
|
61
|
+
include_manage_subtree: z.boolean().optional()
|
|
62
|
+
}).default({})
|
|
63
|
+
});
|
|
64
|
+
function readDeployConfigFile(filePath) {
|
|
65
|
+
const absolutePath = path.resolve(process.cwd(), filePath);
|
|
66
|
+
if (!fs.existsSync(absolutePath)) {
|
|
67
|
+
throw new DeployPlanError(`Deploy config file not found: ${absolutePath}`);
|
|
68
|
+
}
|
|
69
|
+
const raw = fs.readFileSync(absolutePath, "utf8");
|
|
70
|
+
if (absolutePath.endsWith(".json")) {
|
|
71
|
+
return JSON.parse(raw);
|
|
72
|
+
}
|
|
73
|
+
return YAML.parse(raw);
|
|
74
|
+
}
|
|
75
|
+
function validateEditionRules(config, edition) {
|
|
76
|
+
const errors = [];
|
|
77
|
+
if (edition === "oss") {
|
|
78
|
+
if (config.edition === "enterprise") {
|
|
79
|
+
errors.push("OSS deploy tooling cannot consume a config explicitly marked as enterprise.");
|
|
80
|
+
}
|
|
81
|
+
if (config.features.management_api === true) {
|
|
82
|
+
errors.push("OSS edition cannot enable management_api.");
|
|
83
|
+
}
|
|
84
|
+
if (config.features.landing === true) {
|
|
85
|
+
errors.push("OSS edition cannot enable landing.");
|
|
86
|
+
}
|
|
87
|
+
if (config.license.required === true) {
|
|
88
|
+
errors.push("OSS edition cannot require enterprise licensing.");
|
|
89
|
+
}
|
|
90
|
+
if (config.license.server_url || config.license.key || config.license.install_fingerprint) {
|
|
91
|
+
errors.push("OSS edition cannot include enterprise license server settings.");
|
|
92
|
+
}
|
|
93
|
+
if (config.frontend.dashboard_variant === "enterprise") {
|
|
94
|
+
errors.push("OSS edition cannot use the enterprise dashboard variant.");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (edition === "enterprise") {
|
|
98
|
+
if (config.edition === "oss") {
|
|
99
|
+
errors.push("Enterprise deploy tooling cannot consume a config explicitly marked as oss.");
|
|
100
|
+
}
|
|
101
|
+
if (config.features.management_api === false) {
|
|
102
|
+
errors.push("Enterprise edition must enable management_api.");
|
|
103
|
+
}
|
|
104
|
+
if (config.features.landing === false) {
|
|
105
|
+
errors.push("Enterprise edition must enable landing.");
|
|
106
|
+
}
|
|
107
|
+
if (config.license.required === false) {
|
|
108
|
+
errors.push("Enterprise edition must require licensing.");
|
|
109
|
+
}
|
|
110
|
+
if (!config.license.server_url) {
|
|
111
|
+
errors.push("Enterprise edition requires license.server_url.");
|
|
112
|
+
}
|
|
113
|
+
if (config.frontend.dashboard_variant === "oss") {
|
|
114
|
+
errors.push("Enterprise edition cannot use the OSS dashboard variant.");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (errors.length > 0) {
|
|
118
|
+
throw new DeployPlanError(errors.join(" "));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function buildServicePlans(config, edition) {
|
|
122
|
+
const observabilityEnabled = config.observability.enabled ?? edition === "enterprise";
|
|
123
|
+
const managementEnabled = edition === "enterprise";
|
|
124
|
+
const landingEnabled = edition === "enterprise";
|
|
125
|
+
return [
|
|
126
|
+
{ id: "api", enabled: true, tier: "core", reason: "Required in all editions.", image: config.images.api },
|
|
127
|
+
{ id: "web", enabled: true, tier: "core", reason: "Primary dashboard artifact.", image: edition === "enterprise" ? config.images.enterprise_web : config.images.web },
|
|
128
|
+
{ id: "postgres", enabled: true, tier: "core", reason: "Core persistence.", image: null },
|
|
129
|
+
{ id: "redis", enabled: true, tier: "core", reason: "Core cache and sessions.", image: null },
|
|
130
|
+
{ id: "rustfs", enabled: true, tier: "core", reason: "Object storage for artifacts.", image: null },
|
|
131
|
+
{ id: "openfga", enabled: true, tier: "core", reason: "Authorization service.", image: null },
|
|
132
|
+
{ id: "minikms", enabled: true, tier: "core", reason: "Secret encryption service.", image: null },
|
|
133
|
+
{ id: "keycloak", enabled: true, tier: "core", reason: "Authentication provider.", image: config.images.keycloak },
|
|
134
|
+
{ id: "management-api", enabled: managementEnabled, tier: "enterprise", reason: managementEnabled ? "Enterprise control plane API." : "Not deployed in OSS.", image: managementEnabled ? config.images.management_api : null },
|
|
135
|
+
{ id: "landing", enabled: landingEnabled, tier: "enterprise", reason: landingEnabled ? "Enterprise/public onboarding surface." : "Omitted in OSS.", image: landingEnabled ? config.images.landing : null },
|
|
136
|
+
{ id: "clickstack", enabled: observabilityEnabled, tier: observabilityEnabled ? "optional" : "optional", reason: observabilityEnabled ? "Observability enabled for this topology." : "Observability disabled.", image: observabilityEnabled ? config.images.clickstack : null },
|
|
137
|
+
{ id: "otel-agent", enabled: observabilityEnabled, tier: "optional", reason: observabilityEnabled ? "OTEL pipeline enabled for this topology." : "OTEL disabled.", image: observabilityEnabled ? config.images.otel_agent : null }
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
function buildFrontendArtifacts(config, edition) {
|
|
141
|
+
const enterprise = edition === "enterprise";
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
id: "dashboard",
|
|
145
|
+
package_name: "envsync-web",
|
|
146
|
+
build_command: enterprise ? "bun run --filter envsync-web build:enterprise" : "bun run --filter envsync-web build:oss",
|
|
147
|
+
mount_path: "/",
|
|
148
|
+
included: true,
|
|
149
|
+
image: enterprise ? config.images.enterprise_web : config.images.web
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: "landing",
|
|
153
|
+
package_name: "envsync-landing",
|
|
154
|
+
build_command: "bun run --filter envsync-landing build",
|
|
155
|
+
mount_path: "/",
|
|
156
|
+
included: enterprise,
|
|
157
|
+
image: enterprise ? config.images.landing : null
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
function buildRuntimeEnv(config, edition) {
|
|
162
|
+
const enterprise = edition === "enterprise";
|
|
163
|
+
const observabilityEnabled = config.observability.enabled ?? enterprise;
|
|
164
|
+
return {
|
|
165
|
+
ENVSYNC_EDITION: edition,
|
|
166
|
+
ENVSYNC_OBSERVABILITY_ENABLED: String(observabilityEnabled),
|
|
167
|
+
ENVSYNC_MANAGEMENT_ENABLED: String(enterprise),
|
|
168
|
+
ENVSYNC_LANDING_ENABLED: String(enterprise),
|
|
169
|
+
ENVSYNC_SINGLE_ORG_MODE: String(edition === "oss"),
|
|
170
|
+
ENVSYNC_LICENSE_ENFORCEMENT: String(enterprise),
|
|
171
|
+
ENVSYNC_LICENSE_MODE: enterprise ? "certificate" : "none",
|
|
172
|
+
ENVSYNC_LICENSE_BUNDLE_PATH: enterprise ? "/etc/envsync/license/enterprise-license-bundle.json" : "",
|
|
173
|
+
ENVSYNC_LICENSE_CERT_PATH: enterprise ? "/etc/envsync/license/enterprise-cert.pem" : "",
|
|
174
|
+
ENVSYNC_LICENSE_KEY_PATH: enterprise ? "/etc/envsync/license/enterprise-key.pem" : "",
|
|
175
|
+
ENVSYNC_LICENSE_ROOT_CA_CERT_PATH: enterprise ? "/etc/envsync/license/root-ca.pem" : "",
|
|
176
|
+
MANAGEMENT_API_URL: enterprise ? `https://manage-api.${config.domain.root_domain}` : "",
|
|
177
|
+
ENVSYNC_LICENSE_SERVER_URL: enterprise ? config.license.server_url ?? "" : "",
|
|
178
|
+
ENVSYNC_LICENSE_KEY: enterprise ? config.license.key ?? "" : "",
|
|
179
|
+
ENVSYNC_INSTALL_FINGERPRINT: enterprise ? config.license.install_fingerprint ?? "" : "",
|
|
180
|
+
ENVSYNC_LICENSE_LEASE_TTL_SECONDS: String(config.license.lease_ttl_seconds),
|
|
181
|
+
ENVSYNC_STACK_NAME: config.services.stack_name,
|
|
182
|
+
ENVSYNC_RELEASE_VERSION: config.release.version
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function buildReleaseArtifacts(config, edition) {
|
|
186
|
+
const npmPackages = [
|
|
187
|
+
{
|
|
188
|
+
name: "@envsync-cloud/deploy",
|
|
189
|
+
registry: "npm",
|
|
190
|
+
edition: "oss",
|
|
191
|
+
publish: edition === "oss"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: "@envsync-cloud/deploy-cli",
|
|
195
|
+
registry: "github-packages",
|
|
196
|
+
edition: "enterprise",
|
|
197
|
+
publish: edition === "enterprise"
|
|
198
|
+
}
|
|
199
|
+
];
|
|
200
|
+
const container_images = [
|
|
201
|
+
{
|
|
202
|
+
name: "envsync-api",
|
|
203
|
+
image: config.images.api,
|
|
204
|
+
build_target: "packages/envsync-api",
|
|
205
|
+
edition: "shared"
|
|
206
|
+
}
|
|
207
|
+
];
|
|
208
|
+
if (edition === "enterprise") {
|
|
209
|
+
container_images.push(
|
|
210
|
+
{
|
|
211
|
+
name: "envsync-management-api",
|
|
212
|
+
image: config.images.management_api,
|
|
213
|
+
build_target: "packages/envsync-management-api",
|
|
214
|
+
edition: "enterprise"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "envsync-web-static",
|
|
218
|
+
image: config.images.enterprise_web,
|
|
219
|
+
build_target: "apps/envsync-web#build:enterprise",
|
|
220
|
+
edition: "enterprise"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "envsync-landing-static",
|
|
224
|
+
image: config.images.landing,
|
|
225
|
+
build_target: "apps/envsync-landing#build",
|
|
226
|
+
edition: "enterprise"
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
container_images.push({
|
|
231
|
+
name: "envsync-web-oss-static",
|
|
232
|
+
image: config.images.web,
|
|
233
|
+
build_target: "apps/envsync-web#build:oss",
|
|
234
|
+
edition: "oss"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
npm_packages: npmPackages,
|
|
239
|
+
container_images
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function createDeploymentPlan(rawConfig, forcedEdition) {
|
|
243
|
+
const config = deployConfigSchema.parse(rawConfig);
|
|
244
|
+
const edition = forcedEdition ?? config.edition ?? "oss";
|
|
245
|
+
validateEditionRules(config, edition);
|
|
246
|
+
const warnings = [];
|
|
247
|
+
if (edition === "oss" && (config.observability.enabled ?? false) === false) {
|
|
248
|
+
warnings.push("Observability is disabled for OSS. ClickStack and OTEL services will be omitted.");
|
|
249
|
+
}
|
|
250
|
+
if (edition === "enterprise" && !config.license.key) {
|
|
251
|
+
warnings.push("Enterprise topology is valid, but license.key is empty. Activation will fail until a real key is supplied.");
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
edition,
|
|
255
|
+
config,
|
|
256
|
+
services: buildServicePlans(config, edition),
|
|
257
|
+
frontend: buildFrontendArtifacts(config, edition),
|
|
258
|
+
runtime_env: buildRuntimeEnv(config, edition),
|
|
259
|
+
release_artifacts: buildReleaseArtifacts(config, edition),
|
|
260
|
+
warnings
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function loadDeploymentPlanFromFile(filePath, forcedEdition) {
|
|
264
|
+
return createDeploymentPlan(readDeployConfigFile(filePath), forcedEdition);
|
|
265
|
+
}
|
|
266
|
+
function formatDeploymentPlan(plan, format = "yaml") {
|
|
267
|
+
if (format === "json") {
|
|
268
|
+
return JSON.stringify(plan, null, 2);
|
|
269
|
+
}
|
|
270
|
+
return YAML.stringify(plan);
|
|
271
|
+
}
|
|
272
|
+
export {
|
|
273
|
+
DeployPlanError,
|
|
274
|
+
createDeploymentPlan,
|
|
275
|
+
formatDeploymentPlan,
|
|
276
|
+
loadDeploymentPlanFromFile,
|
|
277
|
+
readDeployConfigFile
|
|
278
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@envsync-cloud/deploy-core",
|
|
3
|
+
"version": "0.8.7",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"module": "src/index.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format esm --dts --out-dir dist",
|
|
18
|
+
"test": "bun test"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"yaml": "^2.8.1",
|
|
22
|
+
"zod": "^3.25.76"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"tsup": "^8.5.0",
|
|
26
|
+
"typescript": "^5.9.2"
|
|
27
|
+
}
|
|
28
|
+
}
|