#!/bin/sh # Gitea Initialization Script for Fellowship DevOps Escape Room # Sets up Gitea with admin user, organization, and the LOTR SUT repository # This script runs as a one-shot container after Gitea starts up # # Key: We use docker-compose exec instead of docker exec for reliable container access set -e GITEA_URL="${GITEA_URL:-http://gitea:3000}" ADMIN_USER="${GITEA_ADMIN_USER:-fellowship}" ADMIN_PASS="${GITEA_ADMIN_PASSWORD:-fellowship123}" ADMIN_EMAIL="${GITEA_ADMIN_EMAIL:-gandalf@fellowship.local}" ORG_NAME="${GITEA_ORG_NAME:-fellowship-org}" REPO_NAME="${GITEA_REPO_NAME:-lotr-sut}" REPO_DESC="The Fellowship's Quest List — LOTR-themed SUT for DevOps tutorials" SUT_SOURCE_DIR="${SUT_SOURCE_DIR:-/sut-source}" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [gitea-init] $*" } warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [gitea-init] ⚠️ WARNING: $*" >&2 } error() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [gitea-init] ❌ ERROR: $*" >&2 return 1 } log "==========================================" log "Gitea Initialization — Fellowship DevOps" log "==========================================" log "Settings:" log " Gitea Container: ${GITEA_CONTAINER}" log " Admin User: ${ADMIN_USER}" log " Organization: ${ORG_NAME}" log " Repository: ${ORG_NAME}/${REPO_NAME}" log "==========================================" # Install required tools setup_tools() { log "Setting up tools..." if ! command -v curl > /dev/null 2>&1; then apk add --no-cache curl fi if ! command -v docker > /dev/null 2>&1; then apk add --no-cache docker-cli fi log "✓ Tools ready" } # Wait for Gitea to be ready wait_for_gitea() { log "Waiting for Gitea API to be ready at ${GITEA_URL}..." local max_attempts=60 local attempt=1 while [ $attempt -le $max_attempts ]; do if curl -sf "${GITEA_URL}/api/v1/version" > /dev/null 2>&1; then log "✓ Gitea API is ready" return 0 fi sleep 2 attempt=$((attempt + 1)) [ $((attempt % 10)) -eq 0 ] && log " Still waiting (${attempt}/${max_attempts})..." done error "Gitea did not become ready after $((max_attempts * 2)) seconds" return 1 } # Create the admin user using Gitea CLI via docker create_admin() { log "Creating admin user '${ADMIN_USER}'..." # Check if user already exists via API local existing_user existing_user=$(curl -s -u "${ADMIN_USER}:${ADMIN_PASS}" "${GITEA_URL}/api/v1/user" 2>/dev/null || echo "") if echo "$existing_user" | grep -q '"username"'; then log "✓ Admin user '${ADMIN_USER}' already exists" return 0 fi # Find gitea container by name matching (handles project prefix like fellowship-gitea-1) local gitea_container gitea_container=$(docker ps --format '{{.Names}}' | grep -E 'gitea$|gitea-1$|gitea-[\w-]*$' | head -1) if [ -z "$gitea_container" ]; then error "Could not find gitea container" return 1 fi log " Found gitea container: $gitea_container" # Use gitea CLI to create admin user via docker exec # Must run as 'git' user (not root) - Gitea refuses to run as root if docker exec -u git "$gitea_container" \ gitea admin user create \ --username "${ADMIN_USER}" \ --password "${ADMIN_PASS}" \ --email "${ADMIN_EMAIL}" \ --admin \ --must-change-password=false > /tmp/gitea_user_create.log 2>&1; then log "✓ Admin user '${ADMIN_USER}' created successfully" return 0 fi # Check if user already exists (might exist from previous run) if grep -q "already exists" /tmp/gitea_user_create.log 2>/dev/null; then log "✓ Admin user '${ADMIN_USER}' already exists" return 0 fi # If both methods fail, show error and return failure log "Creation output:" cat /tmp/gitea_user_create.log || true error "Failed to create admin user" return 1 } # Create organization via API (requires auth) create_org() { log "Creating organization '${ORG_NAME}'..." local response response=$(curl -s -X POST "${GITEA_URL}/api/v1/orgs" \ -u "${ADMIN_USER}:${ADMIN_PASS}" \ -H "Content-Type: application/json" \ -d "{ \"username\": \"${ORG_NAME}\", \"full_name\": \"The Fellowship of the Ring\", \"description\": \"One org to rule them all\", \"visibility\": \"public\" }" 2>&1) if echo "$response" | grep -q '"id"'; then log "✓ Organization '${ORG_NAME}' created" return 0 elif echo "$response" | grep -q "already exists\|account already exists"; then log "✓ Organization '${ORG_NAME}' already exists" return 0 else # Log the actual API response for debugging echo "$response" 1>&2 error "Failed to create organization" return 1 fi } # Create repository via API (requires auth) create_repo() { log "Creating repository '${ORG_NAME}/${REPO_NAME}'..." local status status=$(curl -s -o /dev/null -w "%{http_code}" \ -u "${ADMIN_USER}:${ADMIN_PASS}" \ "${GITEA_URL}/api/v1/repos/${ORG_NAME}/${REPO_NAME}" 2>/dev/null) if [ "$status" = "200" ]; then log "✓ Repository '${ORG_NAME}/${REPO_NAME}' already exists" return 0 fi local response response=$(curl -s -X POST "${GITEA_URL}/api/v1/orgs/${ORG_NAME}/repos" \ -u "${ADMIN_USER}:${ADMIN_PASS}" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"${REPO_NAME}\", \"description\": \"${REPO_DESC}\", \"private\": false, \"auto_init\": false, \"default_branch\": \"main\" }" 2>&1) if echo "$response" | grep -q '"id"'; then log "✓ Repository '${ORG_NAME}/${REPO_NAME}' created" return 0 elif echo "$response" | grep -q "already exists\|The repository already exists"; then log "✓ Repository '${ORG_NAME}/${REPO_NAME}' already exists" return 0 else # Log the actual API response for debugging echo "$response" 1>&2 error "Failed to create repository" return 1 fi } # Push SUT source code to Gitea (optional, skipped if repo has commits) push_sut_code() { log "Checking if SUT code needs to be pushed..." # Check if repo already has commits local commits commits=$(curl -s \ -u "${ADMIN_USER}:${ADMIN_PASS}" \ "${GITEA_URL}/api/v1/repos/${ORG_NAME}/${REPO_NAME}/commits?limit=1" \ 2>/dev/null | grep -c '"sha"' || echo "0") # Trim whitespace and handle invalid values commits=$(echo "$commits" | xargs) commits=${commits:-0} # Default to 0 if empty # Check if commits is a valid number and greater than 0 if [ "$commits" -gt 0 ] 2>/dev/null; then log "✓ Repository already has commits — skipping push" return 0 fi # Find the SUT source if [ ! -d "${SUT_SOURCE_DIR}" ]; then warn "SUT source directory not found at ${SUT_SOURCE_DIR}" warn "Skipping code push — repository will be created but empty" return 0 fi log " Source directory: ${SUT_SOURCE_DIR}" log " (Code push omitted for now — repository ready for manual commit)" return 0 } # Main initialization sequence main() { setup_tools || exit 1 if ! wait_for_gitea; then error "Aborting — Gitea is not available" exit 1 fi # Create admin user first (required for subsequent operations) if ! create_admin; then error "Failed to create admin user" exit 1 fi # Wait for admin credentials to be valid before using API log "Waiting for admin credentials to be recognized..." local max_attempts=15 local attempt=1 while [ $attempt -le $max_attempts ]; do if curl -sf -u "${ADMIN_USER}:${ADMIN_PASS}" \ "${GITEA_URL}/api/v1/user" > /dev/null 2>&1; then log "✓ Admin user is now authenticated" break fi sleep 1 attempt=$((attempt + 1)) [ $((attempt % 5)) -eq 0 ] && log " Still waiting (${attempt}/${max_attempts})..." done # Create organization if ! create_org; then warn "Failed to create organization (may already exist)" fi # Create repository if ! create_repo; then warn "Failed to create repository (may already exist)" fi # Push source code (optional) push_sut_code || true log "==========================================" log "✅ Gitea initialization complete!" log "==========================================" log " URL: ${GITEA_URL}" log " Admin: ${ADMIN_USER}" log " Repository: ${GITEA_URL}/${ORG_NAME}/${REPO_NAME}" log "==========================================" } # Run main initialization main "$@"