Files
edr-platform/scripts/deploy/sync-env-from-env-manager.sh
2026-08-17 12:53:08 +00:00

93 lines
3.5 KiB
Bash

#!/usr/bin/env bash
# Sync .env files from the Env Manager API into the repo.
#
# Usage:
# ENV_MANAGER_TOKEN=xxx ./scripts/deploy/sync-env-from-server.sh freight-api freight-portal freight-backoffice
#
# You normally only need to pass the token via the action secret, and BRANCH
# via the job-level env (e.g. `BRANCH: ${{ github.ref_name }}` in the workflow):
# env:
# BRANCH: ${{ github.ref_name }}
# ENV_MANAGER_TOKEN: ${{ secrets.ENV_MANAGER_TOKEN }}
#
# API layout (one endpoint per service):
# GET https://env.smart.aaca.gov.et/api/env/edr/<branch>/<service>?format=dotenv
# Header: Authorization: Bearer <ENV_MANAGER_TOKEN>
set -euo pipefail
PROJECT="edr"
ENV_MANAGER_URL="https://env.smart.aaca.gov.et"
BRANCH="${BRANCH:?BRANCH is required}"
ENV_MANAGER_TOKEN="${ENV_MANAGER_TOKEN:?ENV_MANAGER_TOKEN is required}"
declare -A SERVICE_ENV_TARGET=(
["freight_api"]="apps/edr-freight-api/.env"
["freight_portal"]="apps/edr-freight-web/portal/.env"
["freight_backoffice"]="apps/edr-freight-web/backoffice/.env"
["gps_tracker"]="apps/edr-gps-tracker/.env"
["passenger_api"]="apps/edr-passenger-api/.env"
["passenger_portal"]="apps/edr-passenger-web/portal/.env"
["passenger_backoffice"]="apps/edr-passenger-web/backoffice/.env"
["payment_api"]="apps/edr-payment-api/.env"
["synapse"]="infrastructure/matrix/synapse/.env"
# element_web holds no secrets, but its config.json is rendered at container
# start from MATRIX_PUBLIC_BASEURL / MATRIX_SERVER_NAME / ELEMENT_PUBLIC_URL
# (see infrastructure/matrix/element), so it needs an env file like the rest —
# plus the PORT line every service env is required to carry.
["element_web"]="infrastructure/matrix/element/.env"
)
for service in "$@"; do
branch_api_name="${BRANCH//-/_}"
service_api_name="${service//-/_}"
dest="${SERVICE_ENV_TARGET[${service_api_name}]:-}"
if [[ -z "${dest}" ]]; then
echo "Unknown service: ${service}" >&2
exit 1
fi
url="${ENV_MANAGER_URL}/api/env/${PROJECT}/${branch_api_name}/${service_api_name}?format=dotenv"
mkdir -p "$(dirname "${dest}")"
tmp_file="$(mktemp)"
trap 'rm -f "${tmp_file}"' RETURN 2>/dev/null || true
http_status=$(curl -fsS -o "${tmp_file}" -w "%{http_code}" \
-H "Authorization: Bearer ${ENV_MANAGER_TOKEN}" \
"${url}") || {
echo "Failed to fetch env for '${service}' from ${url}" >&2
rm -f "${tmp_file}"
exit 1
}
if [[ "${http_status}" != "200" ]]; then
echo "Env Manager returned HTTP ${http_status} for '${service}' (${url})" >&2
rm -f "${tmp_file}"
exit 1
fi
if [[ ! -s "${tmp_file}" ]]; then
echo "Env Manager returned an empty response for '${service}' (${url})" >&2
rm -f "${tmp_file}"
exit 1
fi
mv "${tmp_file}" "${dest}"
echo "Synced ${url} -> ${dest}"
port_value=$(sed -n -E 's/^[[:space:]]*PORT[[:space:]]*=[[:space:]]*"?([^"#]+)"?[[:space:]]*(#.*)?$/\1/p' "${dest}" | head -n1 | tr -d '[:space:]')
if [[ -z "${port_value}" ]]; then
echo "Missing required PORT in env file for '${service}' (${dest})" >&2
exit 1
fi
if [[ -n "${GITHUB_ENV:-}" ]]; then
service_var=$(echo "${service}" | tr '[:lower:]-' '[:upper:]_')
echo "${service_var}_PORT=${port_value}" >> "${GITHUB_ENV}"
echo "Exported ${service_var}_PORT from ${dest}"
# Forward NEXT_PUBLIC_* and VITE_* vars so docker compose build can inject them as build args.
grep -E '^[[:space:]]*(NEXT_PUBLIC_|VITE_)[A-Za-z0-9_]+=' "${dest}" \
| sed -E 's/^[[:space:]]*//' >> "${GITHUB_ENV}" || true
fi
done