@envsync-cloud/deploy-cli 0.6.5 → 0.6.6
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 -2
- package/dist/index.js +39 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ bunx @envsync-cloud/deploy-cli <command>
|
|
|
40
40
|
```text
|
|
41
41
|
envsync-deploy preinstall
|
|
42
42
|
envsync-deploy setup
|
|
43
|
-
envsync-deploy bootstrap [--dry-run]
|
|
43
|
+
envsync-deploy bootstrap [--dry-run] [--force]
|
|
44
44
|
envsync-deploy deploy [--dry-run]
|
|
45
45
|
envsync-deploy health [--json]
|
|
46
46
|
envsync-deploy upgrade [--dry-run]
|
|
@@ -71,7 +71,7 @@ Bootstrap infra, migrations, RustFS, and OpenFGA:
|
|
|
71
71
|
npx @envsync-cloud/deploy-cli bootstrap
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
`bootstrap` is destructive. It removes the existing EnvSync stack, matching containers, network, and managed volumes before rebuilding, and requires typing `
|
|
74
|
+
`bootstrap` is destructive. It removes the existing EnvSync stack, matching containers, network, and managed volumes before rebuilding, and requires typing `yes` to continue. Use `--force` to bypass the prompt in automation or other non-interactive environments.
|
|
75
75
|
|
|
76
76
|
Deploy the pending API and frontend services:
|
|
77
77
|
|
|
@@ -106,6 +106,7 @@ Preview mutating commands without changing the host:
|
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
108
|
npx @envsync-cloud/deploy-cli bootstrap --dry-run
|
|
109
|
+
npx @envsync-cloud/deploy-cli bootstrap --force
|
|
109
110
|
npx @envsync-cloud/deploy-cli deploy --dry-run
|
|
110
111
|
```
|
|
111
112
|
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var REQUIRED_BOOTSTRAP_ENV_KEYS = [
|
|
|
48
48
|
"OPENFGA_MODEL_ID"
|
|
49
49
|
];
|
|
50
50
|
var SEMVER_VERSION_RE = /^\d+\.\d+\.\d+$/;
|
|
51
|
-
var currentOptions = { dryRun: false };
|
|
51
|
+
var currentOptions = { dryRun: false, force: false };
|
|
52
52
|
function formatShellArg(arg) {
|
|
53
53
|
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(arg)) return arg;
|
|
54
54
|
return JSON.stringify(arg);
|
|
@@ -221,7 +221,7 @@ async function ask(question, fallback = "") {
|
|
|
221
221
|
}
|
|
222
222
|
async function askRequired(question) {
|
|
223
223
|
if (!process.stdin.isTTY) {
|
|
224
|
-
throw new Error(
|
|
224
|
+
throw new Error("Bootstrap confirmation requires an interactive terminal. Re-run with --force to bypass the prompt.");
|
|
225
225
|
}
|
|
226
226
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
227
227
|
return await new Promise((resolve) => {
|
|
@@ -1090,7 +1090,29 @@ function waitForTcpService(config, label, host, port, timeoutSeconds = 120) {
|
|
|
1090
1090
|
throw new Error(`Timed out waiting for ${label} at ${host}:${port}`);
|
|
1091
1091
|
}
|
|
1092
1092
|
function waitForHttpService(config, label, url, timeoutSeconds = 120) {
|
|
1093
|
-
|
|
1093
|
+
if (currentOptions.dryRun) {
|
|
1094
|
+
logDryRun(`Would wait for ${label} at ${url}`);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
logStep(`Waiting for ${label} on ${url}`);
|
|
1098
|
+
const deadline = Date.now() + timeoutSeconds * 1e3;
|
|
1099
|
+
while (Date.now() < deadline) {
|
|
1100
|
+
if (commandSucceeds("docker", [
|
|
1101
|
+
"run",
|
|
1102
|
+
"--rm",
|
|
1103
|
+
"--network",
|
|
1104
|
+
stackNetworkName(config),
|
|
1105
|
+
"alpine:3.20",
|
|
1106
|
+
"sh",
|
|
1107
|
+
"-lc",
|
|
1108
|
+
`wget -q -O /dev/null ${JSON.stringify(url)}`
|
|
1109
|
+
])) {
|
|
1110
|
+
logSuccess(`${label} is ready`);
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
sleepSeconds(2);
|
|
1114
|
+
}
|
|
1115
|
+
throw new Error(`Timed out waiting for ${label} at ${url}`);
|
|
1094
1116
|
}
|
|
1095
1117
|
function runOpenFgaMigrate(config, runtimeEnv) {
|
|
1096
1118
|
logStep("Running OpenFGA datastore migrations");
|
|
@@ -1307,9 +1329,14 @@ async function confirmBootstrapReset(config) {
|
|
|
1307
1329
|
logWarn("Containers: none currently matched");
|
|
1308
1330
|
}
|
|
1309
1331
|
logWarn("This removes existing deployment data for the managed EnvSync services.");
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1332
|
+
if (currentOptions.force) {
|
|
1333
|
+
logWarn("Skipping confirmation because --force was provided.");
|
|
1334
|
+
logSuccess("Destructive bootstrap reset confirmed");
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
const response = await askRequired(chalk.bold.red('Type "yes" to continue:'));
|
|
1338
|
+
if (response !== "yes") {
|
|
1339
|
+
throw new Error("Bootstrap aborted. Confirmation did not match 'yes'.");
|
|
1313
1340
|
}
|
|
1314
1341
|
logSuccess("Destructive bootstrap reset confirmed");
|
|
1315
1342
|
}
|
|
@@ -1480,9 +1507,8 @@ async function cmdBootstrap() {
|
|
|
1480
1507
|
assertSwarmManager();
|
|
1481
1508
|
if (currentOptions.dryRun) {
|
|
1482
1509
|
logWarn("Dry-run mode: bootstrap reset will be previewed but not executed.");
|
|
1483
|
-
} else {
|
|
1484
|
-
await confirmBootstrapReset(config);
|
|
1485
1510
|
}
|
|
1511
|
+
await confirmBootstrapReset(config);
|
|
1486
1512
|
cleanupBootstrapState(config);
|
|
1487
1513
|
ensureRepoCheckout(config);
|
|
1488
1514
|
writeDeployArtifacts(config, nextGenerated);
|
|
@@ -1513,7 +1539,7 @@ async function cmdBootstrap() {
|
|
|
1513
1539
|
run("docker", ["stack", "deploy", "-c", BOOTSTRAP_STACK_FILE, config.services.stack_name]);
|
|
1514
1540
|
logSuccess("Runtime bootstrap stack deployed");
|
|
1515
1541
|
}
|
|
1516
|
-
waitForHttpService(config, "keycloak", "http://keycloak:
|
|
1542
|
+
waitForHttpService(config, "keycloak management readiness", "http://keycloak:9000/health/ready", 180);
|
|
1517
1543
|
waitForHttpService(config, "openfga", "http://openfga:8090/stores");
|
|
1518
1544
|
waitForTcpService(config, "minikms", "minikms", 50051);
|
|
1519
1545
|
const initResult = runBootstrapInit(config);
|
|
@@ -1770,9 +1796,10 @@ async function main() {
|
|
|
1770
1796
|
const command = argv[0];
|
|
1771
1797
|
const args = argv.slice(1);
|
|
1772
1798
|
currentOptions = {
|
|
1773
|
-
dryRun: args.includes("--dry-run")
|
|
1799
|
+
dryRun: args.includes("--dry-run"),
|
|
1800
|
+
force: args.includes("--force")
|
|
1774
1801
|
};
|
|
1775
|
-
const positionals = args.filter((arg) => arg !== "--dry-run");
|
|
1802
|
+
const positionals = args.filter((arg) => arg !== "--dry-run" && arg !== "--force");
|
|
1776
1803
|
switch (command) {
|
|
1777
1804
|
case "preinstall":
|
|
1778
1805
|
await cmdPreinstall();
|
|
@@ -1803,7 +1830,7 @@ async function main() {
|
|
|
1803
1830
|
break;
|
|
1804
1831
|
default:
|
|
1805
1832
|
console.log(
|
|
1806
|
-
"Usage: envsync-deploy <preinstall|setup|bootstrap|deploy|health|upgrade|upgrade-deps|backup|restore> [--dry-run]"
|
|
1833
|
+
"Usage: envsync-deploy <preinstall|setup|bootstrap|deploy|health|upgrade|upgrade-deps|backup|restore> [--dry-run] [--force]"
|
|
1807
1834
|
);
|
|
1808
1835
|
process.exit(command ? 1 : 0);
|
|
1809
1836
|
}
|