322 lines
9.0 KiB
Bash
322 lines
9.0 KiB
Bash
#!/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" <<EOF
|
||
[program:runner-${RUNNER_NAME}]
|
||
command=/usr/local/bin/act_runner daemon --config ${RUNNER_DIR}/config.yaml
|
||
directory=${RUNNER_DIR}
|
||
autostart=true
|
||
autorestart=true
|
||
stderr_logfile=/var/log/supervisor/runner-${RUNNER_NAME}.err.log
|
||
stdout_logfile=/var/log/supervisor/runner-${RUNNER_NAME}.out.log
|
||
stdout_logfile_maxbytes=50MB
|
||
stdout_logfile_backups=10
|
||
stderr_logfile_maxbytes=50MB
|
||
stderr_logfile_backups=10
|
||
user=root
|
||
environment=HOME="/root"
|
||
EOF
|
||
|
||
echo "✓ Supervisor configuration created"
|
||
|
||
# 重新加载 supervisor
|
||
echo ""
|
||
echo "Reloading supervisor..."
|
||
supervisorctl reread
|
||
supervisorctl update
|
||
|
||
echo "Starting runner..."
|
||
sleep 2
|
||
# 启动 runner
|
||
supervisorctl restart "runner-${RUNNER_NAME}" 2>/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
|