@envsync-cloud/deploy-cli 0.6.11 → 0.6.13

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 (2) hide show
  1. package/dist/index.js +33 -52
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ var KEYCLOAK_REALM_FILE = "/opt/envsync/deploy/keycloak-realm.envsync.json";
25
25
  var NGINX_WEB_CONF = "/opt/envsync/deploy/nginx-web.conf";
26
26
  var NGINX_LANDING_CONF = "/opt/envsync/deploy/nginx-landing.conf";
27
27
  var OTEL_AGENT_CONF = "/opt/envsync/deploy/otel-agent.yaml";
28
+ var CLICKSTACK_CLICKHOUSE_CONF = "/opt/envsync/deploy/clickhouse-listen.xml";
28
29
  var INTERNAL_CONFIG_JSON = "/opt/envsync/deploy/config.json";
29
30
  var STACK_VOLUMES = [
30
31
  "postgres_data",
@@ -757,6 +758,14 @@ function renderOtelAgentConfig(config) {
757
758
  " exporters: [otlphttp/clickstack]"
758
759
  ].join("\n") + "\n";
759
760
  }
761
+ function renderClickstackClickHouseConfig() {
762
+ return [
763
+ "<clickhouse>",
764
+ " <listen_host>0.0.0.0</listen_host>",
765
+ " <listen_try>1</listen_try>",
766
+ "</clickhouse>"
767
+ ].join("\n") + "\n";
768
+ }
760
769
  function renderStack(config, runtimeEnv, mode) {
761
770
  const hosts = domainMap(config.domain.root_domain);
762
771
  const includeRuntimeInfra = mode !== "base";
@@ -956,7 +965,10 @@ ${renderEnvList({
956
965
  - clickstack_data:/data/db
957
966
  - clickstack_ch_data:/var/lib/clickhouse
958
967
  - clickstack_ch_logs:/var/log/clickhouse-server
968
+ - ${CLICKSTACK_CLICKHOUSE_CONF}:/etc/clickhouse-server/config.d/envsync-listen-host.xml:ro
959
969
  networks: [envsync]
970
+ healthcheck:
971
+ disable: true
960
972
 
961
973
  otel-agent:
962
974
  image: ${config.images.otel_agent}
@@ -1026,6 +1038,7 @@ function writeDeployArtifacts(config, generated) {
1026
1038
  writeFileMaybe(NGINX_WEB_CONF, renderNginxConf("web"));
1027
1039
  writeFileMaybe(NGINX_LANDING_CONF, renderNginxConf("landing"));
1028
1040
  writeFileMaybe(OTEL_AGENT_CONF, renderOtelAgentConfig(config));
1041
+ writeFileMaybe(CLICKSTACK_CLICKHOUSE_CONF, renderClickstackClickHouseConfig());
1029
1042
  logSuccess(currentOptions.dryRun ? "Deploy artifacts previewed" : "Deploy artifacts written");
1030
1043
  }
1031
1044
  function saveDesiredConfig(config) {
@@ -1172,51 +1185,6 @@ function waitForHttpService(config, label, url, timeoutSeconds = 120) {
1172
1185
  }
1173
1186
  throw new Error(`Timed out waiting for ${label} at ${url}`);
1174
1187
  }
1175
- function serviceContainerId(config, serviceName) {
1176
- const output = tryRun(
1177
- "docker",
1178
- [
1179
- "ps",
1180
- "--filter",
1181
- `label=com.docker.swarm.service.name=${config.services.stack_name}_${serviceName}`,
1182
- "--format",
1183
- "{{.ID}}"
1184
- ],
1185
- { quiet: true }
1186
- );
1187
- return output.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "";
1188
- }
1189
- function waitForContainerHealth(config, serviceName, label, timeoutSeconds = 180) {
1190
- if (currentOptions.dryRun) {
1191
- logDryRun(`Would wait for ${label}`);
1192
- return;
1193
- }
1194
- logStep(`Waiting for ${label}`);
1195
- const deadline = Date.now() + timeoutSeconds * 1e3;
1196
- while (Date.now() < deadline) {
1197
- const containerId = serviceContainerId(config, serviceName);
1198
- if (!containerId) {
1199
- sleepSeconds(2);
1200
- continue;
1201
- }
1202
- const health = tryRun(
1203
- "docker",
1204
- [
1205
- "inspect",
1206
- "--format",
1207
- "{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}",
1208
- containerId
1209
- ],
1210
- { quiet: true }
1211
- ).trim();
1212
- if (health === "healthy" || health === "running") {
1213
- logSuccess(`${label} is ready`);
1214
- return;
1215
- }
1216
- sleepSeconds(2);
1217
- }
1218
- throw new Error(`Timed out waiting for ${label}`);
1219
- }
1220
1188
  function runOpenFgaMigrate(config, runtimeEnv) {
1221
1189
  logStep("Running OpenFGA datastore migrations");
1222
1190
  if (currentOptions.dryRun) {
@@ -1351,13 +1319,24 @@ function runClickstackBootstrap(config) {
1351
1319
  logCommand("node", [path.join(REPO_ROOT, "scripts/bootstrap-clickstack-selfhost.mjs")]);
1352
1320
  return;
1353
1321
  }
1354
- run("node", [path.join(REPO_ROOT, "scripts/bootstrap-clickstack-selfhost.mjs")], {
1355
- env: {
1356
- ENVSYNC_STACK_NAME: config.services.stack_name,
1357
- ENVSYNC_ROOT_DOMAIN: config.domain.root_domain
1322
+ const deadline = Date.now() + 180 * 1e3;
1323
+ let lastError = "unknown error";
1324
+ while (Date.now() < deadline) {
1325
+ try {
1326
+ run("node", [path.join(REPO_ROOT, "scripts/bootstrap-clickstack-selfhost.mjs")], {
1327
+ env: {
1328
+ ENVSYNC_STACK_NAME: config.services.stack_name,
1329
+ ENVSYNC_ROOT_DOMAIN: config.domain.root_domain
1330
+ }
1331
+ });
1332
+ logSuccess("ClickStack self-host bootstrap completed");
1333
+ return;
1334
+ } catch (error) {
1335
+ lastError = error instanceof Error ? error.message : String(error);
1336
+ sleepSeconds(3);
1358
1337
  }
1359
- });
1360
- logSuccess("ClickStack self-host bootstrap completed");
1338
+ }
1339
+ throw new Error(`Timed out bootstrapping ClickStack: ${lastError}`);
1361
1340
  }
1362
1341
  function parseBootstrapInitJson(output) {
1363
1342
  const trimmed = output.trim();
@@ -1685,7 +1664,7 @@ async function cmdBootstrap() {
1685
1664
  waitForHttpService(config, "keycloak management readiness", "http://keycloak:9000/health/ready", 180);
1686
1665
  waitForHttpService(config, "openfga", "http://openfga:8090/stores");
1687
1666
  waitForTcpService(config, "minikms", "minikms", 50051);
1688
- waitForContainerHealth(config, "clickstack", "clickstack container health");
1667
+ waitForTcpService(config, "clickstack ui", "clickstack", 8080, 180);
1689
1668
  const initResult = runBootstrapInit(config);
1690
1669
  const persistedGenerated = normalizeGeneratedState({
1691
1670
  openfga: {
@@ -1921,6 +1900,7 @@ async function cmdBackup() {
1921
1900
  writeFile(path.join(staged, "traefik-dynamic.yaml"), fs.readFileSync(TRAEFIK_DYNAMIC_FILE, "utf8"));
1922
1901
  writeFile(path.join(staged, "keycloak-realm.envsync.json"), fs.readFileSync(KEYCLOAK_REALM_FILE, "utf8"));
1923
1902
  writeFile(path.join(staged, "otel-agent.yaml"), fs.readFileSync(OTEL_AGENT_CONF, "utf8"));
1903
+ writeFile(path.join(staged, "clickhouse-listen.xml"), fs.readFileSync(CLICKSTACK_CLICKHOUSE_CONF, "utf8"));
1924
1904
  const volumesDir = path.join(staged, "volumes");
1925
1905
  for (const volume of STACK_VOLUMES) {
1926
1906
  backupDockerVolume(stackVolumeName(config, volume), path.join(volumesDir, volume));
@@ -1961,6 +1941,7 @@ async function cmdRestore(archivePath) {
1961
1941
  writeFile(TRAEFIK_DYNAMIC_FILE, fs.readFileSync(path.join(restoreRoot, "traefik-dynamic.yaml"), "utf8"));
1962
1942
  writeFile(KEYCLOAK_REALM_FILE, fs.readFileSync(path.join(restoreRoot, "keycloak-realm.envsync.json"), "utf8"));
1963
1943
  writeFile(OTEL_AGENT_CONF, fs.readFileSync(path.join(restoreRoot, "otel-agent.yaml"), "utf8"));
1944
+ writeFile(CLICKSTACK_CLICKHOUSE_CONF, fs.readFileSync(path.join(restoreRoot, "clickhouse-listen.xml"), "utf8"));
1964
1945
  const config = loadConfig();
1965
1946
  for (const volume of STACK_VOLUMES) {
1966
1947
  restoreDockerVolume(stackVolumeName(config, volume), path.join(restoreRoot, "volumes", volume));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envsync-cloud/deploy-cli",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "CLI for self-hosted EnvSync deployment on Docker Swarm",
5
5
  "type": "module",
6
6
  "bin": {