#!/bin/bash set -euo pipefail # pipelines/gitea/setup.sh — Automate Gitea initial setup via REST API # # Steps: # 1. Create admin user (idempotent — skip if already exists) # 2. Create OAuth2 application for Woodpecker CI (idempotent — reuse if exists) # 3. Create stonks-oracle repository (idempotent — skip if already exists) # # Outputs OAuth2 client_id and client_secret to stdout and to # gitea-oauth2.env (sourceable by runmefirst.sh). # # Requirements: 1.1, 1.2, 1.5, 2.3 # ------------------------------------------------------- # Configuration (override via environment variables) # ------------------------------------------------------- GITEA_URL="${GITEA_URL:-http://10.1.1.12:30300}" GITEA_ADMIN_USER="${GITEA_ADMIN_USER:-admin}" GITEA_ADMIN_PASSWORD="${GITEA_ADMIN_PASSWORD:-St0nks0racl3!}" GITEA_ADMIN_EMAIL="${GITEA_ADMIN_EMAIL:-admin@celestium.life}" OAUTH2_APP_NAME="woodpecker-ci" OAUTH2_REDIRECT_URI="https://stonks-ci.celestium.life/authorize" REPO_NAME="stonks-oracle" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OAUTH2_ENV_FILE="${SCRIPT_DIR}/gitea-oauth2.env" API="${GITEA_URL}/api/v1" AUTH_HEADER="Authorization: Basic $(echo -n "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" | base64)" echo "=== Gitea Setup ===" echo " URL: ${GITEA_URL}" echo " Admin user: ${GITEA_ADMIN_USER}" echo "" # ------------------------------------------------------- # Helper: wait for Gitea to be reachable # (Gitea returns 404 on /api/v1/version when on install page, so check root) # ------------------------------------------------------- echo "--- Waiting for Gitea to be reachable ---" for i in $(seq 1 30); do HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "${GITEA_URL}/" 2>/dev/null || echo "000") if [ "$HTTP_STATUS" != "000" ]; then echo " ✓ Gitea is reachable (HTTP ${HTTP_STATUS})" break fi if [ "$i" -eq 30 ]; then echo " ✗ Gitea not reachable after 30 attempts" exit 1 fi echo " Attempt ${i}/30 — waiting 5s..." sleep 5 done echo "" # ------------------------------------------------------- # Step 1: Create admin user # ------------------------------------------------------- echo "--- Step 1: Create admin user ---" # Check if admin user already exists by attempting to query the API with credentials HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 \ -H "${AUTH_HEADER}" \ "${API}/user") if [ "$HTTP_CODE" = "200" ]; then echo " ✓ Admin user '${GITEA_ADMIN_USER}' already exists and credentials are valid" elif [ "$HTTP_CODE" = "404" ]; then # Gitea is on the install page — API not available yet echo " Gitea API not available (install page) — completing initial setup..." INSTALL_RESPONSE=$(curl -s -w "\n%{http_code}" \ -X POST "${GITEA_URL}/" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "db_type=sqlite3" \ --data-urlencode "db_host=localhost:3306" \ --data-urlencode "db_user=root" \ --data-urlencode "db_passwd=" \ --data-urlencode "db_name=gitea" \ --data-urlencode "ssl_mode=disable" \ --data-urlencode "db_path=/data/gitea/gitea.db" \ --data-urlencode "app_name=Gitea: Git with a cup of tea" \ --data-urlencode "repo_root_path=/data/git/repositories" \ --data-urlencode "lfs_root_path=/data/git/lfs" \ --data-urlencode "run_user=git" \ --data-urlencode "domain=gitea-service.git-server.svc.cluster.local" \ --data-urlencode "ssh_port=22" \ --data-urlencode "http_port=3000" \ --data-urlencode "app_url=http://gitea-service.git-server.svc.cluster.local:3000/" \ --data-urlencode "log_root_path=/data/gitea/log" \ --data-urlencode "admin_name=${GITEA_ADMIN_USER}" \ --data-urlencode "admin_passwd=${GITEA_ADMIN_PASSWORD}" \ --data-urlencode "admin_confirm_passwd=${GITEA_ADMIN_PASSWORD}" \ --data-urlencode "admin_email=${GITEA_ADMIN_EMAIL}") INSTALL_CODE=$(echo "$INSTALL_RESPONSE" | tail -n 1) if [ "$INSTALL_CODE" = "200" ] || [ "$INSTALL_CODE" = "302" ]; then echo " ✓ Gitea initial install completed with admin user" # Gitea restarts after install — wait for API to become available echo " Waiting for Gitea API to become available after install..." for j in $(seq 1 30); do API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "${API}/version" 2>/dev/null || echo "000") if [ "$API_STATUS" = "200" ]; then echo " ✓ Gitea API is ready" break fi if [ "$j" -eq 30 ]; then echo " ✗ Gitea API not available after install (waited 150s)" exit 1 fi sleep 5 done else echo " ✗ Install wizard returned HTTP ${INSTALL_CODE}" echo " Response: $(echo "$INSTALL_RESPONSE" | head -n -1 | tail -5)" exit 1 fi else echo " Admin user not found or credentials invalid — creating via admin API..." # Try creating the user via Gitea's admin create-user API # This works when Gitea has been initialized but no admin user exists, # or when using the built-in admin creation endpoint RESPONSE=$(curl -s -w "\n%{http_code}" \ -X POST "${API}/admin/users" \ -H "Content-Type: application/json" \ -H "${AUTH_HEADER}" \ -d "{ \"username\": \"${GITEA_ADMIN_USER}\", \"password\": \"${GITEA_ADMIN_PASSWORD}\", \"email\": \"${GITEA_ADMIN_EMAIL}\", \"must_change_password\": false, \"login_name\": \"${GITEA_ADMIN_USER}\", \"source_id\": 0, \"visibility\": \"public\" }") BODY=$(echo "$RESPONSE" | head -n -1) CODE=$(echo "$RESPONSE" | tail -n 1) if [ "$CODE" = "201" ]; then echo " ✓ Admin user '${GITEA_ADMIN_USER}' created" elif [ "$CODE" = "422" ]; then echo " ✓ Admin user '${GITEA_ADMIN_USER}' already exists (422)" else echo " ✗ Unexpected response creating admin user: HTTP ${CODE}" echo " Response: ${BODY}" exit 1 fi fi echo "" # ------------------------------------------------------- # Step 2: Create OAuth2 application for Woodpecker CI # ------------------------------------------------------- echo "--- Step 2: Create OAuth2 application '${OAUTH2_APP_NAME}' ---" # Check if the OAuth2 app already exists EXISTING_APPS=$(curl -s \ -H "${AUTH_HEADER}" \ "${API}/user/applications/oauth2") EXISTING_APP=$(echo "$EXISTING_APPS" | python3 -c " import sys, json apps = json.load(sys.stdin) for app in apps: if app.get('name') == '${OAUTH2_APP_NAME}': print(json.dumps(app)) break " 2>/dev/null || echo "") if [ -n "$EXISTING_APP" ]; then echo " ✓ OAuth2 app '${OAUTH2_APP_NAME}' already exists" OAUTH2_CLIENT_ID=$(echo "$EXISTING_APP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])") # Note: Gitea does not return client_secret for existing apps. # If we need the secret, we must delete and recreate. OAUTH2_CLIENT_SECRET=$(echo "$EXISTING_APP" | python3 -c " import sys, json data = json.load(sys.stdin) print(data.get('client_secret', '')) " 2>/dev/null || echo "") if [ -z "$OAUTH2_CLIENT_SECRET" ]; then echo " ⚠ Client secret not available for existing app — recreating..." APP_ID=$(echo "$EXISTING_APP" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") curl -s -X DELETE \ -H "${AUTH_HEADER}" \ "${API}/user/applications/oauth2/${APP_ID}" > /dev/null echo " Deleted existing OAuth2 app (id=${APP_ID})" EXISTING_APP="" fi fi if [ -z "${EXISTING_APP:-}" ]; then # Create the OAuth2 application RESPONSE=$(curl -s -w "\n%{http_code}" \ -X POST "${API}/user/applications/oauth2" \ -H "Content-Type: application/json" \ -H "${AUTH_HEADER}" \ -d "{ \"name\": \"${OAUTH2_APP_NAME}\", \"redirect_uris\": [\"${OAUTH2_REDIRECT_URI}\"], \"confidential_client\": true }") BODY=$(echo "$RESPONSE" | head -n -1) CODE=$(echo "$RESPONSE" | tail -n 1) if [ "$CODE" = "201" ]; then OAUTH2_CLIENT_ID=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])") OAUTH2_CLIENT_SECRET=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_secret'])") echo " ✓ OAuth2 app '${OAUTH2_APP_NAME}' created" else echo " ✗ Failed to create OAuth2 app: HTTP ${CODE}" echo " Response: ${BODY}" exit 1 fi fi echo " Client ID: ${OAUTH2_CLIENT_ID}" echo " Client Secret: ${OAUTH2_CLIENT_SECRET:0:8}..." echo "" # ------------------------------------------------------- # Step 3: Create stonks-oracle repository # ------------------------------------------------------- echo "--- Step 3: Create '${REPO_NAME}' repository ---" # Check if repo already exists REPO_CHECK=$(curl -s -o /dev/null -w "%{http_code}" \ -H "${AUTH_HEADER}" \ "${API}/repos/${GITEA_ADMIN_USER}/${REPO_NAME}") if [ "$REPO_CHECK" = "200" ]; then echo " ✓ Repository '${REPO_NAME}' already exists" else RESPONSE=$(curl -s -w "\n%{http_code}" \ -X POST "${API}/user/repos" \ -H "Content-Type: application/json" \ -H "${AUTH_HEADER}" \ -d "{ \"name\": \"${REPO_NAME}\", \"description\": \"Stonks Oracle — AI market intelligence and paper-trading platform\", \"private\": false, \"auto_init\": false }") BODY=$(echo "$RESPONSE" | head -n -1) CODE=$(echo "$RESPONSE" | tail -n 1) if [ "$CODE" = "201" ]; then echo " ✓ Repository '${REPO_NAME}' created" elif [ "$CODE" = "409" ]; then echo " ✓ Repository '${REPO_NAME}' already exists (409)" else echo " ✗ Failed to create repository: HTTP ${CODE}" echo " Response: ${BODY}" exit 1 fi fi echo "" # ------------------------------------------------------- # Output OAuth2 credentials # ------------------------------------------------------- echo "--- OAuth2 Credentials ---" echo "GITEA_CLIENT_ID=${OAUTH2_CLIENT_ID}" echo "GITEA_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}" # Write to env file for runmefirst.sh to source cat > "${OAUTH2_ENV_FILE}" <