diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index 2ccf5a6..6a72615 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -254,30 +254,16 @@ jobs: set -euo pipefail git pull - - name: Sync .env files from .env.example + - name: Inject .env files from Gitea variables working-directory: /docker/FarmaFinder + env: + GITEA_TOKEN: ${{ vars.GITEA_TOKEN }} + GITEA_OWNER: Ichitux + GITEA_REPO: FarmaFinder + WORK_DIR: /docker/FarmaFinder run: | set -euo pipefail - while IFS= read -r env_example; do - dir=$(dirname "$env_example") - env_file="$dir/.env" - - if [ ! -f "$env_file" ]; then - cp "$env_example" "$env_file" - echo "[env-sync] Created $env_file from $env_example" - else - while IFS= read -r line || [ -n "$line" ]; do - case "$line" in - ''|\#*) continue ;; - esac - key=$(echo "$line" | cut -d'=' -f1) - if ! grep -qF "$key=" "$env_file"; then - echo "$line" >> "$env_file" - echo "[env-sync] Added missing key '$key' to $env_file" - fi - done < "$env_example" - fi - done < <(find apps -name ".env.example" -type f) + bash scripts/deploy-env.sh - name: Deploy containers working-directory: /docker/FarmaFinder diff --git a/scripts/deploy-env.sh b/scripts/deploy-env.sh new file mode 100644 index 0000000..8481c05 --- /dev/null +++ b/scripts/deploy-env.sh @@ -0,0 +1,191 @@ +#!/usr/bin/env bash +# deploy-env.sh — Fetch Gitea Actions variables and write .env files. +# Called by the CI/CD deploy step on the self-hosted runner. +# +# Required env vars (injected by Gitea Actions): +# GITEA_TOKEN — API token with repo read access +# GITEA_OWNER — repo owner (e.g. Ichitux) +# GITEA_REPO — repo name (e.g. FarmaFinder) +# +# Usage: +# GITEA_TOKEN=xxx GITEA_OWNER=Ichitux GITEA_REPO=FarmaFinder ./scripts/deploy-env.sh + +set -euo pipefail + +GITEA_URL="${GITEA_URL:-https://git.hacecalor.net}" +WORK_DIR="${WORK_DIR:-.}" + +# --------------------------------------------------------------------------- +# Helper: fetch all repo variables from Gitea API (handles pagination) +# Returns JSON array on stdout +# --------------------------------------------------------------------------- +fetch_variables() { + local page=1 limit=50 all='[]' + while true; do + local resp + resp=$(curl -sf \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/actions/variables?limit=${limit}&page=${page}") + + local count + count=$(echo "$resp" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))") + + all=$(python3 -c " +import sys, json +a = json.loads('''${all}''') +b = json.loads(sys.stdin.read()) +print(json.dumps(a + b)) +" <<< "$resp") + + if [ "$count" -lt "$limit" ]; then + break + fi + page=$((page + 1)) + done + echo "$all" +} + +# --------------------------------------------------------------------------- +# Helper: write a .env file from a JSON object of key-value pairs. +# Keys are sorted alphabetically. Comments from .env.example are preserved. +# --------------------------------------------------------------------------- +write_env() { + local env_path="$1" + local json_obj="$2" + local example_path="${env_path}.example" + + # If no example file exists, write a plain KEY=VALUE file + if [ ! -f "$example_path" ]; then + python3 -c " +import json, sys +obj = json.loads('''${json_obj}''') +for k in sorted(obj): + print(f'{k}={obj[k]}') +" > "$env_path" + echo "[env] Wrote $env_path (${#json_obj} bytes, no .example template)" + return + fi + + # If .example exists, produce a file that preserves comments/order + # and fills in values from the JSON + python3 -c " +import json, sys, re + +example_path = '''${example_path}''' +env_path = '''${env_path}''' +values = json.loads('''${json_obj}''') + +with open(example_path) as f: + lines = f.readlines() + +output = [] +written_keys = set() +for line in lines: + stripped = line.rstrip('\n') + + # Pass through comments and blank lines + if stripped.startswith('#') or stripped.strip() == '': + output.append(stripped) + continue + + # Parse KEY=VALUE lines + m = re.match(r'^([A-Za-z_][A-Za-z0-9_]*)=(.*)', stripped) + if m: + key, _ = m.group(1), m.group(2) + if key in values: + output.append(f'{key}={values[key]}') + written_keys.add(key) + else: + output.append(stripped) # keep example default + else: + output.append(stripped) + +# Append any keys from values that weren't in .example +for k in sorted(values): + if k not in written_keys: + output.append(f'{k}={values[k]}') + +with open(env_path, 'w') as f: + f.write('\n'.join(output) + '\n') + +print(f'[env] Wrote {env_path} ({len(values)} vars)') +" 2>&1 +} + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- +echo "=== deploy-env.sh ===" +echo "Fetching variables from Gitea: ${GITEA_OWNER}/${GITEA_REPO}" + +VARS_JSON=$(fetch_variables) +VAR_COUNT=$(echo "$VARS_JSON" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))") +echo "Found ${VAR_COUNT} variables" + +# Group variables by prefix +# ROOT_* → root .env (strip prefix) +# BACKEND_* → apps/backend/.env (strip prefix) +# FRONTEND_* → apps/frontend/.env (strip prefix) +# PARAPHARMACY_* → apps/parapharmacy-api/.env (strip prefix) +# No prefix → root .env (backward compat with original vars) + +ROOT_VARS=$(python3 -c " +import json, sys +vars = json.loads(sys.stdin.read()) +# Keys that are CI-only and should NOT appear in application .env files +skip = {'GITEA_TOKEN'} +result = {} +for v in vars: + name = v['name'] + value = v['data'] + if name in skip: + continue + if name.startswith('ROOT_'): + result[name[5:]] = value # strip ROOT_ prefix + elif not any(name.startswith(p) for p in ['BACKEND_', 'FRONTEND_', 'PARAPHARMACY_']): + result[name] = value # unprefixed → root +print(json.dumps(result)) +" <<< "$VARS_JSON") + +BACKEND_VARS=$(python3 -c " +import json, sys +vars = json.loads(sys.stdin.read()) +result = {} +for v in vars: + name = v['name'] + if name.startswith('BACKEND_'): + result[name[8:]] = value = v['data'] +print(json.dumps(result)) +" <<< "$VARS_JSON") + +FRONTEND_VARS=$(python3 -c " +import json, sys +vars = json.loads(sys.stdin.read()) +result = {} +for v in vars: + name = v['name'] + if name.startswith('FRONTEND_'): + result[name[9:]] = v['data'] +print(json.dumps(result)) +" <<< "$VARS_JSON") + +PARAPHARMACY_VARS=$(python3 -c " +import json, sys +vars = json.loads(sys.stdin.read()) +result = {} +for v in vars: + name = v['name'] + if name.startswith('PARAPHARMACY_'): + result[name[13:]] = v['data'] +print(json.dumps(result)) +" <<< "$VARS_JSON") + +# Write each .env file +echo "" +write_env "${WORK_DIR}/.env" "$ROOT_VARS" +write_env "${WORK_DIR}/apps/backend/.env" "$BACKEND_VARS" +write_env "${WORK_DIR}/apps/frontend/.env" "$FRONTEND_VARS" +write_env "${WORK_DIR}/apps/parapharmacy-api/.env" "$PARAPHARMACY_VARS" + +echo "" +echo "=== All .env files written ==="