@envsync-cloud/deploy-cli 0.6.11 → 0.6.12

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 +37 -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,14 @@ ${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
+ test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8080 || exit 1"]
972
+ interval: 30s
973
+ timeout: 10s
974
+ retries: 10
975
+ start_period: 180s
960
976
 
961
977
  otel-agent:
962
978
  image: ${config.images.otel_agent}
@@ -1026,6 +1042,7 @@ function writeDeployArtifacts(config, generated) {
1026
1042
  writeFileMaybe(NGINX_WEB_CONF, renderNginxConf("web"));
1027
1043
  writeFileMaybe(NGINX_LANDING_CONF, renderNginxConf("landing"));
1028
1044
  writeFileMaybe(OTEL_AGENT_CONF, renderOtelAgentConfig(config));
1045
+ writeFileMaybe(CLICKSTACK_CLICKHOUSE_CONF, renderClickstackClickHouseConfig());
1029
1046
  logSuccess(currentOptions.dryRun ? "Deploy artifacts previewed" : "Deploy artifacts written");
1030
1047
  }
1031
1048
  function saveDesiredConfig(config) {
@@ -1172,51 +1189,6 @@ function waitForHttpService(config, label, url, timeoutSeconds = 120) {
1172
1189
  }
1173
1190
  throw new Error(`Timed out waiting for ${label} at ${url}`);
1174
1191
  }
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
1192
  function runOpenFgaMigrate(config, runtimeEnv) {
1221
1193
  logStep("Running OpenFGA datastore migrations");
1222
1194
  if (currentOptions.dryRun) {
@@ -1351,13 +1323,24 @@ function runClickstackBootstrap(config) {
1351
1323
  logCommand("node", [path.join(REPO_ROOT, "scripts/bootstrap-clickstack-selfhost.mjs")]);
1352
1324
  return;
1353
1325
  }
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
1326
+ const deadline = Date.now() + 180 * 1e3;
1327
+ let lastError = "unknown error";
1328
+ while (Date.now() < deadline) {
1329
+ try {
1330
+ run("node", [path.join(REPO_ROOT, "scripts/bootstrap-clickstack-selfhost.mjs")], {
1331
+ env: {
1332
+ ENVSYNC_STACK_NAME: config.services.stack_name,
1333
+ ENVSYNC_ROOT_DOMAIN: config.domain.root_domain
1334
+ }
1335
+ });
1336
+ logSuccess("ClickStack self-host bootstrap completed");
1337
+ return;
1338
+ } catch (error) {
1339
+ lastError = error instanceof Error ? error.message : String(error);
1340
+ sleepSeconds(3);
1358
1341
  }
1359
- });
1360
- logSuccess("ClickStack self-host bootstrap completed");
1342
+ }
1343
+ throw new Error(`Timed out bootstrapping ClickStack: ${lastError}`);
1361
1344
  }
1362
1345
  function parseBootstrapInitJson(output) {
1363
1346
  const trimmed = output.trim();
@@ -1685,7 +1668,7 @@ async function cmdBootstrap() {
1685
1668
  waitForHttpService(config, "keycloak management readiness", "http://keycloak:9000/health/ready", 180);
1686
1669
  waitForHttpService(config, "openfga", "http://openfga:8090/stores");
1687
1670
  waitForTcpService(config, "minikms", "minikms", 50051);
1688
- waitForContainerHealth(config, "clickstack", "clickstack container health");
1671
+ waitForHttpService(config, "clickstack ui", "http://clickstack:8080", 180);
1689
1672
  const initResult = runBootstrapInit(config);
1690
1673
  const persistedGenerated = normalizeGeneratedState({
1691
1674
  openfga: {
@@ -1921,6 +1904,7 @@ async function cmdBackup() {
1921
1904
  writeFile(path.join(staged, "traefik-dynamic.yaml"), fs.readFileSync(TRAEFIK_DYNAMIC_FILE, "utf8"));
1922
1905
  writeFile(path.join(staged, "keycloak-realm.envsync.json"), fs.readFileSync(KEYCLOAK_REALM_FILE, "utf8"));
1923
1906
  writeFile(path.join(staged, "otel-agent.yaml"), fs.readFileSync(OTEL_AGENT_CONF, "utf8"));
1907
+ writeFile(path.join(staged, "clickhouse-listen.xml"), fs.readFileSync(CLICKSTACK_CLICKHOUSE_CONF, "utf8"));
1924
1908
  const volumesDir = path.join(staged, "volumes");
1925
1909
  for (const volume of STACK_VOLUMES) {
1926
1910
  backupDockerVolume(stackVolumeName(config, volume), path.join(volumesDir, volume));
@@ -1961,6 +1945,7 @@ async function cmdRestore(archivePath) {
1961
1945
  writeFile(TRAEFIK_DYNAMIC_FILE, fs.readFileSync(path.join(restoreRoot, "traefik-dynamic.yaml"), "utf8"));
1962
1946
  writeFile(KEYCLOAK_REALM_FILE, fs.readFileSync(path.join(restoreRoot, "keycloak-realm.envsync.json"), "utf8"));
1963
1947
  writeFile(OTEL_AGENT_CONF, fs.readFileSync(path.join(restoreRoot, "otel-agent.yaml"), "utf8"));
1948
+ writeFile(CLICKSTACK_CLICKHOUSE_CONF, fs.readFileSync(path.join(restoreRoot, "clickhouse-listen.xml"), "utf8"));
1964
1949
  const config = loadConfig();
1965
1950
  for (const volume of STACK_VOLUMES) {
1966
1951
  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.12",
4
4
  "description": "CLI for self-hosted EnvSync deployment on Docker Swarm",
5
5
  "type": "module",
6
6
  "bin": {