#!/usr/bin/env bash set -euo pipefail ROOT_DIR=$(cd "$(dirname "$0")/../.." && pwd) PLATFORM_REPO_DIR="${PLATFORM_REPO_DIR:-$ROOT_DIR/../unrip3}" BOOTSTRAP_ENV_FILE="${BOOTSTRAP_ENV_FILE:-$PLATFORM_REPO_DIR/.state/hetzner/bootstrap-secrets.resolved.env}" PLATFORM_APP_ENV_FILE="${PLATFORM_APP_ENV_FILE:-$PLATFORM_REPO_DIR/.env}" APP_ENV_FILE="${APP_ENV_FILE:-$ROOT_DIR/.env}" FORGEJO_REMOTE_NAME="${FORGEJO_REMOTE_NAME:-forgejo}" PROJECT_NAME="${PROJECT_NAME:-unrip}" PROJECT_NAMESPACE="${PROJECT_NAMESPACE:-$PROJECT_NAME}" PROJECT_DEPLOYMENTS="${PROJECT_DEPLOYMENTS:-near-intents-ingest,dummy-reactor,dummy-executor,dummy-consumer}" PROJECT_REGISTRY_SECRET_NAME="${PROJECT_REGISTRY_SECRET_NAME:-${PROJECT_NAME}-registry-creds}" APP_SECRET_NAME="${APP_SECRET_NAME:-${PROJECT_NAME}-secrets}" require() { command -v "$1" >/dev/null 2>&1 || { echo "missing required command: $1" >&2 exit 1 } } load_env_defaults() { local file="$1" [[ -f "$file" ]] || return 0 eval "$( python3 - "$file" <<'PY' import os import shlex import sys for raw in open(sys.argv[1], 'r', encoding='utf-8'): line = raw.strip() if not line or line.startswith('#'): continue if line.startswith('export '): line = line[len('export '):] if '=' not in line: continue key, value = line.split('=', 1) key = key.strip() if key in os.environ: continue print(f'export {key}={shlex.quote(value)}') PY )" } require git require kubectl require python3 require base64 load_env_defaults "$BOOTSTRAP_ENV_FILE" load_env_defaults "$PLATFORM_APP_ENV_FILE" load_env_defaults "$APP_ENV_FILE" REMOTE_URL="${FORGEJO_REMOTE_URL:-$(git -C "$ROOT_DIR" remote get-url "$FORGEJO_REMOTE_NAME")}" eval "$( python3 - "$REMOTE_URL" <<'PY' import sys from urllib.parse import urlparse remote = sys.argv[1] parsed = urlparse(remote) if parsed.scheme not in {'http', 'https'}: raise SystemExit('forgejo remote must use http(s) for automatic bootstrap') path = parsed.path.rstrip('/') if path.endswith('.git'): path = path[:-4] parts = [part for part in path.split('/') if part] if len(parts) < 2: raise SystemExit('could not parse repo owner/name from forgejo remote') base_url = f'{parsed.scheme}://{parsed.hostname}' if parsed.port: base_url += f':{parsed.port}' if parsed.username and parsed.password: print(f'export FORGEJO_API_PASSWORD={parsed.password}') if parsed.username: print(f'export FORGEJO_API_USERNAME={parsed.username}') print(f'export FORGEJO_URL={base_url}') print(f'export FORGEJO_REPO_OWNER={parts[-2]}') print(f'export FORGEJO_REPO_NAME={parts[-1]}') PY )" : "${KUBECONFIG_PATH:=${KUBECONFIG:-$PLATFORM_REPO_DIR/.state/hetzner/kubeconfig.yaml}}" : "${CI_KUBECONFIG_PATH:=$PLATFORM_REPO_DIR/.state/hetzner/kubeconfig.incluster.yaml}" : "${FORGEJO_URL:?set FORGEJO_URL or configure a forgejo remote}" : "${FORGEJO_REPO_OWNER:?set FORGEJO_REPO_OWNER}" : "${FORGEJO_REPO_NAME:?set FORGEJO_REPO_NAME}" : "${FORGEJO_ADMIN_USERNAME:=${FORGEJO_API_USERNAME:-}}" if [[ -z "${FORGEJO_TOKEN:-}" ]]; then : "${FORGEJO_ADMIN_USERNAME:=${FORGEJO_API_USERNAME:-}}" : "${FORGEJO_ADMIN_USERNAME:?set FORGEJO_TOKEN or FORGEJO_ADMIN_USERNAME}" : "${FORGEJO_ADMIN_PASSWORD:=${FORGEJO_API_PASSWORD:-}}" : "${FORGEJO_ADMIN_PASSWORD:?set FORGEJO_TOKEN or FORGEJO_ADMIN_PASSWORD}" fi if [[ ! -f "$KUBECONFIG_PATH" ]]; then echo "missing kubeconfig: $KUBECONFIG_PATH" >&2 exit 1 fi if [[ ! -f "$CI_KUBECONFIG_PATH" ]]; then echo "missing in-cluster kubeconfig: $CI_KUBECONFIG_PATH" >&2 exit 1 fi export KUBECONFIG="$KUBECONFIG_PATH" if [[ -z "${REGISTRY_HOST:-}" ]]; then REGISTRY_HOST="${REGISTRY_DOMAIN:-}" fi if [[ -z "${REGISTRY_HOST:-}" ]]; then REGISTRY_HOST="$(kubectl get ingress -n registry registry -o jsonpath='{.spec.rules[0].host}' 2>/dev/null || true)" fi if [[ -z "${REGISTRY_USERNAME:-}" ]]; then REGISTRY_USERNAME="$(kubectl get secret registry-secrets -n registry -o jsonpath='{.data.htpasswd}' 2>/dev/null | base64 -d | cut -d: -f1 || true)" fi : "${REGISTRY_HOST:?set REGISTRY_HOST or configure the registry ingress first}" : "${REGISTRY_USERNAME:?set REGISTRY_USERNAME or bootstrap the shared registry first}" : "${REGISTRY_PASSWORD:?set REGISTRY_PASSWORD}" : "${NEAR_INTENTS_API_KEY:?set NEAR_INTENTS_API_KEY}" echo "bootstrapping namespace $PROJECT_NAMESPACE" kubectl apply -f "$ROOT_DIR/deploy/k8s/base/namespace.yaml" echo "upserting runtime secret $APP_SECRET_NAME" kubectl -n "$PROJECT_NAMESPACE" create secret generic "$APP_SECRET_NAME" \ --from-literal=NEAR_INTENTS_API_KEY="$NEAR_INTENTS_API_KEY" \ --dry-run=client -o yaml | kubectl apply -f - echo "upserting registry pull/push secret $PROJECT_REGISTRY_SECRET_NAME" kubectl -n "$PROJECT_NAMESPACE" create secret docker-registry "$PROJECT_REGISTRY_SECRET_NAME" \ --docker-server="$REGISTRY_HOST" \ --docker-username="$REGISTRY_USERNAME" \ --docker-password="$REGISTRY_PASSWORD" \ --dry-run=client -o yaml | kubectl apply -f - echo "applying app manifests" kubectl apply -k "$ROOT_DIR/deploy/k8s/base" echo "upserting Forgejo repo settings" forgejo_args=() if [[ -n "${FORGEJO_TOKEN:-}" ]]; then forgejo_args+=(--token "$FORGEJO_TOKEN") fi if [[ -n "${FORGEJO_ADMIN_USERNAME:-}" ]]; then forgejo_args+=(--admin-username "$FORGEJO_ADMIN_USERNAME") fi if [[ -n "${FORGEJO_ADMIN_PASSWORD:-}" ]]; then forgejo_args+=(--admin-password "$FORGEJO_ADMIN_PASSWORD") fi python3 "$ROOT_DIR/scripts/deploy/forgejo_repo_bootstrap.py" \ --forgejo-url "$FORGEJO_URL" \ --repo-owner "$FORGEJO_REPO_OWNER" \ --repo-name "$FORGEJO_REPO_NAME" \ --ci-kubeconfig "$CI_KUBECONFIG_PATH" \ --registry-host "$REGISTRY_HOST" \ --project-name "$PROJECT_NAME" \ --project-namespace "$PROJECT_NAMESPACE" \ --project-deployments "$PROJECT_DEPLOYMENTS" \ --project-registry-secret-name "$PROJECT_REGISTRY_SECRET_NAME" \ "${forgejo_args[@]}" cat <