#!/bin/bash set -e echo "==========================================" echo " Gitea Runner Registration Script " echo "==========================================" echo "" # 检查 act_runner 是否安装 if ! command -v act_runner &> /dev/null; then echo "✗ act_runner is not installed!" echo "" echo "Please run the setup script first:" echo " docker-compose exec gitea-runner /data/setup.sh" exit 1 fi echo "✓ act_runner found: $(act_runner --version)" echo "" # 获取注册信息并验证 while true; do read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE # 验证 URL 格式 if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then echo "✗ Error: URL must start with http:// or https://" echo "" continue fi # 移除末尾的斜杠 GITEA_INSTANCE="${GITEA_INSTANCE%/}" echo "✓ URL validated: $GITEA_INSTANCE" break done read -p "Enter registration token: " GITEA_TOKEN if [ -z "$GITEA_TOKEN" ]; then echo "✗ Error: Token cannot be empty!" exit 1 fi read -p "Enter runner name (default: docker-runner): " RUNNER_NAME RUNNER_NAME=${RUNNER_NAME:-docker-runner} # 多个 label(逗号分隔,无空格) # ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18 read -p "Enter runner labels (default: ubuntu-22.04:host://ubuntu:22.04): " RUNNER_LABELS RUNNER_LABELS=${RUNNER_LABELS:-ubuntu-22.04:host://ubuntu:22.04} # 创建 runner 目录 RUNNER_DIR="/data/runners/${RUNNER_NAME}" mkdir -p "$RUNNER_DIR" cd "$RUNNER_DIR" echo "" echo "Registration Information:" echo " Instance: $GITEA_INSTANCE" echo " Name: $RUNNER_NAME" echo " Labels: $RUNNER_LABELS" echo " Directory: $RUNNER_DIR" echo "" # 检查是否已经注册 if [ -f ".runner" ] || [ -f "config.yaml" ]; then echo "⚠ Runner already exists in this directory!" read -p "Do you want to re-register? This will overwrite existing configuration. (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo "Registration cancelled." exit 0 fi echo "Cleaning up existing runner..." # 停止现有 runner echo "Stopping existing runner..." supervisorctl stop "runner-${RUNNER_NAME}" 2>/dev/null || true # 删除 supervisor 配置 rm -f "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" # 重新加载 supervisor supervisorctl reread 2>/dev/null || true supervisorctl update 2>/dev/null || true # 删除日志 rm -f "/var/log/supervisor/runner-${RUNNER_NAME}".*.log* # 删除旧配置和缓存 rm -f .runner config.yaml rm -rf cache fi # 执行注册 echo "" echo "Registering runner..." act_runner register \ --instance "$GITEA_INSTANCE" \ --token "$GITEA_TOKEN" \ --name "$RUNNER_NAME" \ --labels "$RUNNER_LABELS" \ --no-interactive if [ ! -f ".runner" ]; then echo "" echo "✗ Registration failed! .runner file not created." exit 1 fi echo "✓ Registration successful!" # 生成配置文件 echo "" echo "Generating config.yaml..." act_runner generate-config > config.yaml echo "✓ Configuration file generated!" # 创建缓存目录 mkdir -p cache # 使用 Python 修改配置(最可靠的方法) echo "" echo "Configuring runner settings..." if command -v python3 &> /dev/null; then python3 << PYEOF import yaml import sys try: # 读取生成的配置 with open('config.yaml', 'r') as f: config = yaml.safe_load(f) # 读取 .runner 获取实际注册的 labels import json with open('.runner', 'r') as f: runner_data = json.load(f) # 使用 .runner 中的 labels(这是实际注册的) registered_labels = runner_data.get('labels', []) # 修改配置 if 'runner' not in config: config['runner'] = {} # 使用实际注册的 labels config['runner']['labels'] = registered_labels config['runner']['capacity'] = 2 # 启用缓存 if 'cache' not in config: config['cache'] = {} config['cache']['enabled'] = True config['cache']['dir'] = './cache' # 保存配置 with open('config.yaml', 'w') as f: yaml.dump(config, f, default_flow_style=False, sort_keys=False) print("✓ Configuration updated using Python") print(f" - Labels: {registered_labels}") print(f" - Capacity: 2") print(f" - Cache enabled: ./cache") sys.exit(0) except Exception as e: print(f"✗ Python configuration failed: {e}", file=sys.stderr) sys.exit(1) PYEOF PYTHON_EXIT=$? if [ $PYTHON_EXIT -ne 0 ]; then echo "" echo "⚠ Python configuration failed, using basic sed..." # 基本的 sed 修改(只修改简单的值,不动 labels) sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true sed -i 's/enabled: false/enabled: true/g' config.yaml || true sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true echo "✓ Basic configuration applied" echo " Note: Please manually verify labels in config.yaml match .runner" fi else echo "⚠ Python3 not found, applying basic configuration..." # 基本的 sed 修改 sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true sed -i 's/enabled: false/enabled: true/g' config.yaml || true sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true echo "✓ Basic configuration applied" echo " Note: Labels will use act_runner defaults" fi # 验证配置文件 echo "" echo "Validating configuration..." # 检查 YAML 语法 if command -v python3 &> /dev/null; then python3 << PYEOF import yaml import sys try: with open('config.yaml', 'r') as f: yaml.safe_load(f) print("✓ config.yaml syntax is valid") sys.exit(0) except Exception as e: print(f"✗ config.yaml syntax error: {e}", file=sys.stderr) sys.exit(1) PYEOF if [ $? -ne 0 ]; then echo "" echo "✗ Configuration file has syntax errors!" echo " Backup available at: config.yaml.bak" exit 1 fi fi # 显示配置摘要 echo "" echo "Configuration Summary:" echo "-------------------------------------------" echo ".runner labels:" cat .runner | grep -A 10 '"labels"' | head -15 echo "" echo "config.yaml labels:" grep -A 5 "^ labels:" config.yaml | head -10 # 创建 supervisor 配置 echo "" echo "Creating supervisor configuration..." cat > "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" </dev/null || \ supervisorctl start "runner-${RUNNER_NAME}" # 等待启动 sleep 3 # 显示状态 RUNNER_STATUS=$(supervisorctl status "runner-${RUNNER_NAME}" 2>/dev/null || echo "UNKNOWN") echo "" echo "==========================================" echo "✓ Runner registered and started!" echo "==========================================" echo "" echo "Runner Information:" echo " Name: $RUNNER_NAME" echo " Directory: $RUNNER_DIR" echo " Status: $RUNNER_STATUS" echo "" echo "Configuration files:" echo " .runner: $(ls -lh .runner 2>/dev/null | awk '{print $5}' || echo 'N/A')" echo " config.yaml: $(ls -lh config.yaml 2>/dev/null | awk '{print $5}' || echo 'N/A')" echo "" echo "Useful commands:" echo " View logs: docker-compose exec gitea-runner /data/manage.sh logs ${RUNNER_NAME}" echo " Follow logs: docker-compose exec gitea-runner /data/manage.sh follow ${RUNNER_NAME}" echo " Check status: docker-compose exec gitea-runner /data/manage.sh status" echo " Restart: docker-compose exec gitea-runner /data/manage.sh restart ${RUNNER_NAME}" echo "" # 显示最近的日志 if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" ]; then echo "Recent logs:" echo "-------------------------------------------" tail -n 20 "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" 2>/dev/null || echo "No logs yet" echo "" fi # 检查是否有错误 if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" ]; then # 只查找 error/fatal/panic 级别的日志 ERR_CONTENT=$(grep -E 'level=(error|fatal|panic)' \ "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" | tail -n 5 2>/dev/null) if [ -n "$ERR_CONTENT" ]; then echo "❌ Recent errors detected:" echo "-------------------------------------------" echo "$ERR_CONTENT" echo "" echo "Check full error log with:" echo " docker-compose exec gitea-runner cat /var/log/supervisor/runner-${RUNNER_NAME}.err.log" fi fi