#!/bin/bash RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}ℹ️ $1${NC}" } log_success() { echo -e "${GREEN}✅ $1${NC}" } log_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } log_error() { echo -e "${RED}❌ $1${NC}" } show_banner() { echo "" echo -e "${YELLOW}════════════════════════════════════════════${NC}" echo -e "${YELLOW} $1${NC}" echo -e "${YELLOW}════════════════════════════════════════════${NC}" echo "" } load_config_or_defaults() { if [ ! -f "$CONFIG_FILE" ]; then log_warning "未找到配置文件,使用默认值" return fi source "$CONFIG_FILE" log_success "配置文件已加载: $CONFIG_FILE" } check_command_exists() { if command -v "$1" >/dev/null 2>&1; then return 0 else return 1 fi } check_prerequisites() { show_banner "检查前置条件" local missing_tools=() for cmd in docker curl jq; do if check_command_exists "$cmd"; then log_success "$cmd 已安装" else log_error "$cmd 未安装" missing_tools+=("$cmd") fi done if [ ${#missing_tools[@]} -ne 0 ]; then log_error "缺少必要工具: ${missing_tools[*]}" log_info "请安装后重试:brew install ${missing_tools[*]}" return 1 fi if [ ! -f ~/.ssh/id_rsa ] && [ ! -f ~/.ssh/id_ed25519 ]; then log_warning "未找到 SSH 密钥,将无法免密登录生产服务器" log_info "建议运行: ssh-keygen -t rsa -b 4096" fi log_success "前置条件检查通过" return 0 } wait_for_jenkins_ready() { show_banner "等待 Jenkins 就绪" local max_attempts=30 local attempt=1 while [ $attempt -le $max_attempts ]; do if curl -sf "${JENKINS_URL}/login" > /dev/null 2>&1; then log_success "Jenkins 已就绪 (${attempt}/${max_attempts})" return 0 fi log_info "等待 Jenkins 启动... (${attempt}/${max_attempts})" sleep 5 ((attempt++)) done log_error "Jenkins 启动超时!请手动检查:docker logs ${JENKINS_CONTAINER_NAME}" return 1 } jenkins_api_call() { local method="$1" local endpoint="$2" local data="$3" local auth="${JENKINS_ADMIN_USER}:${JENKINS_ADMIN_PASSWORD}" if [ -n "$data" ]; then curl -s -X "$method" \ --user "$auth" \ -H "Content-Type: application/json" \ -d "$data" \ "${JENKINS_URL}${endpoint}" 2>/dev/null else curl -s -X "$method" \ --user "$auth" \ "${JENKINS_URL}${endpoint}" 2>/dev/null fi } gitea_api_call() { local method="$1" local endpoint="$2" local data="$3" if [ -z "$GITEA_TOKEN" ]; then obtain_gitea_token fi if [ -n "$data" ]; then curl -s -X "$method" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "$data" \ "${GITEA_URL}/api/v1${endpoint}" 2>/dev/null else curl -s -X "$method" \ -H "Authorization: token ${GITEA_TOKEN}" \ "${GITEA_URL}/api/v1${endpoint}" 2>/dev/null fi } obtain_gitea_token() { log_info "获取 Gitea API Token..." local response=$(curl -s -X POST \ "${GITEA_URL}/api/v1/users/${GITEA_USERNAME}/tokens" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"jenkins-ci-token-$(date +%s)\", \"scopes\": [\"write:repository\", \"read:org\"] }") GITEA_TOKEN=$(echo "$response" | jq -r '.sha // empty') if [ -n "$GITEA_TOKEN" ]; then log_success "Gitea Token 获取成功" else log_error "Gitea Token 获取失败: $response" exit 1 fi } cleanup_temp_tokens() { log_info "清理临时 Token..." gitea_api_call "GET" "/users/${GITEA_USERNAME}/tokens" | jq -r '.[] | select(.name | startswith("jenkins-ci-token")) | .id' | while read token_id; do gitea_api_call "DELETE" "/users/${GITEA_USERNAME}/tokens/$token_id" > /dev/null done log_success "临时 Token 已清理" }