Files
stonks-oracle/pipelines/gitea/setup.sh
T

290 lines
10 KiB
Bash
Executable File

#!/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 " ✓ OAuth2 app exists, secret stored in Woodpecker DB (not recreating)"
# Write client_id only — secret is only available on first creation
cat > "${OAUTH2_ENV_FILE}" <<EOF
# Generated by gitea/setup.sh
# Secret only available on first creation — Woodpecker DB has it
GITEA_CLIENT_ID=${OAUTH2_CLIENT_ID}
GITEA_CLIENT_SECRET=EXISTING_APP_SECRET_IN_WOODPECKER_DB
EOF
echo ""
echo " ✓ Credentials written to ${OAUTH2_ENV_FILE}"
echo ""
echo "=== Gitea Setup Complete ==="
exit 0
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}" <<EOF
# Generated by gitea/setup.sh — do not edit manually
GITEA_CLIENT_ID=${OAUTH2_CLIENT_ID}
GITEA_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}
EOF
echo ""
echo " ✓ Credentials written to ${OAUTH2_ENV_FILE}"
echo ""
echo "=== Gitea Setup Complete ==="