@keepur/hive 0.2.5 → 0.2.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.
@@ -16,7 +16,10 @@ set -euo pipefail
16
16
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
17
17
  BUILD_DIR="${BUILD_DIR:-$HOME/build/hive}"
18
18
  DEPLOY_DIR="${DEPLOY_DIR:-$HOME/services/hive}"
19
- INSTANCES_CONF="$SCRIPT_DIR/instances.conf"
19
+ # HIVE_INSTANCES_CONF (KPR-70) lets multi-instance dev hosts point at a
20
+ # workspace-level conf outside .hive/, so engine swaps don't wipe their
21
+ # registry. The shipped $SCRIPT_DIR/instances.conf is empty by design.
22
+ INSTANCES_CONF="${HIVE_INSTANCES_CONF:-$SCRIPT_DIR/instances.conf}"
20
23
 
21
24
  cd "$BUILD_DIR"
22
25
  [[ "$(git branch --show-current)" == "deploy" ]] || { echo "ERROR: Build dir not on deploy branch"; exit 1; }
@@ -25,6 +28,11 @@ echo "Checking for updates on deploy branch..."
25
28
  git fetch origin deploy --quiet
26
29
 
27
30
  # --- Load instances ---
31
+ if [[ ! -f "$INSTANCES_CONF" ]]; then
32
+ echo "ERROR: instances.conf not found at $INSTANCES_CONF"
33
+ echo " Set HIVE_INSTANCES_CONF to a workspace-level conf outside .hive/."
34
+ exit 1
35
+ fi
28
36
  declare -a INSTANCES=()
29
37
  while IFS='|' read -r id config _agents _label logs_dir ports engine_tag; do
30
38
  [[ "$id" =~ ^[[:space:]]*# ]] && continue
@@ -34,6 +42,12 @@ while IFS='|' read -r id config _agents _label logs_dir ports engine_tag; do
34
42
  INSTANCES+=("$id|${engine_tag:-latest}")
35
43
  done < "$INSTANCES_CONF"
36
44
 
45
+ if [[ ${#INSTANCES[@]} -eq 0 ]]; then
46
+ echo "No instances registered in $INSTANCES_CONF — nothing to check."
47
+ echo "(The shipped service/instances.conf is empty by design; multi-instance dev hosts must use HIVE_INSTANCES_CONF.)"
48
+ exit 0
49
+ fi
50
+
37
51
  UPDATES_NEEDED=()
38
52
  for inst in "${INSTANCES[@]}"; do
39
53
  IFS='|' read -r id tag <<< "$inst"
package/service/deploy.sh CHANGED
@@ -9,7 +9,16 @@ set -euo pipefail
9
9
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
10
  BUILD_DIR="${BUILD_DIR:-$HOME/build/hive}"
11
11
  DEPLOY_DIR="${DEPLOY_DIR:-$HOME/services/hive}"
12
- INSTANCES_CONF="$SCRIPT_DIR/instances.conf"
12
+ INSTANCES_CONF="${HIVE_INSTANCES_CONF:-$SCRIPT_DIR/instances.conf}"
13
+
14
+ # Single-instance mode (KPR-70): when invoked by `hive update` for a customer
15
+ # install, the calling instance passes its own facts via env, and we skip the
16
+ # build-from-source phase + the shipped instances.conf entirely. The instance
17
+ # running the update is the only instance to update — no global registry read.
18
+ SINGLE_INSTANCE_MODE=false
19
+ if [[ "${HIVE_SINGLE_INSTANCE:-}" == "1" ]]; then
20
+ SINGLE_INSTANCE_MODE=true
21
+ fi
13
22
 
14
23
  # --- Flags ---
15
24
  DRY_RUN=false
@@ -30,30 +39,48 @@ for arg in "$@"; do
30
39
  esac
31
40
  done
32
41
 
33
- # --- Notification config (from dodi's .env — the primary instance) ---
34
- # shellcheck source=/dev/null
35
- source "$DEPLOY_DIR/.env"
36
- : "${SLACK_BOT_TOKEN:?SLACK_BOT_TOKEN not set in .env}"
37
- : "${DEVOPS_CHANNEL_ID:?DEVOPS_CHANNEL_ID not set in .env}"
42
+ # --- Notification config ---
43
+ # Source $DEPLOY_DIR/.env if present so SLACK_BOT_TOKEN / DEVOPS_CHANNEL_ID
44
+ # can populate from the dev convention. Customer installs have neither file
45
+ # nor tokens that's fine; notify() degrades to a silent no-op below.
46
+ if [[ -f "$DEPLOY_DIR/.env" ]]; then
47
+ # shellcheck source=/dev/null
48
+ source "$DEPLOY_DIR/.env"
49
+ fi
38
50
 
39
51
  # --- Load instances ---
40
52
  declare -a INSTANCES=()
41
- while IFS='|' read -r id config _agents_path label logs_dir ports engine_tag; do
42
- [[ "$id" =~ ^[[:space:]]*# ]] && continue # skip comments
43
- [[ -z "$id" ]] && continue # skip blank lines
44
- # Trim whitespace
45
- id=$(echo "$id" | xargs)
46
- config=$(echo "$config" | xargs)
47
- label=$(echo "$label" | xargs)
48
- logs_dir=$(echo "$logs_dir" | xargs)
49
- ports=$(echo "$ports" | xargs)
50
- engine_tag=$(echo "${engine_tag:-}" | xargs)
51
- INSTANCES+=("$id|$config|$label|$logs_dir|$ports|$engine_tag")
52
- done < "$INSTANCES_CONF"
53
-
54
- if [[ ${#INSTANCES[@]} -eq 0 ]]; then
55
- echo "ERROR: No instances found in $INSTANCES_CONF"
56
- exit 1
53
+ if $SINGLE_INSTANCE_MODE; then
54
+ : "${HIVE_SINGLE_ID:?HIVE_SINGLE_ID required in single-instance mode}"
55
+ : "${HIVE_SINGLE_CONFIG:?HIVE_SINGLE_CONFIG required in single-instance mode}"
56
+ : "${HIVE_SINGLE_LOGS:?HIVE_SINGLE_LOGS required in single-instance mode}"
57
+ : "${HIVE_SINGLE_PORTS:?HIVE_SINGLE_PORTS required in single-instance mode}"
58
+ : "${HIVE_SINGLE_ROOT:?HIVE_SINGLE_ROOT required in single-instance mode}"
59
+ INSTANCES+=("$HIVE_SINGLE_ID|$HIVE_SINGLE_CONFIG|com.hive.${HIVE_SINGLE_ID}.agent|$HIVE_SINGLE_LOGS|$HIVE_SINGLE_PORTS|${HIVE_SINGLE_TAG:-}")
60
+ else
61
+ if [[ ! -f "$INSTANCES_CONF" ]]; then
62
+ echo "ERROR: instances.conf not found at $INSTANCES_CONF"
63
+ echo " For single-instance updates, set HIVE_SINGLE_INSTANCE=1 and the HIVE_SINGLE_* env vars."
64
+ echo " For multi-instance dev, point HIVE_INSTANCES_CONF at a workspace-level conf."
65
+ exit 1
66
+ fi
67
+ while IFS='|' read -r id config _agents_path label logs_dir ports engine_tag; do
68
+ [[ "$id" =~ ^[[:space:]]*# ]] && continue # skip comments
69
+ [[ -z "$id" ]] && continue # skip blank lines
70
+ # Trim whitespace
71
+ id=$(echo "$id" | xargs)
72
+ config=$(echo "$config" | xargs)
73
+ label=$(echo "$label" | xargs)
74
+ logs_dir=$(echo "$logs_dir" | xargs)
75
+ ports=$(echo "$ports" | xargs)
76
+ engine_tag=$(echo "${engine_tag:-}" | xargs)
77
+ INSTANCES+=("$id|$config|$label|$logs_dir|$ports|$engine_tag")
78
+ done < "$INSTANCES_CONF"
79
+
80
+ if [[ ${#INSTANCES[@]} -eq 0 ]]; then
81
+ echo "ERROR: No instances found in $INSTANCES_CONF"
82
+ exit 1
83
+ fi
57
84
  fi
58
85
 
59
86
  echo "=== Hive Deploy (${#INSTANCES[@]} instances) ==="
@@ -76,6 +103,11 @@ notify() {
76
103
  echo "[DRY RUN] notify: $message"
77
104
  return
78
105
  fi
106
+ # Slack notification is opt-in. Customer installs without devops Slack
107
+ # tokens silently skip — never fail-closed on a missing notification config.
108
+ if [[ -z "${SLACK_BOT_TOKEN:-}" || -z "${DEVOPS_CHANNEL_ID:-}" ]]; then
109
+ return
110
+ fi
79
111
  local payload
80
112
  payload=$(jq -n --arg channel "$DEVOPS_CHANNEL_ID" --arg text "$message" \
81
113
  '{channel: $channel, text: $text}')
@@ -132,12 +164,17 @@ _normalize_tag() {
132
164
  }
133
165
 
134
166
  # _instance_root <id>
135
- # Returns the instance root dir: $DEPLOY_DIR/<id> if that dir exists (post-Phase-5
136
- # per-instance layout), else $DEPLOY_DIR (today's primary-shared-dir layout).
137
- # Lets deploy.sh be per-instance-dir aware now so Phase 5's migration is a no-op
138
- # at the script level.
167
+ # Returns the instance root dir. In single-instance mode (KPR-70) the caller
168
+ # tells us via HIVE_SINGLE_ROOT — we don't probe DEPLOY_DIR. Otherwise:
169
+ # $DEPLOY_DIR/<id> if that dir exists (post-Phase-5 per-instance layout), else
170
+ # $DEPLOY_DIR (today's primary-shared-dir layout). Lets deploy.sh be
171
+ # per-instance-dir aware now so Phase 5's migration is a no-op at the script level.
139
172
  _instance_root() {
140
173
  local id="$1"
174
+ if $SINGLE_INSTANCE_MODE; then
175
+ echo "$HIVE_SINGLE_ROOT"
176
+ return
177
+ fi
141
178
  if [[ -d "$DEPLOY_DIR/$id" ]]; then
142
179
  echo "$DEPLOY_DIR/$id"
143
180
  else
@@ -330,62 +367,76 @@ fi
330
367
  # oscillates between versions on every poll. Compares the configured pins
331
368
  # (not the effective tag for this run) so even an explicit --tag override
332
369
  # can't sneak past a misconfigured pinning state. Fail fast before any work.
333
- declare -a _seen_roots=()
334
- declare -a _seen_pins=()
335
- for inst in "${INSTANCES[@]}"; do
336
- IFS='|' read -r _id _config _label _logs _ports _engine_tag <<< "$inst"
337
- _root=$(_instance_root "$_id")
338
- _pin="${_engine_tag:-latest}"
339
- for i in "${!_seen_roots[@]}"; do
340
- if [[ "${_seen_roots[$i]}" == "$_root" && "${_seen_pins[$i]}" != "$_pin" ]]; then
341
- echo "ERROR: instances share root '$_root' but pin different ENGINE_TAGs ('${_seen_pins[$i]}' vs '$_pin')." >&2
342
- echo " Set the same ENGINE_TAG for all instances under one root, or migrate them to per-instance dirs (Phase 5)." >&2
343
- exit 2
344
- fi
370
+ # Skipped in single-instance mode: one row can't conflict with itself.
371
+ if ! $SINGLE_INSTANCE_MODE; then
372
+ declare -a _seen_roots=()
373
+ declare -a _seen_pins=()
374
+ for inst in "${INSTANCES[@]}"; do
375
+ IFS='|' read -r _id _config _label _logs _ports _engine_tag <<< "$inst"
376
+ _root=$(_instance_root "$_id")
377
+ _pin="${_engine_tag:-latest}"
378
+ for i in "${!_seen_roots[@]}"; do
379
+ if [[ "${_seen_roots[$i]}" == "$_root" && "${_seen_pins[$i]}" != "$_pin" ]]; then
380
+ echo "ERROR: instances share root '$_root' but pin different ENGINE_TAGs ('${_seen_pins[$i]}' vs '$_pin')." >&2
381
+ echo " Set the same ENGINE_TAG for all instances under one root, or migrate them to per-instance dirs (Phase 5)." >&2
382
+ exit 2
383
+ fi
384
+ done
385
+ _seen_roots+=("$_root")
386
+ _seen_pins+=("$_pin")
345
387
  done
346
- _seen_roots+=("$_root")
347
- _seen_pins+=("$_pin")
348
- done
349
- unset _seen_roots _seen_pins _id _config _label _logs _ports _engine_tag _root _pin i
388
+ unset _seen_roots _seen_pins _id _config _label _logs _ports _engine_tag _root _pin i
389
+ fi
350
390
 
351
391
  # =============================================================================
352
392
  # Phase 1: Build (once, in $BUILD_DIR)
353
393
  # =============================================================================
394
+ # Skipped in single-instance mode (KPR-70): customer installs consume the
395
+ # published @keepur/hive npm tarball via fetch_engine in Phase 2 — there is no
396
+ # $BUILD_DIR, no `deploy` branch, nothing to rebuild from source.
354
397
 
355
- echo ""
356
- echo "--- Phase 1: Build ---"
357
- # Per-instance current versions are reported in Phase 2 after each health check.
398
+ DEPLOY_SHA=""
399
+ DEPLOY_MSG=""
400
+
401
+ if $SINGLE_INSTANCE_MODE; then
402
+ echo ""
403
+ echo "--- Phase 1: Build (skipped in single-instance mode) ---"
404
+ else
405
+ echo ""
406
+ echo "--- Phase 1: Build ---"
407
+ # Per-instance current versions are reported in Phase 2 after each health check.
358
408
 
359
- echo "Pulling latest in build dir..."
360
- cd "$BUILD_DIR"
361
- [[ "$(git branch --show-current)" == "deploy" ]] || { echo "ERROR: Build dir not on deploy branch"; exit 1; }
362
- run_cmd git pull --ff-only
409
+ echo "Pulling latest in build dir..."
410
+ cd "$BUILD_DIR"
411
+ [[ "$(git branch --show-current)" == "deploy" ]] || { echo "ERROR: Build dir not on deploy branch"; exit 1; }
412
+ run_cmd git pull --ff-only
363
413
 
364
- DEPLOY_SHA=$(git rev-parse --short HEAD)
365
- DEPLOY_MSG=$(git log -1 --pretty=%s)
414
+ DEPLOY_SHA=$(git rev-parse --short HEAD)
415
+ DEPLOY_MSG=$(git log -1 --pretty=%s)
366
416
 
367
- echo "Installing dependencies..."
368
- if ! run_cmd npm install; then
369
- notify "Deploy aborted. \`npm install\` failed. Commit: \`$DEPLOY_SHA\`."
370
- exit 1
371
- fi
417
+ echo "Installing dependencies..."
418
+ if ! run_cmd npm install; then
419
+ notify "Deploy aborted. \`npm install\` failed. Commit: \`$DEPLOY_SHA\`."
420
+ exit 1
421
+ fi
372
422
 
373
- echo "Running checks..."
374
- if ! run_cmd npm run check; then
375
- notify "Deploy aborted. \`npm run check\` failed. Commit: \`$DEPLOY_SHA\`."
376
- exit 1
377
- fi
423
+ echo "Running checks..."
424
+ if ! run_cmd npm run check; then
425
+ notify "Deploy aborted. \`npm run check\` failed. Commit: \`$DEPLOY_SHA\`."
426
+ exit 1
427
+ fi
378
428
 
379
- echo "Building..."
380
- if ! run_cmd npm run build; then
381
- notify "Deploy aborted. Build failed. Commit: \`$DEPLOY_SHA\`."
382
- exit 1
383
- fi
429
+ echo "Building..."
430
+ if ! run_cmd npm run build; then
431
+ notify "Deploy aborted. Build failed. Commit: \`$DEPLOY_SHA\`."
432
+ exit 1
433
+ fi
384
434
 
385
- echo "Bundling..."
386
- if ! run_cmd npm run bundle; then
387
- notify "Deploy aborted. Bundle failed. Commit: \`$DEPLOY_SHA\`."
388
- exit 1
435
+ echo "Bundling..."
436
+ if ! run_cmd npm run bundle; then
437
+ notify "Deploy aborted. Bundle failed. Commit: \`$DEPLOY_SHA\`."
438
+ exit 1
439
+ fi
389
440
  fi
390
441
 
391
442
  # =============================================================================
@@ -467,16 +518,22 @@ done
467
518
  echo ""
468
519
  echo "--- Phase 3: Report ---"
469
520
 
521
+ # Build-commit clause appears only in multi-instance mode (Phase 1 ran).
522
+ build_clause=""
523
+ if [[ -n "$DEPLOY_SHA" ]]; then
524
+ build_clause=" Build commit \`$DEPLOY_SHA\`: $DEPLOY_MSG."
525
+ fi
526
+
470
527
  if [[ ${#FAILED_INSTANCES[@]} -gt 0 ]]; then
471
528
  failed_list=$(printf ", %s" "${FAILED_INSTANCES[@]}")
472
529
  failed_list=${failed_list:2}
473
- notify "Deploy partial. Build commit \`$DEPLOY_SHA\`: $DEPLOY_MSG. Failed instances: $failed_list."
530
+ notify "Deploy partial.${build_clause} Failed instances: $failed_list."
474
531
  echo "Deploy completed with failures: $failed_list"
475
532
  exit 1
476
533
  else
477
534
  # Count actual deploy targets (respecting --instance filter)
478
535
  deployed=${#INSTANCES[@]}
479
536
  [[ -n "$FILTER_INSTANCE" ]] && deployed=1
480
- notify "Deploy succeeded ($deployed instance(s)). Build commit \`$DEPLOY_SHA\`: $DEPLOY_MSG."
537
+ notify "Deploy succeeded ($deployed instance(s)).${build_clause}"
481
538
  echo "Deploy complete. $deployed instance(s) running."
482
539
  fi
@@ -1,4 +1,19 @@
1
- # Hive instance definitions — one per line
1
+ # Hive instance definitions — multi-instance dev deploy registry
2
+ #
3
+ # THIS FILE SHIPS EMPTY in the @keepur/hive npm bundle.
4
+ #
5
+ # Customer installs do NOT use this file: `hive update` uses the
6
+ # single-instance code path (HIVE_SINGLE_INSTANCE=1) and discovers the calling
7
+ # instance from cwd / hive.yaml / HIVE_HOME — no registry read.
8
+ #
9
+ # Multi-instance dev hosts (one machine running several Hive instances) point
10
+ # the cron-driven deploy-check.sh at a workspace-level conf instead, via:
11
+ #
12
+ # HIVE_INSTANCES_CONF=/path/to/instances.conf
13
+ #
14
+ # That conf lives outside .hive/ so engine swaps don't wipe it.
15
+ #
16
+ # --- Format (when this file IS used) ---
2
17
  # Fields: INSTANCE_ID | HIVE_CONFIG | (unused) | (unused label — advisory) | LOGS_DIR | PORTS (space-separated) | ENGINE_TAG
3
18
  #
4
19
  # HIVE_CONFIG is relative to DEPLOY_DIR
@@ -10,6 +25,6 @@
10
25
  # The fourth column was historically the LaunchAgent label but is now ignored by
11
26
  # deploy.sh — the label is always derived as com.hive.<INSTANCE_ID>.agent to match
12
27
  # what service/install.sh produces. The column is retained for format stability.
13
-
14
- dodi|hive.yaml|-|com.hive.dodi.agent|logs|3100 3200|v0.2.0
15
- personal|hive-personal.yaml|-|com.hive.personal.agent|logs-personal|3400 3403|v0.2.0
28
+ #
29
+ # Example row (commented — do not enable in the shipped bundle):
30
+ # example|hive.yaml|-|com.hive.example.agent|logs|3100 3200|latest