diff --git a/services/nginx/app/resources/edge-gateway-agent/gateway-launcher.sh b/services/nginx/app/resources/edge-gateway-agent/gateway-launcher.sh index cd502c8a..8d73ebe9 100644 --- a/services/nginx/app/resources/edge-gateway-agent/gateway-launcher.sh +++ b/services/nginx/app/resources/edge-gateway-agent/gateway-launcher.sh @@ -64,6 +64,32 @@ config_value() { ' "$CONFIG_PATH" "$key" "$fallback" } +staged_update_value() { + local key="$1" + local fallback="${2:-}" + php -r ' + $path = $argv[1]; + $key = $argv[2]; + $fallback = $argv[3]; + if (!is_file($path)) { + echo $fallback; + exit(0); + } + $decoded = json_decode((string)file_get_contents($path), true); + if (!is_array($decoded) || !array_key_exists($key, $decoded) || $decoded[$key] === null || $decoded[$key] === "") { + echo $fallback; + exit(0); + } + echo is_scalar($decoded[$key]) ? (string)$decoded[$key] : json_encode($decoded[$key], JSON_UNESCAPED_SLASHES); + ' "$STAGED_UPDATE_PATH" "$key" "$fallback" +} + +staged_update_is_applied() { + local status + status="$(staged_update_value status '')" + [ "$status" = "APPLIED" ] +} + ensure_dirs() { mkdir -p "$RUNTIME_DIR" "$RUNTIME_DIR/backups" } @@ -106,7 +132,10 @@ ensure_stack_env() { within_update_window() { local window - window="$(config_value updateWindow '02:00-04:00')" + window="$(staged_update_value update_window '')" + if [ -z "$window" ]; then + window="$(config_value updateWindow '02:00-04:00')" + fi php -r ' $window = $argv[1]; [$start, $end] = array_pad(explode("-", $window, 2), 2, ""); @@ -286,6 +315,10 @@ case "$ACTION" in reconcile_stack ;; reconcile) + if [ -f "$STAGED_UPDATE_PATH" ] && staged_update_is_applied; then + log "Staged update already applied; nothing to reconcile" + exit 0 + fi if [ -f "$STAGED_UPDATE_PATH" ] && ! within_update_window; then log "Update is staged but outside the maintenance window; keeping current stack running" exit 0 diff --git a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayUpdateLifecycleTest.php b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayUpdateLifecycleTest.php index 28b06195..263a56d5 100644 --- a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayUpdateLifecycleTest.php +++ b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayUpdateLifecycleTest.php @@ -88,6 +88,9 @@ it('builds the installer around the compose stack artifacts and management polli expect($launcherSource)->toContain('ensure_stack_env'); expect($launcherSource)->toContain('REDIS_PASSWORD'); expect($launcherSource)->toContain('chmod 0600 "$ENV_FILE"'); + expect($launcherSource)->toContain('staged_update_value()'); + expect($launcherSource)->toContain('window="$(staged_update_value update_window \'\')"'); + expect($launcherSource)->toContain('Staged update already applied; nothing to reconcile'); expect($launcherSource)->toContain('AUTO_UPDATER_BASE_IMAGE="$auto_updater_base_image"'); expect($launcherSource)->toContain('COMPOSE_PROJECT_NAME="$compose_project_name" compose_cmd -f "$COMPOSE_FILE" ps || true'); expect($launcherSource)->toContain('COMPOSE_PROJECT_NAME="$compose_project_name" compose_cmd -f "$COMPOSE_FILE" logs --tail=80 || true');