#!/usr/bin/env bash set -euo pipefail PROG="init_forgejo" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck disable=SC1090 source "$SCRIPT_DIR/knoe_cfg.sh" MODE="$(knoe_normalize_mode "${KNOE_MODE:-${DEPLOYMENT_MODE:-k3d}}")" NAMESPACE="${FORGEJO_NAMESPACE:-}" CFG_PATH="" FORCE=0 usage() { cat < Deployment mode (default: ${MODE:-k3d}) -n, --namespace Target namespace (default: forgejo) -c, --config Path to config file (defaults to detected) --force Delete existing Forgejo resources before deploy --help Show this help Behavior: - Applies a minimal Forgejo Deployment/Service manifest. - Uses CloudNativePG (CNPG) Postgres as the database backend. - By default, creates a dedicated DB + role inside the CNPG cluster. EOF } die() { echo "[ERROR] $*" >&2; exit 2; } log() { echo "[INFO] $*"; } warn() { echo "[WARN] $*" >&2; } while [[ $# -gt 0 ]]; do case "$1" in --mode) MODE="$(knoe_normalize_mode "${2:-}")"; shift 2 ;; --mode=*) MODE="$(knoe_normalize_mode "${1#*=}")"; shift 1 ;; -n|--namespace) NAMESPACE="${2:-}"; shift 2 ;; --namespace=*) NAMESPACE="${1#*=}"; shift 1 ;; -c|--config) CFG_PATH="${2:-}"; shift 2 ;; --config=*) CFG_PATH="${1#*=}"; shift 1 ;; --force) FORCE=1; shift 1 ;; -h|--help) usage; exit 0 ;; *) break ;; esac done # Resolve config path and namespace defaults when present if [[ -z "$CFG_PATH" && -n "${KNOE_CONF:-}" ]]; then CFG_PATH="$(_knoe_cfg_select_cfg_file "${KNOE_CONF}")" fi if [[ -z "$CFG_PATH" ]]; then CFG_PATH="$(_knoe_cfg_select_cfg_file "$SCRIPT_DIR/../conf")" fi if [[ -z "$NAMESPACE" && -n "$CFG_PATH" ]]; then maybe_ns="$(_knoe_cfg_extract_key "$CFG_PATH" "GITOPS_NAMESPACE")" [[ -z "$maybe_ns" ]] && maybe_ns="$(_knoe_cfg_extract_key "$CFG_PATH" "FORGEJO_NAMESPACE")" NAMESPACE="$maybe_ns" fi NAMESPACE="${NAMESPACE:-forgejo}" export FORGEJO_NAMESPACE="$NAMESPACE" case "$MODE" in k3d|k3s|k8s|local) ;; *) die "Unsupported mode '$MODE' (use k3d, k3s, k8s, or local)" ;; esac export KNOE_MODE="$MODE" command -v kubectl >/dev/null || die "kubectl not found" DB_NAMESPACE="${PROLE_NAMESPACE:-}" if [[ -z "$DB_NAMESPACE" && -n "$CFG_PATH" ]]; then DB_NAMESPACE="$(_knoe_cfg_extract_key "$CFG_PATH" "NAMESPACE")" fi DB_NAMESPACE="${DB_NAMESPACE:-default}" CNPG_CLUSTER_NAME="${CNPG_CLUSTER_NAME:-knoe-db}" FORGEJO_DB_NAME="${FORGEJO_DB_NAME:-forgejo}" FORGEJO_DB_USER="${FORGEJO_DB_USER:-forgejo}" FORGEJO_DB_PASSWORD="${FORGEJO_DB_PASSWORD:-}" if [[ -z "$FORGEJO_DB_PASSWORD" ]]; then # 24 chars alnum for broad chart compatibility. FORGEJO_DB_PASSWORD=$(LC_ALL=C tr -dc 'A-Za-z0-9' /dev/null | head -c 24 || true) fi DB_HOST="${CNPG_CLUSTER_NAME}-rw.${DB_NAMESPACE}.svc.cluster.local" DB_PORT="${FORGEJO_DB_PORT:-5432}" kubectl get ns "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE" >/dev/null 2>&1 if [[ "$FORCE" -eq 1 ]]; then warn "--force specified; removing existing Forgejo resources in namespace $NAMESPACE" kubectl -n "$NAMESPACE" delete deploy/forgejo svc/forgejo-http svc/forgejo-ssh ingress/forgejo >/dev/null 2>&1 || true fi ensure_db() { local primary_pod="" primary_pod=$(kubectl -n "$DB_NAMESPACE" get pods \ -l "cnpg.io/cluster=${CNPG_CLUSTER_NAME},role=primary" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true) if [[ -z "$primary_pod" ]]; then primary_pod=$(kubectl -n "$DB_NAMESPACE" get pods \ -l "cnpg.io/cluster=${CNPG_CLUSTER_NAME}" \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true) fi if [[ -z "$primary_pod" ]]; then die "Could not find CNPG pod for cluster '${CNPG_CLUSTER_NAME}' in namespace '${DB_NAMESPACE}'" fi log "Ensuring database '${FORGEJO_DB_NAME}' and role '${FORGEJO_DB_USER}' exist in CNPG cluster '${CNPG_CLUSTER_NAME}' (ns=${DB_NAMESPACE})" # Create role/db idempotently. kubectl -n "$DB_NAMESPACE" exec "$primary_pod" -- bash -lc "psql -v ON_ERROR_STOP=1 -U postgres -d postgres" </dev/null } ensure_db FORGEJO_IMAGE_REPO="${FORGEJO_IMAGE_REPO:-codeberg.org/forgejo/forgejo}" FORGEJO_IMAGE_TAG="${FORGEJO_IMAGE_TAG:-latest}" log "Deploying Forgejo to namespace '$NAMESPACE' (mode=$MODE)" cat <