@envsync-cloud/deploy 0.20.2 → 0.20.4
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/dist/cli.js +42 -12
- package/dist/index.js +42 -12
- package/package.json +4 -3
package/dist/cli.js
CHANGED
|
@@ -361,6 +361,7 @@ function buildRuntimeEnv2(config, generated, options) {
|
|
|
361
361
|
ENVSYNC_EDITION: oss ? "oss" : "enterprise",
|
|
362
362
|
// Self-host product install — never multi-tenant SaaS mode (program plan Phase 1).
|
|
363
363
|
ENVSYNC_DEPLOYMENT_MODE: "selfhosted",
|
|
364
|
+
SKIP_ROOT_ENV: "1",
|
|
364
365
|
ENVSYNC_MANAGEMENT_ENABLED: oss ? "false" : "true",
|
|
365
366
|
// Landing is Hosted-only; self-host does not ship marketing/signup surface.
|
|
366
367
|
ENVSYNC_LANDING_ENABLED: "false",
|
|
@@ -1144,6 +1145,12 @@ ${renderEnvList({
|
|
|
1144
1145
|
})}
|
|
1145
1146
|
${apiLicenseVolume}
|
|
1146
1147
|
networks: [envsync]
|
|
1148
|
+
healthcheck:
|
|
1149
|
+
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:4000/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
1150
|
+
interval: 10s
|
|
1151
|
+
timeout: 5s
|
|
1152
|
+
retries: 8
|
|
1153
|
+
start_period: 45s
|
|
1147
1154
|
deploy:
|
|
1148
1155
|
replicas: ${slotHasApiDeployment(deployment.slots.blue) ? 1 : 0}
|
|
1149
1156
|
|
|
@@ -1157,6 +1164,12 @@ ${renderEnvList({
|
|
|
1157
1164
|
})}
|
|
1158
1165
|
${apiLicenseVolume}
|
|
1159
1166
|
networks: [envsync]
|
|
1167
|
+
healthcheck:
|
|
1168
|
+
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:4000/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
1169
|
+
interval: 10s
|
|
1170
|
+
timeout: 5s
|
|
1171
|
+
retries: 8
|
|
1172
|
+
start_period: 45s
|
|
1160
1173
|
deploy:
|
|
1161
1174
|
replicas: ${slotHasApiDeployment(deployment.slots.green) ? 1 : 0}` : ""}${netutilsService}${vpnResult?.serviceBlock ?? ""}
|
|
1162
1175
|
|
|
@@ -2883,7 +2896,7 @@ function createApiDbUpgradeBackup(config, fromVersion, toVersion) {
|
|
|
2883
2896
|
"postgres:17",
|
|
2884
2897
|
"sh",
|
|
2885
2898
|
"-lc",
|
|
2886
|
-
`pg_dump -h
|
|
2899
|
+
`pg_dump -h postgres -U postgres -d envsync -Fc -f /backup/${fileName}`
|
|
2887
2900
|
]);
|
|
2888
2901
|
logSuccess(`API DB upgrade snapshot created at ${hostPath}`);
|
|
2889
2902
|
return hostPath;
|
|
@@ -2907,7 +2920,7 @@ function restoreApiDbUpgradeBackup(config, backupPath) {
|
|
|
2907
2920
|
"postgres:17",
|
|
2908
2921
|
"sh",
|
|
2909
2922
|
"-lc",
|
|
2910
|
-
`pg_restore --clean --if-exists --no-owner --no-privileges -h
|
|
2923
|
+
`pg_restore --clean --if-exists --no-owner --no-privileges -h postgres -U postgres -d envsync /backup/${fileName}`
|
|
2911
2924
|
]);
|
|
2912
2925
|
logSuccess(`API DB upgrade snapshot restored from ${backupPath}`);
|
|
2913
2926
|
}
|
|
@@ -3275,6 +3288,7 @@ function runApiMigrationJsonCommand(config, image, args) {
|
|
|
3275
3288
|
executedMigrations: []
|
|
3276
3289
|
};
|
|
3277
3290
|
}
|
|
3291
|
+
const migrateCli = args.map((arg) => JSON.stringify(arg)).join(" ");
|
|
3278
3292
|
const output = run(
|
|
3279
3293
|
"docker",
|
|
3280
3294
|
[
|
|
@@ -3287,11 +3301,14 @@ function runApiMigrationJsonCommand(config, image, args) {
|
|
|
3287
3301
|
"-e",
|
|
3288
3302
|
"SKIP_ROOT_ENV=1",
|
|
3289
3303
|
image,
|
|
3290
|
-
"
|
|
3291
|
-
"
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3304
|
+
"sh",
|
|
3305
|
+
"-lc",
|
|
3306
|
+
[
|
|
3307
|
+
"if [ -d /app/packages/envsync-api ]; then cd /app/packages/envsync-api; fi",
|
|
3308
|
+
`if [ -f scripts/migrate.enterprise.ts ]; then exec bun run scripts/migrate.enterprise.ts ${migrateCli} --json`,
|
|
3309
|
+
`elif [ -f scripts/migrate.ts ]; then exec bun run scripts/migrate.ts ${migrateCli} --json`,
|
|
3310
|
+
"else echo 'Migration CLI missing from API image (expected scripts/migrate.ts)' >&2; exit 1; fi"
|
|
3311
|
+
].join("; ")
|
|
3295
3312
|
],
|
|
3296
3313
|
{ quiet: true }
|
|
3297
3314
|
);
|
|
@@ -3630,7 +3647,15 @@ function waitForApiSlotHealthy(config, slot, timeoutSeconds = 180) {
|
|
|
3630
3647
|
sleepSeconds(3);
|
|
3631
3648
|
}
|
|
3632
3649
|
const services = listStackServices(config);
|
|
3633
|
-
|
|
3650
|
+
const ps = tryRun("docker", ["service", "ps", serviceName, "--no-trunc", "--format", "{{.CurrentState}} {{.Error}}"], {
|
|
3651
|
+
quiet: true
|
|
3652
|
+
});
|
|
3653
|
+
const logs = tryRun("docker", ["service", "logs", "--tail", "80", serviceName], { quiet: true });
|
|
3654
|
+
throw new Error(
|
|
3655
|
+
`Timed out waiting for API ${slot} slot to become healthy: ${serviceHealth(services, serviceName)}
|
|
3656
|
+
${ps}
|
|
3657
|
+
${logs}`
|
|
3658
|
+
);
|
|
3634
3659
|
}
|
|
3635
3660
|
function waitForHealthyServices(config, checks, timeoutSeconds = 180) {
|
|
3636
3661
|
if (currentOptions.dryRun) {
|
|
@@ -4188,8 +4213,8 @@ async function cmdDeploy() {
|
|
|
4188
4213
|
logSection("Deploy");
|
|
4189
4214
|
const { config, generated } = loadState();
|
|
4190
4215
|
logReleaseContext(config);
|
|
4191
|
-
if (!isOssConfig2(config)) {
|
|
4192
|
-
|
|
4216
|
+
if (!isOssConfig2(config) && !currentOptions.dryRun) {
|
|
4217
|
+
await ensureEnterpriseCertificateBundle(config);
|
|
4193
4218
|
}
|
|
4194
4219
|
assertSwarmManager();
|
|
4195
4220
|
assertBootstrapState(generated);
|
|
@@ -4255,7 +4280,12 @@ async function cmdDeploy() {
|
|
|
4255
4280
|
const rollbackTarget = preUpgradeHead ?? "zero";
|
|
4256
4281
|
try {
|
|
4257
4282
|
logWarn(`Candidate deploy failed after migration. Rolling schema back to ${rollbackTarget}.`);
|
|
4258
|
-
|
|
4283
|
+
try {
|
|
4284
|
+
runApiMigrationJsonCommand(config, config.images.api, ["rollback_to", rollbackTarget]);
|
|
4285
|
+
} catch {
|
|
4286
|
+
logWarn(`Rollback with ${config.images.api} failed; retrying with ${activeImageBeforeUpgrade}.`);
|
|
4287
|
+
runApiMigrationJsonCommand(config, activeImageBeforeUpgrade, ["rollback_to", rollbackTarget]);
|
|
4288
|
+
}
|
|
4259
4289
|
} catch (rollbackError) {
|
|
4260
4290
|
if (!snapshotPath) {
|
|
4261
4291
|
throw new Error(
|
|
@@ -4564,7 +4594,7 @@ async function cmdUpgrade(targetVersion) {
|
|
|
4564
4594
|
};
|
|
4565
4595
|
logReleaseContext(config);
|
|
4566
4596
|
if (!isOssConfig2(config) && !currentOptions.dryRun) {
|
|
4567
|
-
|
|
4597
|
+
await ensureEnterpriseCertificateBundle(config);
|
|
4568
4598
|
}
|
|
4569
4599
|
config.images = {
|
|
4570
4600
|
...config.images,
|
package/dist/index.js
CHANGED
|
@@ -362,6 +362,7 @@ function buildRuntimeEnv2(config, generated, options) {
|
|
|
362
362
|
ENVSYNC_EDITION: oss ? "oss" : "enterprise",
|
|
363
363
|
// Self-host product install — never multi-tenant SaaS mode (program plan Phase 1).
|
|
364
364
|
ENVSYNC_DEPLOYMENT_MODE: "selfhosted",
|
|
365
|
+
SKIP_ROOT_ENV: "1",
|
|
365
366
|
ENVSYNC_MANAGEMENT_ENABLED: oss ? "false" : "true",
|
|
366
367
|
// Landing is Hosted-only; self-host does not ship marketing/signup surface.
|
|
367
368
|
ENVSYNC_LANDING_ENABLED: "false",
|
|
@@ -1141,6 +1142,12 @@ ${renderEnvList({
|
|
|
1141
1142
|
})}
|
|
1142
1143
|
${apiLicenseVolume}
|
|
1143
1144
|
networks: [envsync]
|
|
1145
|
+
healthcheck:
|
|
1146
|
+
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:4000/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
1147
|
+
interval: 10s
|
|
1148
|
+
timeout: 5s
|
|
1149
|
+
retries: 8
|
|
1150
|
+
start_period: 45s
|
|
1144
1151
|
deploy:
|
|
1145
1152
|
replicas: ${slotHasApiDeployment(deployment.slots.blue) ? 1 : 0}
|
|
1146
1153
|
|
|
@@ -1154,6 +1161,12 @@ ${renderEnvList({
|
|
|
1154
1161
|
})}
|
|
1155
1162
|
${apiLicenseVolume}
|
|
1156
1163
|
networks: [envsync]
|
|
1164
|
+
healthcheck:
|
|
1165
|
+
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:4000/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
1166
|
+
interval: 10s
|
|
1167
|
+
timeout: 5s
|
|
1168
|
+
retries: 8
|
|
1169
|
+
start_period: 45s
|
|
1157
1170
|
deploy:
|
|
1158
1171
|
replicas: ${slotHasApiDeployment(deployment.slots.green) ? 1 : 0}` : ""}${netutilsService}${vpnResult?.serviceBlock ?? ""}
|
|
1159
1172
|
|
|
@@ -2745,7 +2758,7 @@ function createApiDbUpgradeBackup(config, fromVersion, toVersion) {
|
|
|
2745
2758
|
"postgres:17",
|
|
2746
2759
|
"sh",
|
|
2747
2760
|
"-lc",
|
|
2748
|
-
`pg_dump -h
|
|
2761
|
+
`pg_dump -h postgres -U postgres -d envsync -Fc -f /backup/${fileName}`
|
|
2749
2762
|
]);
|
|
2750
2763
|
logSuccess(`API DB upgrade snapshot created at ${hostPath}`);
|
|
2751
2764
|
return hostPath;
|
|
@@ -2769,7 +2782,7 @@ function restoreApiDbUpgradeBackup(config, backupPath) {
|
|
|
2769
2782
|
"postgres:17",
|
|
2770
2783
|
"sh",
|
|
2771
2784
|
"-lc",
|
|
2772
|
-
`pg_restore --clean --if-exists --no-owner --no-privileges -h
|
|
2785
|
+
`pg_restore --clean --if-exists --no-owner --no-privileges -h postgres -U postgres -d envsync /backup/${fileName}`
|
|
2773
2786
|
]);
|
|
2774
2787
|
logSuccess(`API DB upgrade snapshot restored from ${backupPath}`);
|
|
2775
2788
|
}
|
|
@@ -3137,6 +3150,7 @@ function runApiMigrationJsonCommand(config, image, args) {
|
|
|
3137
3150
|
executedMigrations: []
|
|
3138
3151
|
};
|
|
3139
3152
|
}
|
|
3153
|
+
const migrateCli = args.map((arg) => JSON.stringify(arg)).join(" ");
|
|
3140
3154
|
const output = run(
|
|
3141
3155
|
"docker",
|
|
3142
3156
|
[
|
|
@@ -3149,11 +3163,14 @@ function runApiMigrationJsonCommand(config, image, args) {
|
|
|
3149
3163
|
"-e",
|
|
3150
3164
|
"SKIP_ROOT_ENV=1",
|
|
3151
3165
|
image,
|
|
3152
|
-
"
|
|
3153
|
-
"
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3166
|
+
"sh",
|
|
3167
|
+
"-lc",
|
|
3168
|
+
[
|
|
3169
|
+
"if [ -d /app/packages/envsync-api ]; then cd /app/packages/envsync-api; fi",
|
|
3170
|
+
`if [ -f scripts/migrate.enterprise.ts ]; then exec bun run scripts/migrate.enterprise.ts ${migrateCli} --json`,
|
|
3171
|
+
`elif [ -f scripts/migrate.ts ]; then exec bun run scripts/migrate.ts ${migrateCli} --json`,
|
|
3172
|
+
"else echo 'Migration CLI missing from API image (expected scripts/migrate.ts)' >&2; exit 1; fi"
|
|
3173
|
+
].join("; ")
|
|
3157
3174
|
],
|
|
3158
3175
|
{ quiet: true }
|
|
3159
3176
|
);
|
|
@@ -3492,7 +3509,15 @@ function waitForApiSlotHealthy(config, slot, timeoutSeconds = 180) {
|
|
|
3492
3509
|
sleepSeconds(3);
|
|
3493
3510
|
}
|
|
3494
3511
|
const services = listStackServices(config);
|
|
3495
|
-
|
|
3512
|
+
const ps = tryRun("docker", ["service", "ps", serviceName, "--no-trunc", "--format", "{{.CurrentState}} {{.Error}}"], {
|
|
3513
|
+
quiet: true
|
|
3514
|
+
});
|
|
3515
|
+
const logs = tryRun("docker", ["service", "logs", "--tail", "80", serviceName], { quiet: true });
|
|
3516
|
+
throw new Error(
|
|
3517
|
+
`Timed out waiting for API ${slot} slot to become healthy: ${serviceHealth(services, serviceName)}
|
|
3518
|
+
${ps}
|
|
3519
|
+
${logs}`
|
|
3520
|
+
);
|
|
3496
3521
|
}
|
|
3497
3522
|
function waitForHealthyServices(config, checks, timeoutSeconds = 180) {
|
|
3498
3523
|
if (currentOptions.dryRun) {
|
|
@@ -4050,8 +4075,8 @@ async function cmdDeploy() {
|
|
|
4050
4075
|
logSection("Deploy");
|
|
4051
4076
|
const { config, generated } = loadState();
|
|
4052
4077
|
logReleaseContext(config);
|
|
4053
|
-
if (!isOssConfig2(config)) {
|
|
4054
|
-
|
|
4078
|
+
if (!isOssConfig2(config) && !currentOptions.dryRun) {
|
|
4079
|
+
await ensureEnterpriseCertificateBundle(config);
|
|
4055
4080
|
}
|
|
4056
4081
|
assertSwarmManager();
|
|
4057
4082
|
assertBootstrapState(generated);
|
|
@@ -4117,7 +4142,12 @@ async function cmdDeploy() {
|
|
|
4117
4142
|
const rollbackTarget = preUpgradeHead ?? "zero";
|
|
4118
4143
|
try {
|
|
4119
4144
|
logWarn(`Candidate deploy failed after migration. Rolling schema back to ${rollbackTarget}.`);
|
|
4120
|
-
|
|
4145
|
+
try {
|
|
4146
|
+
runApiMigrationJsonCommand(config, config.images.api, ["rollback_to", rollbackTarget]);
|
|
4147
|
+
} catch {
|
|
4148
|
+
logWarn(`Rollback with ${config.images.api} failed; retrying with ${activeImageBeforeUpgrade}.`);
|
|
4149
|
+
runApiMigrationJsonCommand(config, activeImageBeforeUpgrade, ["rollback_to", rollbackTarget]);
|
|
4150
|
+
}
|
|
4121
4151
|
} catch (rollbackError) {
|
|
4122
4152
|
if (!snapshotPath) {
|
|
4123
4153
|
throw new Error(
|
|
@@ -4426,7 +4456,7 @@ async function cmdUpgrade(targetVersion) {
|
|
|
4426
4456
|
};
|
|
4427
4457
|
logReleaseContext(config);
|
|
4428
4458
|
if (!isOssConfig2(config) && !currentOptions.dryRun) {
|
|
4429
|
-
|
|
4459
|
+
await ensureEnterpriseCertificateBundle(config);
|
|
4430
4460
|
}
|
|
4431
4461
|
config.images = {
|
|
4432
4462
|
...config.images,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envsync-cloud/deploy",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.4",
|
|
4
4
|
"description": "OSS CLI for self-hosted EnvSync deployment on Docker Swarm",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,10 +42,11 @@
|
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"chalk": "^5.6.2",
|
|
45
|
-
"yaml": "^1.10.2"
|
|
45
|
+
"yaml": "^1.10.2",
|
|
46
|
+
"zod": "^3.25.76"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@envsync-cloud/deploy-core": "0.20.
|
|
49
|
+
"@envsync-cloud/deploy-core": "0.20.4",
|
|
49
50
|
"tsup": "^8.5.0",
|
|
50
51
|
"typescript": "^5.9.2"
|
|
51
52
|
},
|