#!/usr/bin/env bash
# Sync Bloom's deployment secrets from GitHub Actions to the dev k3s cluster as Kubernetes
# Secrets (M24-4), via Bitnami sealed-secrets (decision record: deploy/k8s/README.md#secrets).
# This is the `dev` secrets target, called by the "Sync secrets (dev)" workflow and by the
# M24-5 helm deploy; run it again any time a secret is added or rotated in Actions settings.
#
# Flow - plaintext never leaves the runner; only ciphertext crosses SSH or touches the VM:
#   1. ensure the sealed-secrets controller + kubeseal on the cluster host (idempotent)
#   2. fetch the cluster's public sealing certificate
#   3. render bloom-api-secrets / bloom-swarm-secrets from SECRETS_JSON and seal them locally
#   4. apply the SealedSecrets over ssh and wait until the controller has unsealed them
#
# Requires: DEPLOY_HOST, DEPLOY_SSH_KEY (the dev environment's deploy credentials, as
# exedev.sh) and SECRETS_JSON (toJSON(secrets) - NEVER toJSON(vars): variables are non-secret
# config and belong to the chart's ConfigMaps). Optional: DEPLOY_USER (exedev),
# BLOOM_NAMESPACE (bloom). Run from the repo root.
set -euo pipefail

: "${SECRETS_JSON:?SECRETS_JSON not set}"
namespace="${BLOOM_NAMESPACE:-bloom}"

# shellcheck source=scripts/deploy/sshlib.sh
source "$(dirname "${BASH_SOURCE[0]}")/sshlib.sh"
deploy_ssh_setup

workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT

echo "==> Ensuring the sealed-secrets controller on $DEPLOY_HOST (idempotent)"
"${ssh_cmd[@]}" 'bash -s -- install' < deploy/k8s/sealed-secrets.sh

echo "==> Fetching the cluster's sealing certificate"
"${ssh_cmd[@]}" 'bash -s -- cert' < deploy/k8s/sealed-secrets.sh > "$workdir/sealing-cert.pem"

echo "==> Ensuring kubeseal locally"
bash deploy/k8s/sealed-secrets.sh kubeseal

echo "==> Rendering + sealing"
sealed=()
for component in api swarm; do
  manifest="$(bash scripts/deploy/render-k8s-secrets.sh "$component" "$namespace")"
  if [ -z "$manifest" ]; then
    echo "    (no $component secrets in the Actions context - skipping)"
    continue
  fi
  {
    [ "${#sealed[@]}" -eq 0 ] || echo '---'
    printf '%s' "$manifest" | kubeseal --cert "$workdir/sealing-cert.pem" --format yaml
  } >> "$workdir/sealed.yaml"
  sealed+=("bloom-${component}-secrets")
done
if [ "${#sealed[@]}" -eq 0 ]; then
  echo "::error::no secrets rendered from SECRETS_JSON - is the workflow passing toJSON(secrets)?" >&2
  exit 1
fi

echo "==> Applying SealedSecrets (${sealed[*]}) and waiting for the controller to unseal"
"${ssh_cmd[@]}" 'KUBECONFIG="$HOME/.kube/config" kubectl apply -f -' < "$workdir/sealed.yaml"
for name in "${sealed[@]}"; do
  "${ssh_cmd[@]}" "KUBECONFIG=\"\$HOME/.kube/config\" kubectl -n '$namespace' wait \
    --for=condition=Synced 'sealedsecret/$name' --timeout=120s"
  # Evidence without exposure: list the delivered key NAMES only, never any value.
  echo "    $name keys:"
  "${ssh_cmd[@]}" "KUBECONFIG=\"\$HOME/.kube/config\" kubectl -n '$namespace' get secret '$name' \
    -o go-template='{{range \$k, \$v := .data}}{{\$k}}{{\"\\n\"}}{{end}}'" | sed 's/^/      /'
done
echo "==> Done. Pods pick the new values up on their next rollout (the M24-5 deploy, or" \
  "kubectl -n $namespace rollout restart deploy)."
