lotr-sut/gitea/init.sh
Fellowship Scholar f6a5823439 init commit
2026-03-29 20:07:56 +00:00

282 lines
8.8 KiB
Bash
Executable File

#!/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 "$@"