File size: 2,916 Bytes
059ec0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════════
# sync-env.sh β€” Ensure .env has every key from .env.example
#
# Reads .env.example as the source of truth. For any key that is
# missing in the local .env, appends the .env.example value (or
# a placeholder) under the same section comment. Existing keys in
# .env are preserved (never overwritten) so secrets stay intact.
#
# Usage:
#   ./scripts/sync-env.sh                  # sync into .env
#   ./scripts/sync-env.sh --check          # report missing keys only
#   ./scripts/sync-env.sh --target .env.production
# ═══════════════════════════════════════════════════════════════

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
EXAMPLE="${REPO_ROOT}/.env.example"
COOLIFY="${REPO_ROOT}/.env.example.coolify"

target=".env"
mode="sync"
for arg in "$@"; do
  case "$arg" in
    --check) mode="check" ;;
    --target) shift; target="${1:-.env}" ;;
    *) ;;
  esac
done
TARGET="${REPO_ROOT}/${target}"

if [[ ! -f "$EXAMPLE" ]]; then
  echo "ERROR: $EXAMPLE not found" >&2
  exit 1
fi
if [[ ! -f "$TARGET" ]]; then
  echo "Creating $TARGET from $EXAMPLE template"
  cp "$EXAMPLE" "$TARGET"
  exit 0
fi

# Extract existing keys (handle values that span lines)
declare -A existing
while IFS= read -r line; do
  # Skip comments / blanks
  [[ "$line" =~ ^[[:space:]]*# ]] && continue
  [[ -z "$line" ]] && continue
  if [[ "$line" =~ ^[[:space:]]*([A-Z_][A-Z_0-9]*)= ]]; then
    key="${BASH_REMATCH[1]}"
    existing["$key"]=1
  fi
done < "$TARGET"

missing=()
total=0
while IFS= read -r line; do
  [[ "$line" =~ ^[[:space:]]*# ]] && continue
  [[ -z "$line" ]] && continue
  if [[ "$line" =~ ^[[:space:]]*([A-Z_][A-Z_0-9]*)= ]]; then
    key="${BASH_REMATCH[1]}"
    total=$((total + 1))
    if [[ -z "${existing[$key]:-}" ]]; then
      missing+=("$line")
    fi
  fi
done < "$EXAMPLE"

if [[ "$mode" == "check" ]]; then
  echo "Checked $target against .env.example"
  echo "  Total keys in .env.example: $total"
  echo "  Already present in $target: $((total - ${#missing[@]}))"
  echo "  Missing keys: ${#missing[@]}"
  if [[ ${#missing[@]} -gt 0 ]]; then
    echo ""
    echo "Missing keys (add these to $target):"
    printf '  %s\n' "${missing[@]}"
    exit 1
  fi
  exit 0
fi

if [[ ${#missing[@]} -eq 0 ]]; then
  echo "βœ“ $target already in sync with .env.example ($total keys)"
  exit 0
fi

{
  echo ""
  echo "# ─── Auto-synced from .env.example ($(date -u +%Y-%m-%dT%H:%M:%SZ)) ──"
  printf '%s\n' "${missing[@]}"
} >> "$TARGET"

echo "βœ“ Added ${#missing[@]} missing keys to $target"
echo "  Total keys in $target: $total"