chore: 重构 OpenCode 命令和技能文档体系
- 新增:统一的 git 命令文档(add/commit/push/pull 等) - 新增:整合的 Gitea 技能文档(API、运行器、工作流等) - 新增:工作流模板(Android、Go、Node.js 等) - 移除:已弃用的旧命令脚本和发布脚本 - 改进:.gitignore 添加敏感文件保护规则 - 改进:AGENTS.md 完善了开发规范和示例 此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
This commit is contained in:
595
command/gitea-delete-runner.md
Normal file
595
command/gitea-delete-runner.md
Normal file
@@ -0,0 +1,595 @@
|
||||
---
|
||||
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
|
||||
|
||||
无需参数,运行后交互式选择。
|
||||
|
||||
```bash
|
||||
/gitea-delete-runner
|
||||
```
|
||||
|
||||
## AI 执行指导
|
||||
|
||||
当用户调用此命令时,AI 应该:
|
||||
|
||||
1. **获取并展示 runner 列表**:调用 Gitea API 获取服务器上的全局 runners,并以清晰的格式展示给用户
|
||||
2. **等待用户选择**:让用户选择要删除的 runner(序号、'all' 或 'q')
|
||||
3. **确认操作**:在删除前要求用户输入 'yes' 确认
|
||||
4. **执行删除**:按照三步流程删除选中的 runners
|
||||
5. **显示结果**:展示删除操作的详细结果
|
||||
|
||||
**注意**:此命令需要与用户进行多次交互,不要一次性执行所有步骤。
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### 1. Load Configuration
|
||||
|
||||
```bash
|
||||
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 列表,然后等待用户选择。
|
||||
|
||||
```bash
|
||||
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 根据用户输入执行相应部分):
|
||||
|
||||
```bash
|
||||
# 假设用户选择存储在变量 $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' 确认。
|
||||
|
||||
```bash
|
||||
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'),执行删除操作;否则取消。
|
||||
|
||||
```bash
|
||||
# 假设用户确认输入存储在 $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 执行**:显示删除操作的最终结果。
|
||||
|
||||
```bash
|
||||
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 完成后停止(推荐)
|
||||
- 强制立即停止(有风险)
|
||||
- **优雅停止**:先尝试 SIGTERM,2 秒后才使用 SIGKILL
|
||||
- **服务器注销**:自动从 Gitea 服务器注销 runner
|
||||
- **三步删除流程**:
|
||||
1. 从服务器注销
|
||||
2. 停止本地进程(检测 busy 状态)
|
||||
3. 删除本地配置
|
||||
- **清晰提示**:显示每个步骤的执行状态和警告信息
|
||||
- **批量删除支持**:可一次性删除所有 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. **步骤 1**:加载并验证 Gitea 配置
|
||||
2. **步骤 2**:获取并展示 runners 列表 → **等待用户选择**
|
||||
3. **步骤 3**:处理用户选择,验证输入
|
||||
4. **步骤 4**:显示删除警告和列表 → **等待用户确认**
|
||||
5. **步骤 5**:执行删除操作
|
||||
- 5.1: 从服务器注销
|
||||
- 5.2: 检查并停止本地进程
|
||||
- **如果 runner 正在执行 job(busy)** → **等待用户选择**(等待完成 or 强制停止)
|
||||
- 5.3: 删除本地配置
|
||||
6. **步骤 6**:显示操作结果摘要
|
||||
|
||||
**重要**:这是一个交互式命令,可能需要在以下位置等待用户输入:
|
||||
- 步骤 2: 选择要删除的 runner
|
||||
- 步骤 4: 确认删除操作
|
||||
- 步骤 5.2: 如果 runner 正在执行 job,选择等待或强制停止
|
||||
|
||||
不要一次性执行所有步骤。
|
||||
Reference in New Issue
Block a user