# Gitea Runner 管理 完整的 Gitea Act Runner 创建、注册、配置和管理指南。 ## 概述 Gitea Act Runner 是 Gitea Actions 的 CI/CD 执行器,兼容 GitHub Actions workflow 语法。 ### Runner 级别 | 级别 | 作用域 | 权限要求 | 适用场景 | |------|--------|---------|---------| | **全局 Runner** | 所有组织和仓库 | 管理员 Token | 共享资源、统一管理 | | **组织 Runner** | 特定组织 | 组织管理权限 | 组织内项目共享 | | **仓库 Runner** | 特定仓库 | 仓库管理权限 | 独立项目使用 | **推荐**: - 小团队或个人使用:**全局 Runner**(统一管理,配置简单) - 企业多组织:**组织 Runner**(隔离资源,权限分离) ### 执行模式 | 模式 | 环境 | 适用场景 | Android SDK | |------|------|---------|-------------| | **Host Mode** | Native macOS/Linux | Android/iOS 构建、原生工具链 | macOS ARM64 支持 | | Docker Mode | Linux 容器 | 跨平台构建 | Linux ARM64 不支持 | **推荐**:macOS ARM64 使用 **Host Mode** 以支持 Android SDK。 ## Runner 目录结构 所有 Runner 配置统一管理在: ``` ~/.config/gitea/runners/ ├── runner-macbook-pro/ # Runner 1 │ ├── .runner # 注册信息(JSON) │ ├── config.yaml # Runner 配置 │ ├── cache/ # Cache 目录 │ └── workspace/ # 工作目录 └── runner-mac-mini/ # Runner 2 └── ... ``` ## 前置要求 ### 1. 安装 act_runner ```bash # 使用 Homebrew(推荐) brew install act_runner # 或手动下载 curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-arm64 \ -o /usr/local/bin/act_runner chmod +x /usr/local/bin/act_runner # 验证安装 act_runner --version ``` ### 2. 安装开发工具(可选,根据需要) ```bash # Go(Go 项目构建) brew install go # Node.js(前端项目构建) brew install node@22 npm install -g pnpm # JDK 17(Android 项目构建) brew install openjdk@17 # Docker(容器构建) # 从 https://docker.com 安装 Docker Desktop ``` ### 3. 安装 Android SDK(Android 项目构建) ```bash # 使用 Homebrew brew install --cask android-commandlinetools # 或手动安装 mkdir -p ~/android-sdk/cmdline-tools cd ~/android-sdk/cmdline-tools curl -sL https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip -o cmdline-tools.zip unzip cmdline-tools.zip mv cmdline-tools latest rm cmdline-tools.zip # 接受许可并安装组件 yes | sdkmanager --licenses sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.0.0" ``` ### 4. 配置环境变量 添加到 `~/.zshrc` 或 `~/.bashrc`: ```bash # Go export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin # Java export JAVA_HOME=/opt/homebrew/opt/openjdk@17 export PATH=$PATH:$JAVA_HOME/bin # Android SDK export ANDROID_HOME=~/android-sdk export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin export PATH=$PATH:$ANDROID_HOME/platform-tools ``` 重新加载配置: ```bash source ~/.zshrc # 或 source ~/.bashrc ``` ### 5. 验证环境 ```bash go version # Go 1.23+ node --version # v22.x pnpm --version # Latest java -version # 17+ echo $ANDROID_HOME # SDK 路径 docker --version # Latest act_runner --version ``` ## 创建 Runner ### 使用命令快速创建 ```bash /gitea-create-runner ``` 此命令会自动: 1. 检查并安装 act_runner(如未安装) 2. 加载 Gitea 配置(如不存在则提示初始化) 3. 生成 runner 名称(基于主机名) 4. 检测系统环境并生成 labels 5. 创建 runner 目录结构 6. 生成 host 模式配置文件 7. 获取注册 token(优先全局) 8. 注册并启动 runner ### 详细创建流程 当运行 `/gitea-create-runner` 命令时,会执行以下步骤: #### 步骤 1: 检查 act_runner 安装 ```bash if command -v act_runner &> /dev/null; then echo "✓ act_runner 已安装" else echo "⚠️ act_runner 未安装,正在安装..." brew install act_runner fi ``` #### 步骤 2: 加载 Gitea 配置 ```bash config_file="$HOME/.config/gitea/config.env" if [ ! -f "$config_file" ]; then echo "❌ Gitea 配置不存在,请先初始化: /gitea-reset" exit 1 fi source "$config_file" ``` #### 步骤 3: 生成 Runner 名称 ```bash # 基于主机名自动生成 hostname=$(hostname -s) runner_name="runner-$hostname" # 或使用命令参数 # /gitea-create-runner my-custom-name ``` #### 步骤 4: 智能检测系统环境和 Labels ```bash # 检测操作系统 OS=$(uname -s) case "$OS" in Darwin) os_label="macOS" ;; Linux) os_label="ubuntu" ;; *) os_label="unknown" ;; esac # 检测架构 ARCH=$(uname -m) case "$ARCH" in arm64|aarch64) arch_label="ARM64" ;; x86_64) arch_label="x64" ;; *) arch_label="unknown" ;; esac # 生成组合 label combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]') # 生成建议的 labels suggested_labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host" echo "" echo "检测到系统环境:" echo " 操作系统: $OS ($os_label)" echo " 架构: $ARCH ($arch_label)" echo "" echo "建议的 Runner Labels:" echo " $suggested_labels" echo "" ``` **输出示例**: ``` 检测到系统环境: 操作系统: Darwin (macOS) 架构: arm64 (ARM64) 建议的 Runner Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host ``` #### 步骤 5: 创建 Runner 目录 ```bash runners_dir="$HOME/.config/gitea/runners" runner_dir="$runners_dir/$runner_name" # 检查是否已存在 if [ -d "$runner_dir" ]; then echo "❌ Runner '$runner_name' 已存在" echo "请使用其他名称或先删除现有 runner: /gitea-delete-runner $runner_name" exit 1 fi # 创建目录结构 mkdir -p "$runner_dir"/{cache,workspace} echo "✓ 创建目录: $runner_dir" ``` #### 步骤 6: 生成配置文件 **默认生成 Host Mode 配置**: ```yaml log: level: info runner: file: $HOME/.config/gitea/runners/$runner_name/.runner capacity: ${GITEA_RUNNER_CAPACITY:-2} timeout: ${GITEA_RUNNER_TIMEOUT:-3h} shutdown_timeout: 30s insecure: false fetch_timeout: 5s fetch_interval: 2s labels: - "self-hosted:host" - "macOS:host" - "ARM64:host" - "darwin-arm64:host" cache: enabled: true dir: "$HOME/.config/gitea/runners/$runner_name/cache" host: "127.0.0.1" port: 9000 host: workdir_parent: "$HOME/.config/gitea/runners/$runner_name/workspace" ``` **说明**: - 默认使用 Host Mode(支持 Android SDK、iOS 等原生工具) - 自动填充系统检测的 labels - 容量和超时可通过环境变量配置 #### 步骤 7: 获取注册 Token ```bash echo "" echo "正在获取 Runner 注册 Token..." # 默认尝试全局 Runner(管理员权限) echo "尝试创建全局 Runner(可用于所有组织和仓库)..." response=$(curl -s -w "\n%{http_code}" \ -H "Authorization: token $GITEA_TOKEN" \ "${GITEA_URL}/api/v1/admin/runners/registration-token") http_code=$(echo "$response" | tail -n1) body=$(echo "$response" | sed '$d') # 如果全局 Runner 失败(权限不足),降级到组织 Runner if [ "$http_code" != "200" ]; then echo "⚠️ 全局 Runner 权限不足 (HTTP $http_code)" echo " 全局 Runner 需要管理员 Token" echo "" echo "降级到组织 Runner..." runner_level="organization" if [ -n "$GITEA_DEFAULT_ORG" ]; then org_name="$GITEA_DEFAULT_ORG" else read -p "请输入组织名称: " org_input if [ -z "$org_input" ]; then echo "❌ 必须指定组织名称" exit 1 fi org_name="$org_input" fi echo "使用组织: $org_name" response=$(curl -s -w "\n%{http_code}" -X POST \ -H "Authorization: token $GITEA_TOKEN" \ "${GITEA_URL}/api/v1/orgs/$org_name/actions/runners/registration-token") http_code=$(echo "$response" | tail -n1) body=$(echo "$response" | sed '$d') else echo "✓ 使用全局 Runner" runner_level="global" fi if [ "$http_code" != "200" ]; then echo "❌ 获取注册 Token 失败 (HTTP $http_code)" echo "$body" exit 1 fi registration_token=$(echo "$body" | jq -r '.token') echo "✓ 注册 Token 已获取" ``` #### 步骤 8: 注册 Runner ```bash echo "" echo "正在注册 Runner..." act_runner register \ --config "$runner_dir/config.yaml" \ --instance "$GITEA_URL" \ --token "$registration_token" \ --name "$runner_name" \ --labels "$labels" \ --no-interactive if [ $? -eq 0 ]; then echo "✓ Runner 注册成功" else echo "❌ Runner 注册失败" exit 1 fi ``` #### 步骤 9: 自动启动 Runner ```bash echo "" echo "正在启动 Runner..." # 后台启动 Runner nohup act_runner daemon --config "$runner_dir/config.yaml" \ > "$runner_dir/runner.log" 2>&1 & runner_pid=$! # 等待 2 秒让 runner 启动 sleep 2 # 检查进程是否存在 if ps -p $runner_pid > /dev/null 2>&1; then echo "✓ Runner 已启动 (PID: $runner_pid)" else echo "⚠️ Runner 启动失败,请查看日志:" echo " tail -f $runner_dir/runner.log" exit 1 fi echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Runner 创建完成!" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" echo "Runner 名称: $runner_name" echo "Runner 级别: ${runner_level}" if [ "$runner_level" = "organization" ]; then echo "所属组织: ${org_name}" fi echo "PID: $runner_pid" echo "配置文件: $runner_dir/config.yaml" echo "工作目录: $runner_dir/workspace" echo "Cache 目录: $runner_dir/cache" echo "日志文件: $runner_dir/runner.log" echo "" echo "管理命令:" echo " 查看日志: tail -f $runner_dir/runner.log" echo " 停止 Runner: pkill -f 'act_runner daemon --config.*$runner_name'" echo " 查看所有: /gitea-list-runners" echo " 删除 Runner: /gitea-delete-runner $runner_name" echo "" ``` ## Label 设计指南 ### Label 格式 ``` label-name:mode ``` **Mode 类型**: - `host`: Host Mode(原生执行) - `docker://image`: Docker Mode(容器执行) ### 推荐 Labels #### macOS ARM64 ```yaml labels: - "self-hosted:host" - "macOS:host" - "ARM64:host" - "darwin-arm64:host" ``` #### Linux x64 ```yaml labels: - "self-hosted:host" - "ubuntu:host" - "x64:host" - "linux-x64:host" ``` #### Docker Mode ```yaml labels: - "ubuntu-latest:docker://catthehacker/ubuntu:act-latest" - "ubuntu-22.04:docker://catthehacker/ubuntu:act-latest" ``` ### Workflow 匹配 **方法 1: 组合 label(推荐,最精确)** ```yaml jobs: build: runs-on: darwin-arm64 ``` **方法 2: Label 数组(匹配多个条件)** ```yaml jobs: build: runs-on: [self-hosted, macOS, ARM64] ``` **方法 3: 仅操作系统** ```yaml jobs: build: runs-on: macOS ``` ## Runner 配置详解 ### Host Mode 配置 ```yaml log: level: info # 日志级别:debug/info/warn/error runner: file: /path/to/.runner # 注册信息文件 capacity: 2 # 并发任务数 timeout: 3h # 任务超时时间 shutdown_timeout: 30s # 关闭超时时间 insecure: false # 是否允许不安全连接 fetch_timeout: 5s # 获取任务超时 fetch_interval: 2s # 获取任务间隔 labels: - "label-name:host" # Runner labels cache: enabled: true # 启用缓存 dir: "/path/to/cache" # 缓存目录 host: "127.0.0.1" # 监听地址(仅本地) port: 9000 # 缓存服务端口 host: workdir_parent: "/path/to/workspace" # 工作目录父路径 ``` ### Docker Mode 配置 ```yaml log: level: info runner: file: /path/to/.runner capacity: 2 timeout: 3h labels: - "ubuntu-latest:docker://catthehacker/ubuntu:act-latest" cache: enabled: true dir: "/path/to/cache" host: "192.168.0.103" # 主机 IP(非 127.0.0.1) port: 9000 container: options: "--platform=linux/amd64" # 容器选项 network: "host" # 网络模式 ``` ## 多 Runner 缓存共享 ### 方案 A: Master-Slave 模式(推荐 2-3 个 runner) **主 Runner(cache server)**: ```yaml cache: enabled: true dir: "$HOME/.config/gitea/runners/runner-primary/cache" host: "0.0.0.0" # 监听所有接口 port: 9000 ``` **从 Runner(cache client)**: ```yaml cache: enabled: true server: "http://192.168.0.103:9000" # 主 runner IP dir: "$HOME/.config/gitea/runners/runner-secondary/cache" # 本地备份 host: "192.168.0.104" # 本 runner IP port: 9000 ``` ### 方案 B: NFS 共享存储(企业级) **1. 在主 Runner 上设置 NFS server**: ```bash # /etc/exports /Users/voson/.config/gitea/cache -alldirs -mapall=$(id -u):$(id -g) 192.168.0.0/24 sudo nfsd restart ``` **2. 在从 Runner 上挂载**: ```bash sudo mkdir -p /mnt/runner-cache sudo mount -t nfs 192.168.0.103:/Users/voson/.config/gitea/cache /mnt/runner-cache ``` ### 方案 C: 独立缓存(默认) 每个 runner 维护自己的缓存。首次构建下载依赖,后续构建使用本地缓存。 ## 缓存管理 ### Host Mode 缓存位置 | 缓存类型 | 位置 | 行为 | |---------|------|------| | Runner cache service | `config.cache.dir` | act_runner 管理 | | Gradle | `~/.gradle/` | 跨构建持久化 | | npm/pnpm | `~/.npm/`, `~/.pnpm-store/` | 跨构建持久化 | | Go modules | `~/go/pkg/mod/` | 跨构建持久化 | ### 缓存清理脚本 创建 `~/.config/gitea/cleanup-cache.sh`: ```bash #!/bin/bash set -e echo "清理 Gitea Runner 缓存..." runners_dir="$HOME/.config/gitea/runners" # 1. Runner cache(超过 7 天) find "$runners_dir"/*/cache -type f -mtime +7 -delete 2>/dev/null || true echo "✓ Runner cache 已清理" # 2. Gradle cache(超过 30 天) find ~/.gradle/caches -type f -mtime +30 -delete 2>/dev/null || true find ~/.gradle/caches -type d -empty -delete 2>/dev/null || true echo "✓ Gradle cache 已清理" # 3. npm cache 验证 npm cache verify echo "✓ npm cache 已验证" # 4. Workspace 清理(超过 7 天) find "$runners_dir"/*/workspace -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true echo "✓ Workspace 已清理" # 显示缓存大小 echo "" echo "当前缓存大小:" for runner in "$runners_dir"/*; do if [ -d "$runner" ]; then name=$(basename "$runner") size=$(du -sh "$runner/cache" 2>/dev/null | awk '{print $1}') echo " $name: ${size:-0B}" fi done echo "" echo "✓ 清理完成" ``` ### 定时清理 ```bash # 添加到 crontab chmod +x ~/.config/gitea/cleanup-cache.sh crontab -e # 每周日凌晨 3 点清理 0 3 * * 0 ~/.config/gitea/cleanup-cache.sh >> ~/.config/gitea/cleanup.log 2>&1 ``` ## Runner 管理命令 ### 列出所有 Runners ```bash /gitea-list-runners ``` ### 启动 Runner ```bash # 前台运行(调试用) act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml # 后台运行 nohup act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml \ > ~/.config/gitea/runners/runner-macbook-pro/runner.log 2>&1 & ``` ### 停止 Runner ```bash # 查找进程 ps aux | grep "act_runner daemon" # 停止特定 runner pkill -f "act_runner daemon --config.*runner-macbook-pro" # 停止所有 runners pkill -f "act_runner daemon" ``` ### 查看 Runner 日志 ```bash # 实时查看 tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log # 查看最近 100 行 tail -n 100 ~/.config/gitea/runners/runner-macbook-pro/runner.log ``` ### 删除 Runner ```bash /gitea-delete-runner runner-macbook-pro ``` ## 故障排查 ### 1. Android SDK 未找到 ```bash # 验证 ANDROID_HOME echo $ANDROID_HOME ls $ANDROID_HOME # 确保 runner 以安装 SDK 的用户身份运行 whoami ``` ### 2. JDK 版本错误 Android Gradle Plugin 8.x 需要 JDK 17+: ```bash java -version # 应显示: openjdk version "17.x.x" # 如果版本错误,更新 JAVA_HOME export JAVA_HOME=/opt/homebrew/opt/openjdk@17 ``` ### 3. 权限问题 ```bash # 确保 runner 用户拥有工作目录 chown -R $(whoami) ~/.config/gitea/runners chmod -R 755 ~/.config/gitea/runners ``` ### 4. Label 不匹配 ```bash # 检查注册的 labels cat ~/.config/gitea/runners/runner-macbook-pro/.runner | jq '.labels' # 确保 workflow runs-on 匹配 # Workflow: runs-on: darwin-arm64 # Runner: "darwin-arm64:host" label ``` ### 5. 缓存服务端口冲突 ```bash # 检查端口占用 lsof -i :9000 # 如果冲突,修改配置使用其他端口 vim ~/.config/gitea/runners/runner-macbook-pro/config.yaml # 修改: port: 9001 ``` ### 6. Runner 无法连接 Gitea ```bash # 测试 Gitea 连接 source ~/.config/gitea/config.env curl -s "$GITEA_URL/api/v1/version" | jq . # 检查防火墙设置 # 检查网络连接 ``` ### 7. Runner 已注册但不在线 ```bash # 检查 runner 进程 ps aux | grep "act_runner daemon" # 如果未运行,后台启动 runner(创建时会自动启动) nohup act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml \ > ~/.config/gitea/runners/runner-macbook-pro/runner.log 2>&1 & # 查看日志诊断问题 tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log ``` ## Quick Reference | 任务 | 命令 | |------|------| | 安装 runner | `brew install act_runner` | | 创建 runner | `/gitea-create-runner`(自动安装、配置、启动)| | 列出 runners | `/gitea-list-runners` | | 删除 runner | `/gitea-delete-runner` | | 手动启动 | `nohup act_runner daemon --config > 2>&1 &` | | 停止 runner | `pkill -f "act_runner daemon --config.*"` | | 查看状态 | `ps aux \| grep act_runner` | | 查看日志 | `tail -f /runner.log` | | 清理缓存 | `~/.config/gitea/cleanup-cache.sh` | ## 相关资源 - [Gitea Actions 文档](https://docs.gitea.com/usage/actions/overview) - [Act Runner 文档](https://docs.gitea.com/usage/actions/act-runner) - [Android SDK 命令行工具](https://developer.android.com/studio/command-line) - [GitHub Actions Workflow 语法](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions) ## 版本 - **文档版本**: 1.0 - **最后更新**: 2026-01-12 - **兼容性**: act_runner 0.2.13+, macOS ARM64, Linux