- 新增:统一的 git 命令文档(add/commit/push/pull 等) - 新增:整合的 Gitea 技能文档(API、运行器、工作流等) - 新增:工作流模板(Android、Go、Node.js 等) - 移除:已弃用的旧命令脚本和发布脚本 - 改进:.gitignore 添加敏感文件保护规则 - 改进:AGENTS.md 完善了开发规范和示例 此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
22 KiB
22 KiB
description
| description |
|---|
| Delete a Gitea runner configuration (interactive) |
gitea-delete-runner
删除 Gitea Runner 配置(交互式选择)。
命令说明
此命令用于从 Gitea 服务器删除 runner 配置。支持交互式选择单个或所有 runners。
重要:这是一个可执行命令,AI 应该按照以下步骤执行操作,并与用户进行交互。
Features
- 显示 Gitea 服务器上的全局 runners
- 交互式选择要删除的 runner
- 支持删除单个或所有 runners
- 删除 runner 配置目录(包括 cache 和 workspace)
- 停止运行中的 runner 进程
- 自动从 Gitea 服务器注销 runner
- 安全确认机制(需要用户输入 'yes')
User Input Format
无需参数,运行后交互式选择。
/gitea-delete-runner
AI 执行指导
当用户调用此命令时,AI 应该:
- 获取并展示 runner 列表:调用 Gitea API 获取服务器上的全局 runners,并以清晰的格式展示给用户
- 等待用户选择:让用户选择要删除的 runner(序号、'all' 或 'q')
- 确认操作:在删除前要求用户输入 'yes' 确认
- 执行删除:按照三步流程删除选中的 runners
- 显示结果:展示删除操作的详细结果
注意:此命令需要与用户进行多次交互,不要一次性执行所有步骤。
Implementation Steps
1. Load Configuration
config_file_main="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file_main" ]; then
echo "❌ 未找到 Gitea 配置文件"
echo " 路径: $config_file_main"
exit 1
fi
source "$config_file_main"
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
echo "❌ Gitea 配置不完整"
echo " 需要 GITEA_URL 和 GITEA_TOKEN"
exit 1
fi
2. Fetch and Display Runners
AI 执行:运行以下命令获取并显示 runners 列表,然后等待用户选择。
source "$HOME/.config/gitea/config.env"
echo "正在从 Gitea 服务器获取全局 runners..."
echo ""
# Fetch global runners from Gitea API
api_endpoint="${GITEA_URL}/api/v1/admin/actions/runners"
response=$(curl -s -H "Authorization: token $GITEA_TOKEN" "$api_endpoint")
if [ $? -ne 0 ] || [ -z "$response" ]; then
echo "❌ 无法连接到 Gitea 服务器"
exit 1
fi
# Parse runners using jq
if ! command -v jq &> /dev/null; then
echo "❌ 需要安装 jq 工具"
echo " 安装: brew install jq"
exit 1
fi
# Check if response is valid JSON
if ! echo "$response" | jq empty 2>/dev/null; then
echo "❌ API 返回数据格式错误"
echo " 请检查 Token 权限(需要 admin 权限)"
exit 1
fi
# Extract runner information (注意:API 返回格式是 {"runners": [...], "total_count": N})
runner_count=$(echo "$response" | jq '.runners | length')
if [ "$runner_count" -eq 0 ]; then
echo "⚠️ 服务器上没有全局 runners"
exit 0
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Gitea 全局 Runners (共 $runner_count 个)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Display runners with formatted output
echo "$response" | jq -r '.runners[] | [.id, .name, .status] | @tsv' | \
awk 'BEGIN{i=1} {
printf "%2d. %-30s [ID: %-5s] %s\n",
i++, $2, $1, ($3=="online"?"🟢 在线":"🔴 离线")
}'
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "选择要删除的 Runner"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo " 输入序号: 删除单个 runner"
echo " 输入 'all': 删除所有 runners"
echo " 输入 'q' 或 'quit': 取消"
echo ""
# Save runner data to temp file for later use
echo "$response" | jq -r '.runners[] | "\(.id)|\(.name)"' > /tmp/gitea_runners.txt
AI 指导:执行完上述命令后,等待用户输入选择(序号、'all' 或 'q')。
3. Process User Selection
AI 指导:根据用户的输入(从步骤 2 获取),执行相应的处理逻辑。
- 如果用户输入 'q' 或 'quit':取消操作,清理临时文件
- 如果用户输入 'all':准备删除所有 runners,进入步骤 4 确认
- 如果用户输入序号:验证并准备删除对应的 runner,进入步骤 4 确认
选择处理脚本(AI 根据用户输入执行相应部分):
# 假设用户选择存储在变量 $USER_SELECTION 中
if [ "$USER_SELECTION" = "q" ] || [ "$USER_SELECTION" = "quit" ]; then
echo "已取消"
rm -f /tmp/gitea_runners.txt
exit 0
fi
# Read runner data from temp file
mapfile -t runner_data < /tmp/gitea_runners.txt
runner_count=${#runner_data[@]}
if [ "$USER_SELECTION" = "all" ]; then
# Prepare to delete all runners
echo ""
echo "⚠️ 将删除所有 $runner_count 个 runners"
echo ""
# 继续到步骤 4 显示警告并确认
else
# Validate selection is a number
if ! [[ "$USER_SELECTION" =~ ^[0-9]+$ ]]; then
echo "❌ 无效的选择"
rm -f /tmp/gitea_runners.txt
exit 1
fi
# Validate selection is in range
if [ "$USER_SELECTION" -lt 1 ] || [ "$USER_SELECTION" -gt "$runner_count" ]; then
echo "❌ 选择超出范围 (1-$runner_count)"
rm -f /tmp/gitea_runners.txt
exit 1
fi
# Get selected runner info
selected_data="${runner_data[$((USER_SELECTION-1))]}"
IFS='|' read -r id name <<< "$selected_data"
echo ""
echo "已选择: $name (ID: $id)"
echo ""
# 继续到步骤 4 显示警告并确认
fi
4. Display Warning and Get Confirmation
AI 执行:显示删除警告,列出将要删除的 runners,然后等待用户输入 'yes' 确认。
echo "⚠️ 警告: 此操作将执行以下操作:"
echo " - 从 Gitea 服务器注销 runner"
echo " - 停止本地运行的 runner 进程"
echo " - 删除 runner 配置文件"
echo " - 删除 cache 和 workspace 目录"
echo " - 删除所有相关数据"
echo ""
# List runners to be deleted
if [ "$USER_SELECTION" = "all" ]; then
echo "将删除以下 runners:"
cat /tmp/gitea_runners.txt | while IFS='|' read -r id name; do
echo " - $name (ID: $id)"
done
else
# Single runner already displayed in step 3
:
fi
echo ""
AI 指导:显示完警告后,等待用户输入确认('yes' 继续,其他取消)。
5. Execute Deletion
AI 执行:如果用户确认(输入 'yes'),执行删除操作;否则取消。
# 假设用户确认输入存储在 $USER_CONFIRM 中
if [ "$USER_CONFIRM" != "yes" ]; then
echo "已取消"
rm -f /tmp/gitea_runners.txt
exit 0
fi
source "$HOME/.config/gitea/config.env"
echo "开始删除..."
echo ""
success_count=0
fail_count=0
runners_dir="$HOME/.config/gitea/runners"
# Process all selected runners
while IFS='|' read -r runner_id runner_name; do
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "删除: $runner_name (ID: $runner_id)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Find local runner directory by ID (处理 runners/* 不存在的情况)
runner_dir=""
if [ -d "$runners_dir" ]; then
shopt -s nullglob # 避免 * 无匹配时报错
for dir in "$runners_dir"/*; do
if [ -f "$dir/.runner" ]; then
local_id=$(jq -r '.id // ""' "$dir/.runner" 2>/dev/null)
if [ "$local_id" = "$runner_id" ]; then
runner_dir="$dir"
break
fi
fi
done
shopt -u nullglob
fi
# Step 1: Unregister from Gitea server
echo "[1/3] 从 Gitea 服务器注销..."
api_endpoint="${GITEA_URL}/api/v1/admin/actions/runners/${runner_id}"
http_code=$(curl -s -w "%{http_code}" -o /dev/null \
-X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$api_endpoint")
if [ "$http_code" = "204" ]; then
echo " ✓ 已从服务器注销"
else
echo " ⚠️ 注销失败 (HTTP $http_code)"
fi
# Step 2: Stop local process if running
echo "[2/3] 检查本地进程..."
if [ -n "$runner_dir" ] && [ -f "$runner_dir/config.yaml" ]; then
config_file="$runner_dir/config.yaml"
if pgrep -f "act_runner daemon --config $config_file" > /dev/null 2>&1; then
pid=$(pgrep -f "act_runner daemon --config $config_file")
# Check if runner is busy (executing jobs)
# 从服务器获取 runner 的 busy 状态
runner_info=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/actions/runners/${runner_id}")
is_busy=$(echo "$runner_info" | jq -r '.busy // false')
if [ "$is_busy" = "true" ]; then
echo " ⚠️ 警告: Runner 正在执行 job!"
echo " 强制停止可能导致 job 中断和数据不一致"
echo ""
echo " 选项:"
echo " 1. 等待 job 完成后再停止(推荐)"
echo " 2. 强制立即停止"
echo ""
# AI 应在此处等待用户选择
# 假设用户选择存储在 $STOP_CHOICE 中
if [ "$STOP_CHOICE" = "1" ]; then
echo " 等待 job 完成..."
# 轮询检查 runner 是否仍然 busy
max_wait=300 # 最多等待 5 分钟
waited=0
while [ $waited -lt $max_wait ]; do
sleep 10
waited=$((waited + 10))
runner_info=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/actions/runners/${runner_id}")
is_busy=$(echo "$runner_info" | jq -r '.busy // false')
if [ "$is_busy" = "false" ]; then
echo " ✓ Job 已完成"
break
fi
echo " 仍在执行... (已等待 ${waited}s)"
done
if [ $waited -ge $max_wait ]; then
echo " ⚠️ 等待超时,将强制停止"
fi
else
echo " ⚠️ 用户选择强制停止"
fi
fi
# 优雅停止 runner
echo " 正在停止进程 (PID: $pid)..."
kill "$pid" 2>/dev/null
sleep 2
# 如果进程还在运行,强制杀死
if pgrep -f "act_runner daemon --config $config_file" > /dev/null 2>&1; then
echo " 进程未响应,强制终止..."
kill -9 "$pid" 2>/dev/null
sleep 1
fi
# 验证进程已停止
if pgrep -f "act_runner daemon --config $config_file" > /dev/null 2>&1; then
echo " ❌ 无法停止进程"
else
echo " ✓ 进程已停止"
fi
else
echo " ✓ 未运行"
fi
else
echo " ⓘ 未找到本地配置"
fi
# Step 3: Delete local directory
echo "[3/3] 删除本地配置..."
if [ -n "$runner_dir" ] && [ -d "$runner_dir" ]; then
rm -rf "$runner_dir"
if [ ! -d "$runner_dir" ]; then
echo " ✓ 本地配置已删除"
((success_count++))
else
echo " ❌ 删除失败"
((fail_count++))
fi
else
# Server runner deleted, but no local config
((success_count++))
echo " ⓘ 无本地配置需要删除"
fi
echo ""
done < /tmp/gitea_runners.txt
# Cleanup temp file
rm -f /tmp/gitea_runners.txt
6. Display Summary
AI 执行:显示删除操作的最终结果。
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "删除完成"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "成功: $success_count 个"
if [ $fail_count -gt 0 ]; then
echo "失败: $fail_count 个"
fi
echo ""
echo "管理命令:"
echo " 查看剩余 runners: /gitea-list-runners"
echo " 创建新 runner: /gitea-create-runner"
echo ""
AI 指导:删除完成后,可以选择性地验证服务器上的 runner 数量,确认删除成功。
Output Example
Example 1: Delete Single Runner
正在从 Gitea 服务器获取全局 runners...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Gitea 全局 Runners (共 3 个)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. runner-mac-mini4 [ID: 42 ] 🟢 在线
系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30
2. runner-macbook-pro [ID: 43 ] 🔴 离线
系统: darwin 架构: arm64 最后在线: 2026-01-10 18:45
3. runner-linux-server [ID: 44 ] 🟢 在线
系统: linux 架构: amd64 最后在线: 2026-01-12 10:25
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
选择要删除的 Runner
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入序号: 删除单个 runner
输入 'all': 删除所有 runners
输入 'q' 或 'quit': 取消
请选择: 2
已选择: runner-macbook-pro (ID: 43)
⚠️ 警告: 此操作将执行以下操作:
- 从 Gitea 服务器注销 runner
- 停止本地运行的 runner 进程
- 删除 runner 配置文件
- 删除 cache 和 workspace 目录
- 删除所有相关数据
确认删除? 输入 'yes' 继续: yes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除: runner-macbook-pro (ID: 43)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1/3] 从 Gitea 服务器注销...
✓ 已从服务器注销
[2/3] 检查本地进程...
✓ 未运行
[3/3] 删除本地配置...
✓ 本地配置已删除
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
成功: 1 个
管理命令:
查看剩余 runners: /gitea-list-runners
创建新 runner: /gitea-create-runner
Example 2: Delete All Runners
正在从 Gitea 服务器获取全局 runners...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Gitea 全局 Runners (共 2 个)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. runner-mac-mini4 [ID: 42 ] 🟢 在线
系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30
2. runner-linux-server [ID: 44 ] 🟢 在线
系统: linux 架构: amd64 最后在线: 2026-01-12 10:25
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
选择要删除的 Runner
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入序号: 删除单个 runner
输入 'all': 删除所有 runners
输入 'q' 或 'quit': 取消
请选择: all
⚠️ 将删除所有 2 个 runners
⚠️ 警告: 此操作将执行以下操作:
- 从 Gitea 服务器注销 runner
- 停止本地运行的 runner 进程
- 删除 runner 配置文件
- 删除 cache 和 workspace 目录
- 删除所有相关数据
将删除 2 个 runners:
- runner-mac-mini4 (ID: 42)
- runner-linux-server (ID: 44)
确认删除? 输入 'yes' 继续: yes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除: runner-mac-mini4 (ID: 42)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1/3] 从 Gitea 服务器注销...
✓ 已从服务器注销
[2/3] 检查本地进程...
正在停止进程 (PID: 12345)...
✓ 进程已停止
[3/3] 删除本地配置...
✓ 本地配置已删除
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除: runner-linux-server (ID: 44)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[1/3] 从 Gitea 服务器注销...
✓ 已从服务器注销
[2/3] 检查本地进程...
ⓘ 未找到本地配置
[3/3] 删除本地配置...
ⓘ 无本地配置需要删除
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
删除完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
成功: 2 个
管理命令:
查看剩余 runners: /gitea-list-runners
创建新 runner: /gitea-create-runner
Safety Features
- 服务器数据优先:直接从 Gitea 服务器获取 runner 列表,确保准确性
- 交互式选择:支持选择单个或所有 runners,避免误删
- 双重确认:需要输入 'yes' 进行最终确认(防止误删)
- Busy 状态检测:检查 runner 是否正在执行 job
- 如果 runner 正在执行 job,给用户选择:
- 等待 job 完成后停止(推荐)
- 强制立即停止(有风险)
- 如果 runner 正在执行 job,给用户选择:
- 优雅停止:先尝试 SIGTERM,2 秒后才使用 SIGKILL
- 服务器注销:自动从 Gitea 服务器注销 runner
- 三步删除流程:
- 从服务器注销
- 停止本地进程(检测 busy 状态)
- 删除本地配置
- 清晰提示:显示每个步骤的执行状态和警告信息
- 批量删除支持:可一次性删除所有 runners
- 错误处理:各步骤独立执行,部分失败不影响其他操作
- 超时保护:等待 job 完成最多 5 分钟,超时后强制停止
Technical Notes
- 必需工具:需要安装
jq工具(brew install jq) - 权限要求:需要 Gitea admin 权限(全局 runner 管理)
- 配置文件:读取
~/.config/gitea/config.env获取 API 配置 - 本地匹配:通过 runner ID 匹配本地配置目录
- 服务器同步:从服务器注销后再删除本地配置
- 无本地配置:如果只存在服务器记录,仅注销服务器端
- 取消操作:输入 'q' 或 'quit' 可随时取消
- 临时文件:使用
/tmp/gitea_runners.txt存储临时数据,操作完成后自动清理 - API 格式:Gitea API 返回格式为
{"runners": [...], "total_count": N},不是直接的数组 - Busy 检测:通过 API 的
busy字段判断 runner 是否正在执行 job - 停止信号:
kill $pid(SIGTERM): 优雅停止,给进程清理资源的机会kill -9 $pid(SIGKILL): 强制终止,无法被捕获或忽略
- 等待策略:如果 runner busy,最多等待 5 分钟(300 秒),每 10 秒检查一次状态
AI 执行流程总结
当用户调用 /gitea-delete-runner 时,AI 应该按以下流程执行:
- 步骤 1:加载并验证 Gitea 配置
- 步骤 2:获取并展示 runners 列表 → 等待用户选择
- 步骤 3:处理用户选择,验证输入
- 步骤 4:显示删除警告和列表 → 等待用户确认
- 步骤 5:执行删除操作
- 5.1: 从服务器注销
- 5.2: 检查并停止本地进程
- 如果 runner 正在执行 job(busy) → 等待用户选择(等待完成 or 强制停止)
- 5.3: 删除本地配置
- 步骤 6:显示操作结果摘要
重要:这是一个交互式命令,可能需要在以下位置等待用户输入:
- 步骤 2: 选择要删除的 runner
- 步骤 4: 确认删除操作
- 步骤 5.2: 如果 runner 正在执行 job,选择等待或强制停止
不要一次性执行所有步骤。