#!/usr/bin/env bash # Sync service variables from the local .env to the server — now and for every future deploy. # make env-sync (or infra/deploy/env-sync.sh [path/to/.env]) # 1. Filters the local env: drops GITEA_*, empty values and server-managed keys (DB passwords, PSEUDO_KEY, URLs). # 2. Stores the result as the Gitea Actions secret SERVICE_ENV → CD merges it into /srv/ptsr/.env on each deploy. # 3. Applies it on the server right away and recreates app + dashboard if anything changed. # Values are never printed; only key names. set -euo pipefail SRC=${1:-.env} HOST=${DEPLOY_HOST:-vobot} OPTS=${DEPLOY_SSH_OPTS:-} DIR=/srv/ptsr HERE=$(cd "$(dirname "$0")" && pwd) [ -f "$SRC" ] || { echo "no $SRC"; exit 1; } # Values without inline comments / trailing spaces ("KEY=value # коммент" → "value"). val() { grep -E "^$1=" "$SRC" | tail -1 | cut -d= -f2- | sed -E 's/[[:space:]]+#.*$//; s/[[:space:]]+$//' || true; } GITEA_URL=$(val GITEA_URL) GITEA_REPO=$(val GITEA_REPO) GITEA_TOKEN=$(val GITEA_TOKEN) export GITEA_URL GITEA_REPO GITEA_TOKEN OUT=$(mktemp) trap 'rm -f "$OUT"' EXIT sed -E 's/[[:space:]]+#.*$//; s/[[:space:]]+$//' "$SRC" \ | grep -E '^[A-Z_][A-Z0-9_]*=.+' \ | grep -vE '^(GITEA_[A-Z_]*|POSTGRES_PASSWORD|IDENTITY_DB_PASSWORD|CLINICAL_DB_PASSWORD|PSEUDO_KEY|PUBLIC_URL|IDENTITY_DB_URL|CLINICAL_DB_URL|API_BASE_URL)=' \ > "$OUT" || true echo "keys: $(cut -d= -f1 "$OUT" | tr '\n' ' ')" [ -s "$OUT" ] || { echo "nothing to sync"; exit 0; } if [ -n "$GITEA_TOKEN" ] && [ -n "$GITEA_URL" ] && [ -n "$GITEA_REPO" ]; then python3 - "$OUT" <<'PY' import json, os, sys, urllib.request url = f"{os.environ['GITEA_URL']}/api/v1/repos/{os.environ['GITEA_REPO']}/actions/secrets/SERVICE_ENV" body = json.dumps({"data": open(sys.argv[1]).read()}).encode() req = urllib.request.Request(url, method="PUT", data=body, headers={"Authorization": f"token {os.environ['GITEA_TOKEN']}", "Content-Type": "application/json"}) print("gitea secret SERVICE_ENV:", urllib.request.urlopen(req).status) PY else echo "GITEA_* not set in $SRC — skipping the CD secret (server-only sync)" fi retry() { local n=0; until "$@"; do n=$((n + 1)); [ $n -ge 5 ] && return 1; sleep $((n * 10)); done; } # shellcheck disable=SC2086 retry scp -q $OPTS "$OUT" "$HOST:$DIR/service.env" # shellcheck disable=SC2086 retry scp -q $OPTS "$HERE/env_merge.py" "$HOST:$DIR/env_merge.py" # shellcheck disable=SC2086 retry ssh $OPTS "$HOST" "bash -s" <&1 | tail -2 for i in \$(seq 1 30); do curl -sf 127.0.0.1:8010/health >/dev/null && break; sleep 2; done curl -sf 127.0.0.1:8010/health >/dev/null && echo "api ok" elif [ "\$rc" != 3 ]; then exit "\$rc" fi SH