Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dffa3fae12 |
@@ -1,52 +0,0 @@
|
||||
---
|
||||
description: 提交暂存文件,自动生成提交信息并创建版本标签
|
||||
---
|
||||
|
||||
Auto-generate a commit message for staged files, commit to the local repository, and create a version tag following semantic versioning.
|
||||
|
||||
Please follow the git workflow defined in `@skill/git/SKILL.md`:
|
||||
|
||||
1. **Check staging area** - Verify files are staged with `git diff --cached --name-only`
|
||||
- If empty, inform the user and stop
|
||||
2. **Collect information** - Run these commands in parallel:
|
||||
- `git status`
|
||||
- `git diff --cached`
|
||||
- `git log --oneline -10`
|
||||
- `git tag --list | sort -V | tail -5`
|
||||
- Read `@AGENTS.md` if it exists (repository type, version rules, project structure)
|
||||
3. **Detect repository type** - Polyrepo (tag: `1.2.0`) or Monorepo (tag: `subproject-1.2.0`)
|
||||
4. **Detect project type and version** - Check for version files:
|
||||
- iOS: `*.xcodeproj/project.pbxproj` → `MARKETING_VERSION`
|
||||
- Node.js: `package.json` → `version`
|
||||
- Android: `build.gradle(.kts)` → `versionName`
|
||||
- Go: Git tag only
|
||||
5. **Generate commit message** following Conventional Commits:
|
||||
- Format: `<type>(<scope>): <subject>`
|
||||
- Use Chinese for commit messages (macOS/Linux)
|
||||
- Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build
|
||||
- For monorepo, use subproject as scope if changes affect single subproject
|
||||
6. **Update version number** if needed:
|
||||
- feat: minor +1 (1.2.0 → 1.3.0)
|
||||
- fix/perf: patch +1 (1.2.3 → 1.2.4)
|
||||
- Breaking change: major +1 (1.2.3 → 2.0.0)
|
||||
- Only for user-perceivable changes (feat, fix, perf, breaking)
|
||||
- Add updated version file to staging
|
||||
7. **Commit changes** with generated message
|
||||
8. **Create version tag** if version was updated (unless user specified "skip tag"):
|
||||
- Polyrepo: `git tag -a "1.2.0" -m "commit message"`
|
||||
- Monorepo: `git tag -a "subproject-1.2.0" -m "commit message"`
|
||||
|
||||
**Options:**
|
||||
- User can input "skip tag" or "skip" to skip tag creation
|
||||
|
||||
**Display result in Chinese:**
|
||||
```
|
||||
✓ 提交成功
|
||||
|
||||
提交信息:[commit message]
|
||||
版本标签:[tag] (如果创建了)
|
||||
|
||||
要推送到远程仓库,请运行:/git-push
|
||||
```
|
||||
|
||||
**Important:** This command does NOT push to remote. Use `/git-push` to push commits and tags.
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
description: 提交暂存文件,创建版本标签并推送到远程仓库
|
||||
---
|
||||
|
||||
Complete workflow: auto-generate commit message, create version tag, commit, and push everything to remote repository.
|
||||
|
||||
This is the **all-in-one command** that combines `/git-commit` + push operations.
|
||||
|
||||
Please perform the following:
|
||||
|
||||
1-7. **Follow the same steps as `/git-commit`:**
|
||||
- Check staging area (must not be empty)
|
||||
- Analyze changes and repository type
|
||||
- Detect project type and version
|
||||
- Generate commit message (Conventional Commits, Chinese)
|
||||
- Update version number if needed
|
||||
- Commit changes
|
||||
- Create version tag
|
||||
|
||||
Refer to `/git-commit` for detailed steps or `@skill/git/SKILL.md` for complete workflow.
|
||||
|
||||
8. **Push commit to remote:**
|
||||
```bash
|
||||
git push origin $(git branch --show-current)
|
||||
```
|
||||
|
||||
9. **Push tag to remote** (only if tag was created):
|
||||
- Polyrepo: `git push origin <version>`
|
||||
- Monorepo: `git push origin <subproject>-<version>`
|
||||
|
||||
10. **Display result in Chinese:**
|
||||
```
|
||||
✓ 提交并推送成功
|
||||
|
||||
分支:[branch]
|
||||
提交信息:[commit message]
|
||||
版本标签:[tag] (如果创建了)
|
||||
|
||||
已推送到远程仓库:origin
|
||||
- 提交:[commit hash]
|
||||
- 标签:[tag]
|
||||
```
|
||||
|
||||
**Error handling:**
|
||||
- If staging area is empty: "暂存区为空,请先使用 `git add` 添加文件。"
|
||||
- If push fails (e.g., need to pull first): Show error in Chinese with suggested solutions
|
||||
- If remote rejects tag (already exists): Show error and suggest deleting local tag or updating version
|
||||
|
||||
**Options:**
|
||||
- User can input "skip tag" or "skip" to skip tag creation
|
||||
|
||||
**When to use:**
|
||||
- `/git-commit`: Local only, review before pushing
|
||||
- `/git-push`: Commit and push immediately
|
||||
- `/git-push-tags`: Push tags only (no commits)
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
description: 查看当前 Gitea 配置和 Runner 状态
|
||||
---
|
||||
|
||||
Display the current Gitea configuration and runner status.
|
||||
|
||||
## 工作目录
|
||||
|
||||
**macOS / Linux:**
|
||||
```
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
%USERPROFILE%\.config\gitea\
|
||||
```
|
||||
|
||||
Please perform the following:
|
||||
|
||||
1. **Check if configuration exists:**
|
||||
- Config file:
|
||||
- macOS/Linux: `~/.config/gitea/config.env`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\config.env`
|
||||
- If not exists, prompt user to run `/gitea-reset`
|
||||
|
||||
2. **Load and display configuration:**
|
||||
|
||||
**macOS / Linux:**
|
||||
```bash
|
||||
source ~/.config/gitea/config.env
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||
if ($_ -match '^([^=]+)=(.*)$') {
|
||||
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Show in Chinese:
|
||||
- Gitea URL
|
||||
- Default organization (if set)
|
||||
- Config file path (根据平台显示正确路径)
|
||||
|
||||
3. **Validate token and display user info:**
|
||||
- Call API: `GET ${GITEA_URL}/api/v1/user`
|
||||
- Header: `Authorization: token ${GITEA_TOKEN}`
|
||||
- Show: Token status (✓ 有效 / ✗ 无效), username, email
|
||||
|
||||
4. **Display runner information:**
|
||||
- Runners directory:
|
||||
- macOS/Linux: `~/.config/gitea/runners`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\runners`
|
||||
- Count configured runners
|
||||
- List each runner with status:
|
||||
- 🟢 运行中 (process running)
|
||||
- 🔴 已停止 (process not running)
|
||||
- ⚠️ 配置异常 (config file missing)
|
||||
|
||||
5. **Show management commands:**
|
||||
```
|
||||
管理命令:
|
||||
- 重置配置: /gitea-reset
|
||||
- 切换组织: /gitea-switch-org <org-name>
|
||||
- 列出 Runners: /gitea-list-runners
|
||||
- 创建仓库: /create-gitea-repo <repo-name>
|
||||
```
|
||||
|
||||
Use `jq` to parse JSON responses and `pgrep` to check runner process status.
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
description: 在 Gitea 上创建新的 Git 仓库
|
||||
---
|
||||
|
||||
Create a new Git repository on Gitea via API.
|
||||
|
||||
## 工作目录
|
||||
|
||||
**macOS / Linux:**
|
||||
```
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
%USERPROFILE%\.config\gitea\
|
||||
```
|
||||
|
||||
配置文件从该目录加载。
|
||||
|
||||
**User input format:**
|
||||
```
|
||||
$ARGUMENTS = [<owner>/]<repo> [private|public]
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
- `my-project` - Private repo under default org or current user
|
||||
- `ai/my-project` - Private repo under ai organization
|
||||
- `ai/my-project public` - Public repo under ai organization
|
||||
- `username/test private` - Private repo under username
|
||||
|
||||
Please perform the following:
|
||||
|
||||
1. **Load configuration:**
|
||||
|
||||
**macOS / Linux:**
|
||||
```bash
|
||||
source ~/.config/gitea/config.env
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||
if ($_ -match '^([^=]+)=(.*)$') {
|
||||
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- If not exists: prompt to run `/gitea-reset`
|
||||
|
||||
2. **Parse user input from `$ARGUMENTS`:**
|
||||
- Extract: owner (optional), repo (required), visibility (optional, default: private)
|
||||
- If no owner specified:
|
||||
- Use `GITEA_DEFAULT_ORG` if set
|
||||
- Otherwise get current user from API: `GET /api/v1/user`
|
||||
- Validate repo name: only letters, numbers, underscores, hyphens, dots
|
||||
|
||||
3. **Create repository via API:**
|
||||
- Try organization API first:
|
||||
```bash
|
||||
POST ${GITEA_URL}/api/v1/orgs/${owner}/repos
|
||||
Body: {
|
||||
"name": "${repo}",
|
||||
"private": true/false,
|
||||
"auto_init": false,
|
||||
"default_branch": "main"
|
||||
}
|
||||
```
|
||||
- If 404, try user API: `POST /api/v1/user/repos`
|
||||
- Handle response codes:
|
||||
- 201: Success
|
||||
- 409: Repository already exists
|
||||
- 404: Owner not found or no permission
|
||||
- Other: API error
|
||||
|
||||
4. **Extract repository info from response:**
|
||||
- `html_url` - Web URL
|
||||
- `clone_url` - HTTPS URL
|
||||
- `ssh_url` - SSH URL
|
||||
|
||||
5. **Ask user if they want to add remote:**
|
||||
- Check if current directory is a git repo
|
||||
- If not, ask to initialize: `git init`
|
||||
- Check if `origin` remote exists
|
||||
- Add or update remote: `git remote add/set-url origin <clone_url>`
|
||||
|
||||
6. **Display result in Chinese:**
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
仓库创建成功
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
名称: [owner]/[repo]
|
||||
可见性: [private/public]
|
||||
Web URL: [html_url]
|
||||
HTTPS URL: [clone_url]
|
||||
SSH URL: [ssh_url]
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Requires repo creation permission in token
|
||||
- Organization and user repositories use different API endpoints
|
||||
- Default branch is `main` (not `master`)
|
||||
@@ -1,770 +0,0 @@
|
||||
---
|
||||
description: 创建并启动 Gitea Actions Runner(默认使用 host 模式)
|
||||
agent: general
|
||||
subtask: true
|
||||
---
|
||||
|
||||
# 创建并启动 Gitea Actions Runner
|
||||
|
||||
你的任务是创建并启动一个 Gitea Actions Runner(默认使用 host 模式)。
|
||||
|
||||
## 工作目录
|
||||
|
||||
**macOS / Linux:**
|
||||
```
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
%USERPROFILE%\.config\gitea\
|
||||
```
|
||||
|
||||
所有 Runner 配置、缓存、工作区都存储在该目录的 `runners/` 子目录下。
|
||||
|
||||
## 核心功能要求
|
||||
|
||||
请按照以下步骤执行:
|
||||
|
||||
1. **检查 act_runner 安装**
|
||||
- 检查 act_runner 是否已安装(使用 `command -v act_runner`)
|
||||
- 如果未安装,使用 Homebrew 自动安装:`brew install act_runner`
|
||||
- 如果 Homebrew 不存在,提示用户安装 Homebrew
|
||||
- 验证安装成功后显示版本信息
|
||||
|
||||
2. **加载 Gitea 配置**
|
||||
- 从配置文件加载配置:
|
||||
- macOS/Linux: `~/.config/gitea/config.env`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\config.env`
|
||||
- 如果配置文件不存在,提示用户运行 `/gitea-reset` 初始化
|
||||
- 验证必需的配置项:`GITEA_URL` 和 `GITEA_TOKEN`
|
||||
- 显示加载成功的配置信息
|
||||
|
||||
3. **生成 Runner 名称**
|
||||
- 如果用户提供了参数 `$ARGUMENTS`,使用该名称
|
||||
- 否则默认基于主机名生成:`runner-$(hostname -s)`
|
||||
- 验证名称只包含字母、数字、下划线和连字符
|
||||
|
||||
4. **检查 Runner 是否已存在**
|
||||
- 检查 Runner 目录:
|
||||
- macOS/Linux: `~/.config/gitea/runners/$runner_name`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\runners\$runner_name`
|
||||
- 如果已存在,提示用户可选操作:
|
||||
- 使用其他名称
|
||||
- 删除现有 runner(使用 `/gitea-delete-runner`)
|
||||
- 查看所有 runners(使用 `/gitea-list-runners`)
|
||||
|
||||
5. **检测系统环境**
|
||||
- 检测操作系统(macOS/Linux)
|
||||
- 检测架构(ARM64/x64)
|
||||
- 生成 host 模式的 labels:
|
||||
- `self-hosted:host`
|
||||
- `{os_label}:host`(如 `macOS:host`)
|
||||
- `{arch_label}:host`(如 `ARM64:host`)
|
||||
- `{combined}:host`(如 `darwin-arm64:host`)
|
||||
|
||||
6. **创建 Runner 目录结构**
|
||||
- 创建目录结构:
|
||||
- macOS/Linux: `~/.config/gitea/runners/$runner_name/{cache,workspace}`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\runners\$runner_name\{cache,workspace}`
|
||||
- 验证目录创建成功
|
||||
|
||||
7. **生成配置文件**
|
||||
- 创建 `config.yaml`,使用 host 模式配置
|
||||
- 从环境变量读取可选配置:
|
||||
- `GITEA_RUNNER_CAPACITY`(默认 2)
|
||||
- `GITEA_RUNNER_TIMEOUT`(默认 3h)
|
||||
- 配置要点:
|
||||
- log level: info
|
||||
- runner.capacity: 并发任务数
|
||||
- runner.timeout: 任务超时
|
||||
- cache: 启用缓存
|
||||
- host.workdir_parent: 工作目录路径
|
||||
- labels: 使用检测到的系统 labels
|
||||
|
||||
8. **获取注册 Token**
|
||||
- 优先尝试创建全局 Runner(需要管理员权限)
|
||||
- API: `GET ${GITEA_URL}/api/v1/admin/runners/registration-token`
|
||||
- Header: `Authorization: token ${GITEA_TOKEN}`
|
||||
- 如果返回 403/权限不足,自动降级到组织 Runner
|
||||
- 使用 `GITEA_DEFAULT_ORG` 作为组织名
|
||||
- API: `POST ${GITEA_URL}/api/v1/orgs/${org_name}/actions/runners/registration-token`
|
||||
- 从响应中提取 token(JSON 格式)
|
||||
- 记录使用的 runner 级别(global 或 organization)
|
||||
|
||||
9. **注册 Runner**
|
||||
- 执行命令:
|
||||
```bash
|
||||
act_runner register \
|
||||
--config "$runner_dir/config.yaml" \
|
||||
--instance "$GITEA_URL" \
|
||||
--token "$registration_token" \
|
||||
--name "$runner_name" \
|
||||
--labels "$labels" \
|
||||
--no-interactive
|
||||
```
|
||||
- 验证 `.runner` 文件是否创建
|
||||
- 如果失败,提供诊断建议
|
||||
|
||||
10. **后台启动 Runner**
|
||||
- 使用 nohup 后台启动:
|
||||
```bash
|
||||
nohup act_runner daemon --config "$runner_dir/config.yaml" \
|
||||
> "$runner_dir/runner.log" 2>&1 &
|
||||
```
|
||||
- 记录进程 PID
|
||||
- 等待 3 秒初始化
|
||||
- 验证进程仍在运行
|
||||
- 如果失败,显示日志的最后 20 行
|
||||
|
||||
11. **显示创建摘要**
|
||||
- Runner 信息:名称、级别、模式、状态、PID
|
||||
- 如果是组织级别,显示组织名
|
||||
- 配置信息:容量、超时、labels
|
||||
- 目录信息:配置文件、工作目录、缓存目录、日志文件
|
||||
- 管理命令:查看日志、停止 Runner、查看所有、删除
|
||||
- 使用示例:workflow 中的 runs-on 配置
|
||||
|
||||
## 重要配置说明
|
||||
|
||||
- **默认模式**:Host Mode(直接在宿主机执行,支持 Android SDK、iOS 构建等原生工具)
|
||||
- **目录结构**:
|
||||
- macOS/Linux: 所有 runners 位于 `~/.config/gitea/runners/`
|
||||
- Windows: 所有 runners 位于 `%USERPROFILE%\.config\gitea\runners\`
|
||||
- **优雅降级**:全局 runner 权限不足时自动降级到组织 runner
|
||||
- **后台运行**:使用 nohup 后台启动(Unix),或 Start-Process(Windows),日志输出到文件
|
||||
- **进程管理**:需要手动管理进程(系统重启后需重新启动)
|
||||
|
||||
## 可选参数
|
||||
|
||||
- `$ARGUMENTS`: Runner 名称(可选,默认基于主机名生成)
|
||||
|
||||
使用示例:
|
||||
```
|
||||
/gitea-create-runner
|
||||
/gitea-create-runner my-custom-runner
|
||||
```
|
||||
|
||||
## 相关命令
|
||||
|
||||
- `/gitea-config`: 查看 Gitea 配置
|
||||
- `/gitea-reset`: 重置/初始化 Gitea 配置
|
||||
- `/gitea-list-runners`: 列出所有 runners
|
||||
- `/gitea-delete-runner`: 删除指定 runner
|
||||
|
||||
---
|
||||
|
||||
## 详细实现步骤(供 AI 参考)
|
||||
|
||||
### 1. Check act_runner Installation
|
||||
|
||||
**AI 执行**:检查 act_runner 是否已安装,如果没有则自动安装。
|
||||
|
||||
```bash
|
||||
echo "检查 act_runner 安装状态..."
|
||||
|
||||
if command -v act_runner &> /dev/null; then
|
||||
version=$(act_runner --version 2>&1 | head -n1)
|
||||
echo "✓ act_runner 已安装: $version"
|
||||
else
|
||||
echo "⚠️ act_runner 未安装"
|
||||
echo "正在使用 Homebrew 安装..."
|
||||
|
||||
if ! command -v brew &> /dev/null; then
|
||||
echo "❌ 需要先安装 Homebrew"
|
||||
echo " 安装命令: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
brew install act_runner
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
version=$(act_runner --version 2>&1 | head -n1)
|
||||
echo "✓ act_runner 安装成功: $version"
|
||||
else
|
||||
echo "❌ act_runner 安装失败"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 2. Load Gitea Configuration
|
||||
|
||||
**AI 执行**:加载 Gitea 配置,如果不存在则提示初始化。
|
||||
|
||||
```bash
|
||||
config_file="$HOME/.config/gitea/config.env"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "❌ Gitea 配置不存在"
|
||||
echo ""
|
||||
echo "请先初始化 Gitea 配置:"
|
||||
echo " /gitea-reset"
|
||||
echo ""
|
||||
echo "或使用以下命令查看配置:"
|
||||
echo " /gitea-config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$config_file"
|
||||
|
||||
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
|
||||
echo "❌ Gitea 配置不完整"
|
||||
echo " 需要 GITEA_URL 和 GITEA_TOKEN"
|
||||
echo ""
|
||||
echo "请重新初始化配置:"
|
||||
echo " /gitea-reset"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 已加载 Gitea 配置"
|
||||
echo " URL: $GITEA_URL"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 3. Generate Runner Name
|
||||
|
||||
**AI 执行**:生成 runner 名称(基于主机名或用户输入)。
|
||||
|
||||
```bash
|
||||
# Check if runner name provided as argument
|
||||
# 如果用户提供了名称参数,使用该参数;否则基于主机名生成
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
runner_name="$1"
|
||||
echo "使用指定的 Runner 名称: $runner_name"
|
||||
else
|
||||
hostname=$(hostname -s 2>/dev/null || echo "unknown")
|
||||
runner_name="runner-$hostname"
|
||||
echo "生成 Runner 名称: $runner_name"
|
||||
echo " (基于主机名: $hostname)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Validate runner name
|
||||
if [[ ! "$runner_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
echo "❌ Runner 名称只能包含字母、数字、下划线和连字符"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 4. Check Runner Existence
|
||||
|
||||
**AI 执行**:检查 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_dir"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " 1. 使用其他名称: /gitea-create-runner <新名称>"
|
||||
echo " 2. 删除现有 runner: /gitea-delete-runner"
|
||||
echo " 3. 查看所有 runners: /gitea-list-runners"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 5. Detect System Environment
|
||||
|
||||
**AI 执行**:智能检测系统环境并生成 labels。
|
||||
|
||||
```bash
|
||||
echo "检测系统环境..."
|
||||
|
||||
# Detect OS
|
||||
OS=$(uname -s)
|
||||
case "$OS" in
|
||||
Darwin) os_label="macOS" ;;
|
||||
Linux) os_label="ubuntu" ;;
|
||||
*) os_label="unknown" ;;
|
||||
esac
|
||||
|
||||
# Detect architecture
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
arm64|aarch64) arch_label="ARM64" ;;
|
||||
x86_64) arch_label="x64" ;;
|
||||
*) arch_label="unknown" ;;
|
||||
esac
|
||||
|
||||
# Generate combined label
|
||||
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Generate labels for host mode
|
||||
labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
|
||||
|
||||
echo "✓ 系统信息"
|
||||
echo " 操作系统: $OS ($os_label)"
|
||||
echo " 架构: $ARCH ($arch_label)"
|
||||
echo " 组合标签: $combined"
|
||||
echo ""
|
||||
echo "✓ Runner Labels (Host Mode)"
|
||||
echo " $labels"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 6. Create Runner Directory
|
||||
|
||||
**AI 执行**:创建 runner 目录结构。
|
||||
|
||||
```bash
|
||||
echo "创建 Runner 目录..."
|
||||
|
||||
mkdir -p "$runner_dir"/{cache,workspace}
|
||||
|
||||
if [ ! -d "$runner_dir" ]; then
|
||||
echo "❌ 创建目录失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 目录创建成功"
|
||||
echo " 路径: $runner_dir"
|
||||
echo " - cache/"
|
||||
echo " - workspace/"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 7. Generate Configuration File
|
||||
|
||||
**AI 执行**:生成 host 模式配置文件。
|
||||
|
||||
```bash
|
||||
echo "生成配置文件..."
|
||||
|
||||
# Get environment-specific settings (with defaults)
|
||||
runner_capacity="${GITEA_RUNNER_CAPACITY:-2}"
|
||||
runner_timeout="${GITEA_RUNNER_TIMEOUT:-3h}"
|
||||
|
||||
# Generate config.yaml for host mode
|
||||
cat > "$runner_dir/config.yaml" << EOF
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: $runner_dir/.runner
|
||||
capacity: $runner_capacity
|
||||
timeout: $runner_timeout
|
||||
shutdown_timeout: 30s
|
||||
insecure: false
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels:
|
||||
- "self-hosted:host"
|
||||
- "${os_label}:host"
|
||||
- "${arch_label}:host"
|
||||
- "${combined}:host"
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: "$runner_dir/cache"
|
||||
host: "127.0.0.1"
|
||||
port: 9000
|
||||
|
||||
host:
|
||||
workdir_parent: "$runner_dir/workspace"
|
||||
EOF
|
||||
|
||||
if [ ! -f "$runner_dir/config.yaml" ]; then
|
||||
echo "❌ 配置文件生成失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 配置文件已生成"
|
||||
echo " 文件: $runner_dir/config.yaml"
|
||||
echo " 模式: Host Mode (原生执行)"
|
||||
echo " 容量: $runner_capacity 并发任务"
|
||||
echo " 超时: $runner_timeout"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 8. Get Registration Token
|
||||
|
||||
**AI 执行**:获取注册 token(优先全局,失败则降级到组织)。
|
||||
|
||||
```bash
|
||||
echo "获取 Runner 注册 Token..."
|
||||
echo ""
|
||||
|
||||
# Try global runner first (requires admin token)
|
||||
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')
|
||||
|
||||
# Check for admin permission
|
||||
if [ "$http_code" = "200" ]; then
|
||||
echo "✓ 使用全局 Runner"
|
||||
runner_level="global"
|
||||
registration_token=$(echo "$body" | jq -r '.token')
|
||||
else
|
||||
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"
|
||||
echo "使用默认组织: $org_name"
|
||||
else
|
||||
echo "❌ 未配置默认组织"
|
||||
echo " 请在配置文件中设置 GITEA_DEFAULT_ORG"
|
||||
echo " 或重新初始化配置: /gitea-reset"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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')
|
||||
|
||||
if [ "$http_code" != "200" ]; then
|
||||
echo "❌ 获取注册 Token 失败 (HTTP $http_code)"
|
||||
echo " 响应: $body"
|
||||
echo ""
|
||||
echo "可能的原因:"
|
||||
echo " 1. 组织不存在"
|
||||
echo " 2. Token 没有组织管理权限"
|
||||
echo " 3. 网络连接问题"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
registration_token=$(echo "$body" | jq -r '.token')
|
||||
echo "✓ 组织 Runner Token 已获取"
|
||||
fi
|
||||
|
||||
if [ -z "$registration_token" ] || [ "$registration_token" = "null" ]; then
|
||||
echo "❌ 无法解析注册 Token"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 注册 Token 已准备"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 9. Register Runner
|
||||
|
||||
**AI 执行**:注册 runner 到 Gitea 服务器。
|
||||
|
||||
```bash
|
||||
echo "注册 Runner 到 Gitea 服务器..."
|
||||
|
||||
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 注册失败"
|
||||
echo ""
|
||||
echo "请检查:"
|
||||
echo " 1. Token 是否有效"
|
||||
echo " 2. Gitea 服务器是否可访问"
|
||||
echo " 3. 配置文件是否正确"
|
||||
echo ""
|
||||
echo "查看详细错误,可以手动运行:"
|
||||
echo " act_runner register --config $runner_dir/config.yaml --instance $GITEA_URL --token <token> --name $runner_name --labels \"$labels\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify .runner file was created
|
||||
if [ ! -f "$runner_dir/.runner" ]; then
|
||||
echo "⚠️ 注册文件未创建,但注册可能成功"
|
||||
echo " 请检查: $runner_dir/.runner"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 10. Start Runner
|
||||
|
||||
**AI 执行**:后台启动 runner 并验证状态。
|
||||
|
||||
```bash
|
||||
echo "启动 Runner..."
|
||||
|
||||
# Start runner in background
|
||||
nohup act_runner daemon --config "$runner_dir/config.yaml" \
|
||||
> "$runner_dir/runner.log" 2>&1 &
|
||||
|
||||
runner_pid=$!
|
||||
|
||||
echo " 进程已启动 (PID: $runner_pid)"
|
||||
|
||||
# Wait for runner to initialize
|
||||
echo " 等待初始化..."
|
||||
sleep 3
|
||||
|
||||
# Check if process is still running
|
||||
if ps -p $runner_pid > /dev/null 2>&1; then
|
||||
echo "✓ Runner 运行中"
|
||||
else
|
||||
echo "❌ Runner 启动失败"
|
||||
echo ""
|
||||
echo "查看日志以诊断问题:"
|
||||
echo " tail -n 50 $runner_dir/runner.log"
|
||||
echo ""
|
||||
tail -n 20 "$runner_dir/runner.log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
```
|
||||
|
||||
### 11. Display Summary
|
||||
|
||||
**AI 执行**:显示创建结果和管理命令。
|
||||
|
||||
```bash
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "✅ Runner 创建完成!"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "Runner 信息:"
|
||||
echo " 名称: $runner_name"
|
||||
echo " 级别: $runner_level"
|
||||
if [ "$runner_level" = "organization" ]; then
|
||||
echo " 组织: $org_name"
|
||||
fi
|
||||
echo " 模式: Host Mode (原生执行)"
|
||||
echo " 状态: 🟢 运行中"
|
||||
echo " PID: $runner_pid"
|
||||
echo ""
|
||||
echo "配置:"
|
||||
echo " 容量: $runner_capacity 并发任务"
|
||||
echo " 超时: $runner_timeout"
|
||||
echo " Labels: $labels"
|
||||
echo ""
|
||||
echo "目录:"
|
||||
echo " 配置文件: $runner_dir/config.yaml"
|
||||
echo " 注册信息: $runner_dir/.runner"
|
||||
echo " 工作目录: $runner_dir/workspace"
|
||||
echo " 缓存目录: $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"
|
||||
echo ""
|
||||
echo "使用 Runner:"
|
||||
echo " 在 workflow 中使用以下任一 runs-on 值:"
|
||||
echo " - runs-on: $combined"
|
||||
echo " - runs-on: $os_label"
|
||||
echo " - runs-on: [self-hosted, $os_label, $arch_label]"
|
||||
echo ""
|
||||
```
|
||||
|
||||
## Output Example
|
||||
|
||||
### Example 1: Successful Creation (Global Runner)
|
||||
|
||||
```
|
||||
检查 act_runner 安装状态...
|
||||
✓ act_runner 已安装: act_runner version 0.2.13
|
||||
|
||||
✓ 已加载 Gitea 配置
|
||||
URL: https://git.digitevents.com
|
||||
|
||||
生成 Runner 名称: runner-macbook-pro
|
||||
(基于主机名: macbook-pro)
|
||||
|
||||
检测系统环境...
|
||||
✓ 系统信息
|
||||
操作系统: Darwin (macOS)
|
||||
架构: arm64 (ARM64)
|
||||
组合标签: darwin-arm64
|
||||
|
||||
✓ Runner Labels (Host Mode)
|
||||
self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
|
||||
|
||||
创建 Runner 目录...
|
||||
✓ 目录创建成功
|
||||
路径: /Users/voson/.config/gitea/runners/runner-macbook-pro
|
||||
- cache/
|
||||
- workspace/
|
||||
|
||||
生成配置文件...
|
||||
✓ 配置文件已生成
|
||||
文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/config.yaml
|
||||
模式: Host Mode (原生执行)
|
||||
容量: 2 并发任务
|
||||
超时: 3h
|
||||
|
||||
获取 Runner 注册 Token...
|
||||
|
||||
尝试创建全局 Runner(可用于所有组织和仓库)...
|
||||
✓ 使用全局 Runner
|
||||
✓ 注册 Token 已准备
|
||||
|
||||
注册 Runner 到 Gitea 服务器...
|
||||
✓ Runner 注册成功
|
||||
|
||||
启动 Runner...
|
||||
进程已启动 (PID: 12345)
|
||||
等待初始化...
|
||||
✓ Runner 运行中
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Runner 创建完成!
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Runner 信息:
|
||||
名称: runner-macbook-pro
|
||||
级别: global
|
||||
模式: Host Mode (原生执行)
|
||||
状态: 🟢 运行中
|
||||
PID: 12345
|
||||
|
||||
配置:
|
||||
容量: 2 并发任务
|
||||
超时: 3h
|
||||
Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
|
||||
|
||||
目录:
|
||||
配置文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/config.yaml
|
||||
注册信息: /Users/voson/.config/gitea/runners/runner-macbook-pro/.runner
|
||||
工作目录: /Users/voson/.config/gitea/runners/runner-macbook-pro/workspace
|
||||
缓存目录: /Users/voson/.config/gitea/runners/runner-macbook-pro/cache
|
||||
日志文件: /Users/voson/.config/gitea/runners/runner-macbook-pro/runner.log
|
||||
|
||||
管理命令:
|
||||
查看日志: tail -f /Users/voson/.config/gitea/runners/runner-macbook-pro/runner.log
|
||||
停止 Runner: pkill -f 'act_runner daemon --config.*runner-macbook-pro'
|
||||
查看所有: /gitea-list-runners
|
||||
删除 Runner: /gitea-delete-runner
|
||||
|
||||
使用 Runner:
|
||||
在 workflow 中使用以下任一 runs-on 值:
|
||||
- runs-on: darwin-arm64
|
||||
- runs-on: macOS
|
||||
- runs-on: [self-hosted, macOS, ARM64]
|
||||
```
|
||||
|
||||
### Example 2: Auto-install act_runner
|
||||
|
||||
```
|
||||
检查 act_runner 安装状态...
|
||||
⚠️ act_runner 未安装
|
||||
正在使用 Homebrew 安装...
|
||||
==> Downloading act_runner...
|
||||
==> Installing act_runner...
|
||||
✓ act_runner 安装成功: act_runner version 0.2.13
|
||||
|
||||
[继续后续步骤...]
|
||||
```
|
||||
|
||||
### Example 3: Downgrade to Organization Runner
|
||||
|
||||
```
|
||||
获取 Runner 注册 Token...
|
||||
|
||||
尝试创建全局 Runner(可用于所有组织和仓库)...
|
||||
⚠️ 全局 Runner 权限不足 (HTTP 403)
|
||||
全局 Runner 需要管理员 Token
|
||||
|
||||
降级到组织 Runner...
|
||||
使用默认组织: ai
|
||||
✓ 组织 Runner Token 已获取
|
||||
✓ 注册 Token 已准备
|
||||
|
||||
[继续后续步骤...]
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Runner 创建完成!
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Runner 信息:
|
||||
名称: runner-macbook-pro
|
||||
级别: organization
|
||||
组织: ai
|
||||
模式: Host Mode (原生执行)
|
||||
[...]
|
||||
```
|
||||
|
||||
### Example 4: Configuration Not Found
|
||||
|
||||
```
|
||||
检查 act_runner 安装状态...
|
||||
✓ act_runner 已安装: act_runner version 0.2.13
|
||||
|
||||
❌ Gitea 配置不存在
|
||||
|
||||
请先初始化 Gitea 配置:
|
||||
/gitea-reset
|
||||
|
||||
或使用以下命令查看配置:
|
||||
/gitea-config
|
||||
```
|
||||
|
||||
### Example 5: Runner Already Exists
|
||||
|
||||
```
|
||||
[前置检查...]
|
||||
|
||||
生成 Runner 名称: runner-macbook-pro
|
||||
(基于主机名: macbook-pro)
|
||||
|
||||
❌ Runner 'runner-macbook-pro' 已存在
|
||||
路径: /Users/voson/.config/gitea/runners/runner-macbook-pro
|
||||
|
||||
选项:
|
||||
1. 使用其他名称: /gitea-create-runner <新名称>
|
||||
2. 删除现有 runner: /gitea-delete-runner
|
||||
3. 查看所有 runners: /gitea-list-runners
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- **默认模式**:Host Mode(支持 Android SDK、iOS 等原生工具)
|
||||
- **自动安装**:使用 Homebrew 安装 act_runner
|
||||
- **智能检测**:自动检测 OS 和架构,生成合适的 labels
|
||||
- **优雅降级**:全局 runner 权限不足时自动降级到组织 runner
|
||||
- **后台运行**:自动后台启动,日志记录到文件
|
||||
- **配置环境变量**:
|
||||
- `GITEA_RUNNER_CAPACITY`: 并发任务数(默认 2)
|
||||
- `GITEA_RUNNER_TIMEOUT`: 任务超时时间(默认 3h)
|
||||
- **目录权限**:自动创建,权限继承用户默认权限
|
||||
- **进程管理**:使用 nohup 后台运行,支持系统重启后手动重启
|
||||
|
||||
## Related Commands
|
||||
|
||||
- `/gitea-config`: 查看 Gitea 配置
|
||||
- `/gitea-reset`: 重置/初始化 Gitea 配置
|
||||
- `/gitea-list-runners`: 列出所有 runners
|
||||
- `/gitea-delete-runner`: 删除指定 runner
|
||||
- `/create-gitea-repo`: 创建 Gitea 仓库
|
||||
|
||||
## Safety Features
|
||||
|
||||
- **配置验证**:检查必需的配置项
|
||||
- **目录冲突检测**:避免覆盖现有 runner
|
||||
- **启动验证**:等待并验证进程启动成功
|
||||
- **错误提示**:清晰的错误信息和解决方案
|
||||
- **日志记录**:所有输出记录到日志文件
|
||||
|
||||
## Version
|
||||
|
||||
- **Command Version**: 1.0
|
||||
- **Last Updated**: 2026-01-12
|
||||
- **Compatible with**: act_runner 0.2.13+, macOS/Linux
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
description: 删除 Gitea Runner 配置(交互式)
|
||||
agent: general
|
||||
subtask: true
|
||||
---
|
||||
|
||||
Delete Gitea runner configuration with interactive selection. This command requires multiple user interactions.
|
||||
|
||||
**Important:** This is an interactive command. Wait for user input at each step before proceeding.
|
||||
|
||||
## 工作目录
|
||||
|
||||
**macOS / Linux:**
|
||||
```
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
%USERPROFILE%\.config\gitea\
|
||||
```
|
||||
|
||||
所有 Runner 配置、进程管理都基于此目录。
|
||||
|
||||
Please perform the following steps:
|
||||
|
||||
## Step 1: Load Configuration and Fetch Runners
|
||||
|
||||
1. **Load Gitea configuration:**
|
||||
|
||||
**macOS / Linux:**
|
||||
```bash
|
||||
source ~/.config/gitea/config.env
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||
if ($_ -match '^([^=]+)=(.*)$') {
|
||||
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Validate `GITEA_URL` and `GITEA_TOKEN` exist
|
||||
|
||||
2. **Fetch global runners from Gitea server:**
|
||||
- API: `GET ${GITEA_URL}/api/v1/admin/actions/runners`
|
||||
- Requires admin permissions
|
||||
- If fails: show error and check token permissions
|
||||
|
||||
3. **Display runners list in Chinese:**
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Gitea 全局 Runners (共 N 个)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. [runner-name] [ID: XX] 🟢 在线/🔴 离线
|
||||
2. [runner-name] [ID: XX] 🟢 在线/🔴 离线
|
||||
...
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
选择要删除的 Runner
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
输入序号: 删除单个 runner
|
||||
输入 'all': 删除所有 runners
|
||||
输入 'q' 或 'quit': 取消
|
||||
```
|
||||
|
||||
4. **Wait for user selection** → Do NOT proceed until user responds
|
||||
|
||||
## Step 2: Process User Selection
|
||||
|
||||
Based on user input:
|
||||
- If `q` or `quit`: Cancel and exit
|
||||
- If `all`: Prepare to delete all runners
|
||||
- If number: Validate and prepare to delete that runner
|
||||
|
||||
## Step 3: Display Warning and Wait for Confirmation
|
||||
|
||||
Display deletion warning in Chinese:
|
||||
```
|
||||
⚠️ 警告: 此操作将执行以下操作:
|
||||
- 从 Gitea 服务器注销 runner
|
||||
- 停止本地运行的 runner 进程
|
||||
- 删除 runner 配置文件
|
||||
- 删除 cache 和 workspace 目录
|
||||
- 删除所有相关数据
|
||||
|
||||
将删除以下 runners:
|
||||
- [list of runners to be deleted]
|
||||
|
||||
确认删除? 输入 'yes' 继续:
|
||||
```
|
||||
|
||||
**Wait for user confirmation** → Do NOT proceed until user types 'yes'
|
||||
|
||||
## Step 4: Execute Deletion
|
||||
|
||||
If user confirmed with 'yes', for each selected runner:
|
||||
|
||||
### 4.1 Unregister from Gitea Server
|
||||
```bash
|
||||
DELETE ${GITEA_URL}/api/v1/admin/actions/runners/${runner_id}
|
||||
```
|
||||
- Expected: HTTP 204
|
||||
- Show: "✓ 已从服务器注销" or "⚠️ 注销失败"
|
||||
|
||||
### 4.2 Stop Local Process
|
||||
1. Find local runner directory by matching ID in `.runner` file
|
||||
2. Check if process is running: `pgrep -f "act_runner daemon --config ..."`
|
||||
3. If running:
|
||||
- Check if runner is busy (executing jobs) via API
|
||||
- **If busy, wait for user choice:**
|
||||
```
|
||||
⚠️ 警告: Runner 正在执行 job!
|
||||
选项:
|
||||
1. 等待 job 完成后再停止(推荐)
|
||||
2. 强制立即停止
|
||||
```
|
||||
- **Wait for user input** → Proceed based on choice
|
||||
- If waiting: Poll status every 10 seconds, max 5 minutes
|
||||
- Stop process: `kill $pid` (graceful), then `kill -9 $pid` if needed (force)
|
||||
|
||||
### 4.3 Delete Local Directory
|
||||
|
||||
**macOS / Linux:**
|
||||
```bash
|
||||
rm -rf ~/.config/gitea/runners/[runner_name]
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
Remove-Item -Path "$env:USERPROFILE\.config\gitea\runners\[runner_name]" -Recurse -Force
|
||||
```
|
||||
|
||||
## Step 5: Display Result
|
||||
|
||||
Show completion summary in Chinese:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
删除完成
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
成功: N 个
|
||||
失败: M 个 (if any)
|
||||
|
||||
管理命令:
|
||||
查看剩余 runners: /gitea-list-runners
|
||||
创建新 runner: /gitea-create-runner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Points
|
||||
|
||||
**Interactive checkpoints (wait for user input):**
|
||||
1. Step 1: After displaying runners list → Wait for selection
|
||||
2. Step 3: After displaying warning → Wait for confirmation ('yes')
|
||||
3. Step 4.2: If runner is busy → Wait for stop choice (1 or 2)
|
||||
|
||||
**Safety features:**
|
||||
- Double confirmation required
|
||||
- Busy status detection
|
||||
- Graceful stop before force kill
|
||||
- Three-step deletion process
|
||||
- Clear status reporting
|
||||
|
||||
**Technical notes:**
|
||||
- Requires `jq` for JSON parsing
|
||||
- Requires admin token for global runners
|
||||
- Uses temporary file `/tmp/gitea_runners.txt` for data passing
|
||||
- Cleanup temp file after completion
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
description: 列出 Gitea 服务器上的所有全局 Runner
|
||||
---
|
||||
|
||||
List all global runners registered on the Gitea server.
|
||||
|
||||
## 工作目录
|
||||
|
||||
**macOS / Linux:**
|
||||
```
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
%USERPROFILE%\.config\gitea\
|
||||
```
|
||||
|
||||
Please perform the following:
|
||||
|
||||
1. **Read Gitea configuration:**
|
||||
- Read from config file:
|
||||
- macOS/Linux: `~/.config/gitea/config.env`
|
||||
- Windows: `%USERPROFILE%\.config\gitea\config.env`
|
||||
- Extract:
|
||||
- `GITEA_URL`: Gitea server URL
|
||||
- `GITEA_TOKEN`: API token (admin permission required)
|
||||
- If config not found: prompt user to run `/gitea-reset` first
|
||||
|
||||
2. **Call Gitea API to list runners:**
|
||||
```bash
|
||||
curl -s -H "Authorization: token <token>" \
|
||||
"<server>/api/v1/admin/actions/runners"
|
||||
```
|
||||
|
||||
3. **Parse JSON response and extract information:**
|
||||
- Response structure:
|
||||
```json
|
||||
{
|
||||
"runners": [...],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
- Use `jq` to parse JSON
|
||||
- For each runner in `runners` array:
|
||||
- `id`: Runner ID
|
||||
- `name`: Runner name
|
||||
- `status`: Runner status ("online"/"offline")
|
||||
- `busy`: Whether runner is currently busy (true/false)
|
||||
- `ephemeral`: Whether runner is ephemeral (true/false)
|
||||
- `labels`: Array of label objects with `name` and `type`
|
||||
|
||||
4. **Determine runner status:**
|
||||
- 🟢 在线 - `status: "online"`
|
||||
- 🔴 离线 - `status: "offline"`
|
||||
- ⚠️ 未知 - Unable to determine
|
||||
|
||||
5. **Filter global runners:**
|
||||
- The API endpoint `/api/v1/admin/actions/runners` returns all global runners
|
||||
- These are runners registered at the instance level (not org or repo specific)
|
||||
|
||||
6. **Display summary in Chinese:**
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Gitea 全局 Runners
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
服务器: [server_url]
|
||||
总计: N 个全局 runner
|
||||
|
||||
[runner-name]
|
||||
状态: 🟢/🔴 [在线/离线]
|
||||
ID: [id]
|
||||
忙碌: 是/否
|
||||
临时: 是/否
|
||||
标签: [comma-separated labels]
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
管理命令
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
查看配置: /gitea-config
|
||||
创建 runner: /gitea-create-runner
|
||||
删除 runner: /gitea-delete-runner
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Requires admin API token to list runners
|
||||
- **Correct API endpoint**: `/api/v1/admin/actions/runners` (not `/api/v1/admin/runners`)
|
||||
- Only shows global runners (instance-level runners)
|
||||
- Uses `jq` for JSON parsing
|
||||
- Response includes: `id`, `name`, `status`, `busy`, `ephemeral`, `labels`
|
||||
- If API call fails, show error message and suggest checking token permissions
|
||||
- Tested with Gitea version 1.25.3
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
description: 审查代码或文档并提供建议
|
||||
agent: plan
|
||||
---
|
||||
|
||||
Review the code or documentation and provide detailed feedback.
|
||||
|
||||
Please perform the following:
|
||||
|
||||
1. **Review** the code or documentation mentioned by the user
|
||||
2. **Identify issues** and areas for improvement
|
||||
3. **Provide suggestions** with clear explanations
|
||||
4. **Ask for confirmation** before making modifications
|
||||
|
||||
If the user hasn't specified what to review, ask them to provide the code or documentation they want reviewed.
|
||||
|
||||
When suggesting changes:
|
||||
- Explain why each change is needed
|
||||
- Prioritize suggestions by importance
|
||||
- Ask if the user wants all changes applied or only specific ones
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
description: 归纳总结当前对话中有价值的内容,生成 Markdown 文件以便后续参考
|
||||
agent: general
|
||||
---
|
||||
|
||||
# 对话内容总结
|
||||
|
||||
你的任务是归纳总结当前对话中有价值的内容,生成一个结构化的 Markdown 文件,方便后续与 AI 对话时快速回顾,避免重复查询。
|
||||
|
||||
## 总结内容
|
||||
|
||||
请从对话历史中提取以下信息:
|
||||
|
||||
1. **对话主题** - 用户的主要需求和目标
|
||||
2. **关键决策** - 用户做出的重要选择、确定的技术方案
|
||||
3. **代码更改** - 创建、修改或删除的代码文件及核心逻辑
|
||||
4. **配置更新** - 环境变量、配置文件、依赖项变更
|
||||
5. **待办事项** - 用户明确提到的未来任务或计划
|
||||
6. **下一步行动** - 建议的后续步骤
|
||||
7. **重要注意事项** - 需要特别记住的细节、限制条件
|
||||
8. **相关文件路径** - 涉及的重要文件位置(格式:`文件路径:行号`)
|
||||
|
||||
## 生成文件
|
||||
|
||||
1. **默认文件名**:`conversation-summary.md`
|
||||
2. **文件位置**:当前工作目录
|
||||
3. **文件格式**:使用 Markdown 语法,包含清晰的标题和列表
|
||||
4. **时间戳**:在文件开头添加生成时间(格式:YYYY-MM-DD HH:MM:SS)
|
||||
5. **对话上下文**:简要描述对话的背景和目的
|
||||
|
||||
## 执行步骤
|
||||
|
||||
1. **分析对话** - 回顾完整的对话历史,识别有价值的信息点
|
||||
2. **提取内容** - 按照上述分类整理信息,确保准确性和完整性
|
||||
3. **生成总结** - 创建结构化的 Markdown 内容,使用中文描述
|
||||
4. **保存文件** - 将总结写入 `conversation-summary.md` 文件
|
||||
5. **验证内容** - 检查文件是否包含所有关键信息
|
||||
6. **通知用户** - 告知用户文件已生成,并提供文件路径
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 只总结**有价值**的内容,忽略闲聊和无关信息
|
||||
- 保持总结简洁明了,便于快速查阅
|
||||
- 涉及代码时,提供文件路径和关键行号引用
|
||||
- 如果有未完成的任务,明确标注状态(待处理/进行中/已完成)
|
||||
- 如果对话中涉及敏感信息(如密码、密钥),**不要**包含在总结中
|
||||
|
||||
## 输出示例
|
||||
|
||||
```
|
||||
# 对话总结
|
||||
|
||||
**生成时间**: 2025-01-15 14:30:00
|
||||
**对话主题**: 创建 OpenCode 命令用于总结对话内容
|
||||
|
||||
## 关键决策
|
||||
- 命令名称: `summarize-conversation`
|
||||
- 文件位置: 全局命令目录 (`~/.config/opencode/command/`)
|
||||
- 代理类型: general
|
||||
|
||||
## 代码更改
|
||||
- 创建命令文件: `command/summarize-conversation.md`
|
||||
|
||||
## 配置更新
|
||||
- 无
|
||||
|
||||
## 待办事项
|
||||
- 测试命令功能:运行 `/summarize-conversation`
|
||||
- 考虑添加文件命名参数支持
|
||||
|
||||
## 下一步行动
|
||||
1. 使用 `/summarize-conversation` 测试命令效果
|
||||
2. 根据使用反馈优化总结模板
|
||||
|
||||
## 重要注意事项
|
||||
- 总结文件保存在当前工作目录的 `conversation-summary.md`
|
||||
- 每次运行会覆盖之前的总结文件
|
||||
- 建议定期备份重要总结
|
||||
|
||||
## 相关文件
|
||||
- `command/summarize-conversation.md`
|
||||
```
|
||||
|
||||
**完成标准**:成功生成包含上述所有部分的 Markdown 文件,并通知用户文件位置。
|
||||
@@ -21,7 +21,5 @@
|
||||
"apiKey": "0f76aea86295476dbfa98724013b0fe8.o2EaJVqcl4Cf7WLP"
|
||||
}
|
||||
}
|
||||
},
|
||||
"model": "deepseek/deepseek-resoner",
|
||||
"small_model": "deepseek/deepseek-resoner"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ description: Git workflow best practices with commit conventions, tagging, and c
|
||||
|
||||
You are an expert in Git version control and repository management.
|
||||
|
||||
## 功能文档
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [Commit Workflow](./commit-workflow.md) | 提交暂存文件,自动生成提交信息并创建版本标签 |
|
||||
| [Push Workflow](./push-workflow.md) | 提交并推送到远程仓库的完整工作流 |
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Default Main Branch**: Use `main` as the primary branch (not `master`)
|
||||
|
||||
163
skill/git/commit-workflow.md
Normal file
163
skill/git/commit-workflow.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Git Commit Workflow
|
||||
|
||||
提交暂存文件,自动生成提交信息并创建版本标签的完整工作流。
|
||||
|
||||
## 概述
|
||||
|
||||
此工作流用于:
|
||||
- 自动分析暂存区变更
|
||||
- 根据 Conventional Commits 规范生成提交信息
|
||||
- 检测项目类型并更新版本号
|
||||
- 创建语义化版本标签
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 步骤 1: 检查暂存区
|
||||
|
||||
```bash
|
||||
git diff --cached --name-only
|
||||
```
|
||||
|
||||
- 如果暂存区为空,通知用户并停止
|
||||
- 如果有文件,继续下一步
|
||||
|
||||
### 步骤 2: 收集信息(并行执行)
|
||||
|
||||
```bash
|
||||
# 并行执行以下命令
|
||||
git status
|
||||
git diff --cached
|
||||
git log --oneline -10
|
||||
git tag --list | sort -V | tail -5
|
||||
```
|
||||
|
||||
同时检查 `AGENTS.md` 文件获取:
|
||||
- 仓库类型(polyrepo/monorepo)
|
||||
- 版本规则
|
||||
- 项目结构信息
|
||||
|
||||
### 步骤 3: 检测仓库类型
|
||||
|
||||
**Polyrepo(单仓库)**
|
||||
- Tag 格式:`<version>`(如 `1.2.0`)
|
||||
|
||||
**Monorepo(多项目)**
|
||||
- Tag 格式:`<subproject>-<version>`(如 `ios-1.2.0`)
|
||||
- 检测特征:`packages/`、`apps/`、`services/` 目录
|
||||
|
||||
### 步骤 4: 检测项目类型和版本
|
||||
|
||||
| 项目类型 | 版本文件 | 版本字段 |
|
||||
|---------|---------|---------|
|
||||
| iOS | `*.xcodeproj/project.pbxproj` | `MARKETING_VERSION` |
|
||||
| Node.js | `package.json` | `version` |
|
||||
| Android (Groovy) | `app/build.gradle` | `versionName` |
|
||||
| Android (Kotlin) | `app/build.gradle.kts` | `versionName` |
|
||||
| Go | Git tag only | - |
|
||||
| Python | `pyproject.toml` / `setup.py` | `version` |
|
||||
| Rust | `Cargo.toml` | `version` |
|
||||
|
||||
### 步骤 5: 生成提交信息
|
||||
|
||||
遵循 Conventional Commits 格式:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
```
|
||||
|
||||
**提交类型**:
|
||||
|
||||
| Type | 描述 | 版本影响 |
|
||||
|------|------|---------|
|
||||
| `feat` | 新功能 | minor +1 |
|
||||
| `fix` | Bug 修复 | patch +1 |
|
||||
| `perf` | 性能优化 | patch +1 |
|
||||
| `BREAKING CHANGE` | 破坏性变更 | major +1 |
|
||||
| `docs` | 文档更新 | 无 |
|
||||
| `style` | 代码格式 | 无 |
|
||||
| `refactor` | 重构 | 无 |
|
||||
| `test` | 测试 | 无 |
|
||||
| `chore` | 维护任务 | 无 |
|
||||
| `ci` | CI/CD 变更 | 无 |
|
||||
| `build` | 构建配置 | 无 |
|
||||
|
||||
**提交语言**:
|
||||
- macOS/Linux:使用中文
|
||||
- Windows:使用英文(避免编码问题)
|
||||
|
||||
**Monorepo Scope**:
|
||||
- 单项目变更:`feat(ios): 添加上传功能`
|
||||
- 多项目变更:`chore: 更新共享依赖`
|
||||
|
||||
### 步骤 6: 确定新版本号
|
||||
|
||||
根据提交类型计算新版本:
|
||||
|
||||
**版本递增规则**:
|
||||
- `feat`:minor +1(如 `1.2.0` → `1.3.0`)
|
||||
- `fix`/`perf`:patch +1(如 `1.2.3` → `1.2.4`)
|
||||
- Breaking change:major +1(如 `1.2.3` → `2.0.0`)
|
||||
|
||||
**不更新版本**:
|
||||
- `docs`、`test`、`refactor`、`style`、`build`、`ci`、`chore`
|
||||
|
||||
### 步骤 7: 更新版本文件并暂存
|
||||
|
||||
如果需要更新版本(步骤 6 确定了新版本号):
|
||||
|
||||
1. **更新版本文件**:将版本号写入对应的版本文件
|
||||
2. **添加到暂存区**:
|
||||
```bash
|
||||
git add <version-file>
|
||||
```
|
||||
3. **验证暂存**:
|
||||
```bash
|
||||
git diff --cached --name-only
|
||||
```
|
||||
确认版本文件已在暂存区
|
||||
|
||||
### 步骤 8: 执行提交
|
||||
|
||||
```bash
|
||||
git commit -m "<commit-message>"
|
||||
```
|
||||
|
||||
### 步骤 9: 创建版本标签
|
||||
|
||||
仅在版本更新时创建(除非用户指定 "skip tag"):
|
||||
|
||||
**Polyrepo**:
|
||||
```bash
|
||||
git tag -a "1.2.0" -m "<commit-message>"
|
||||
```
|
||||
|
||||
**Monorepo**:
|
||||
```bash
|
||||
git tag -a "ios-1.2.0" -m "<commit-message>"
|
||||
```
|
||||
|
||||
## 选项
|
||||
|
||||
- `skip tag` / `skip`:跳过标签创建
|
||||
|
||||
## 输出格式
|
||||
|
||||
```
|
||||
✓ 提交成功
|
||||
|
||||
提交信息:[commit message]
|
||||
版本标签:[tag](如果创建了)
|
||||
|
||||
要推送到远程仓库,请运行:/git-push
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 此命令**不会推送**到远程,使用 `/git-push` 推送
|
||||
- 暂存区为空时会提示用户先 `git add`
|
||||
- 标签注释使用与提交相同的消息内容
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Git Workflow Best Practices](./SKILL.md)
|
||||
- [Push Workflow](./push-workflow.md)
|
||||
107
skill/git/push-workflow.md
Normal file
107
skill/git/push-workflow.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Git Push Workflow
|
||||
|
||||
提交暂存文件,创建版本标签并推送到远程仓库的完整工作流。
|
||||
|
||||
## 概述
|
||||
|
||||
此工作流是 **All-in-One** 命令,组合了:
|
||||
- `/git-commit` 的所有功能
|
||||
- 推送提交到远程
|
||||
- 推送标签到远程
|
||||
|
||||
## 执行步骤
|
||||
|
||||
### 步骤 1-9: 与 Commit Workflow 相同
|
||||
|
||||
参考 [Commit Workflow](./commit-workflow.md):
|
||||
|
||||
1. 检查暂存区(不能为空)
|
||||
2. 收集变更信息和仓库状态
|
||||
3. 检测仓库类型(polyrepo/monorepo)
|
||||
4. 检测项目类型和版本
|
||||
5. 生成提交信息(Conventional Commits,中文)
|
||||
6. 确定新版本号
|
||||
7. 更新版本文件并添加到暂存区
|
||||
8. 执行提交
|
||||
9. 创建版本标签
|
||||
|
||||
### 步骤 10: 推送提交到远程
|
||||
|
||||
```bash
|
||||
git push origin $(git branch --show-current)
|
||||
```
|
||||
|
||||
### 步骤 11: 推送标签到远程
|
||||
|
||||
仅在创建了标签时执行:
|
||||
|
||||
**Polyrepo**:
|
||||
```bash
|
||||
git push origin <version>
|
||||
```
|
||||
|
||||
**Monorepo**:
|
||||
```bash
|
||||
git push origin <subproject>-<version>
|
||||
```
|
||||
|
||||
## 选项
|
||||
|
||||
- `skip tag` / `skip`:跳过标签创建
|
||||
|
||||
## 输出格式
|
||||
|
||||
```
|
||||
✓ 提交并推送成功
|
||||
|
||||
分支:[branch]
|
||||
提交信息:[commit message]
|
||||
版本标签:[tag](如果创建了)
|
||||
|
||||
已推送到远程仓库:origin
|
||||
- 提交:[commit hash]
|
||||
- 标签:[tag]
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 暂存区为空
|
||||
|
||||
```
|
||||
暂存区为空,请先使用 `git add` 添加文件。
|
||||
```
|
||||
|
||||
### 推送失败
|
||||
|
||||
```
|
||||
❌ 推送失败:[error message]
|
||||
|
||||
可能的解决方案:
|
||||
1. 先拉取远程变更:git pull origin <branch>
|
||||
2. 检查网络连接
|
||||
3. 检查远程仓库权限
|
||||
```
|
||||
|
||||
### 标签已存在
|
||||
|
||||
```
|
||||
❌ 标签推送失败:tag already exists
|
||||
|
||||
解决方案:
|
||||
1. 删除本地标签:git tag -d <tag>
|
||||
2. 更新版本号后重新提交
|
||||
```
|
||||
|
||||
## 使用场景
|
||||
|
||||
| 场景 | 推荐命令 |
|
||||
|------|---------|
|
||||
| 本地提交,稍后审查 | `/git-commit` |
|
||||
| 提交并立即推送 | `/git-push` |
|
||||
| 仅推送已有提交 | `git push origin <branch>` |
|
||||
| 仅推送标签 | `git push origin <tag>` |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Git Workflow Best Practices](./SKILL.md)
|
||||
- [Commit Workflow](./commit-workflow.md)
|
||||
@@ -1,663 +0,0 @@
|
||||
# Git Quick Reference
|
||||
|
||||
Quick reference guide for common Git operations.
|
||||
|
||||
## File Changes and Status
|
||||
|
||||
### View Changed Files
|
||||
|
||||
```bash
|
||||
# Show working directory status
|
||||
git status
|
||||
|
||||
# Show short status
|
||||
git status -s
|
||||
|
||||
# List changed files only (unstaged)
|
||||
git diff --name-only
|
||||
|
||||
# List changed files only (staged)
|
||||
git diff --cached --name-only
|
||||
# or
|
||||
git diff --staged --name-only
|
||||
|
||||
# Show file change statistics
|
||||
git diff --stat
|
||||
git diff --cached --stat
|
||||
```
|
||||
|
||||
### View Detailed Changes
|
||||
|
||||
```bash
|
||||
# View unstaged changes
|
||||
git diff
|
||||
|
||||
# View staged changes
|
||||
git diff --cached
|
||||
# or
|
||||
git diff --staged
|
||||
|
||||
# View specific file changes
|
||||
git diff <file-path>
|
||||
git diff --cached <file-path>
|
||||
|
||||
# View changes between commits
|
||||
git diff <commit1>..<commit2>
|
||||
git diff HEAD~1..HEAD
|
||||
|
||||
# View changes between branches
|
||||
git diff main..feature-branch
|
||||
```
|
||||
|
||||
## Staging and Committing
|
||||
|
||||
### Add Files to Staging
|
||||
|
||||
```bash
|
||||
# Add specific file
|
||||
git add <file-path>
|
||||
|
||||
# Add all files in directory
|
||||
git add .
|
||||
|
||||
# Add all files in repository
|
||||
git add -A
|
||||
|
||||
# Add files interactively
|
||||
git add -p
|
||||
|
||||
# Add only modified files (not new files)
|
||||
git add -u
|
||||
```
|
||||
|
||||
### Check Staging Area
|
||||
|
||||
```bash
|
||||
# List files in staging area
|
||||
git diff --cached --name-only
|
||||
|
||||
# Show detailed staged changes
|
||||
git diff --cached
|
||||
```
|
||||
|
||||
### Commit Changes
|
||||
|
||||
```bash
|
||||
# Simple commit
|
||||
git commit -m "feat: add user authentication"
|
||||
|
||||
# Multi-line commit (macOS/Linux)
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat: add user authentication
|
||||
|
||||
- Add OAuth2 support
|
||||
- Implement JWT tokens
|
||||
- Add login/logout endpoints
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Multi-line commit (Windows)
|
||||
git commit -m "feat: add user authentication" \
|
||||
-m "" \
|
||||
-m "- Add OAuth2 support" \
|
||||
-m "- Implement JWT tokens" \
|
||||
-m "- Add login/logout endpoints"
|
||||
|
||||
# Commit with automatic staging
|
||||
git commit -am "fix: resolve issue"
|
||||
|
||||
# Amend last commit (before push only!)
|
||||
git commit --amend -m "new message"
|
||||
```
|
||||
|
||||
## Tag Management
|
||||
|
||||
### Create Tags
|
||||
|
||||
```bash
|
||||
# Create annotated tag
|
||||
git tag -a "1.2.0" -m "feat: add new feature"
|
||||
|
||||
# Create lightweight tag
|
||||
git tag "1.2.0"
|
||||
|
||||
# Create tag with multi-line message
|
||||
git tag -a "1.2.1" \
|
||||
-m "fix: resolve connection issue" \
|
||||
-m "" \
|
||||
-m "- Increase timeout to 30s" \
|
||||
-m "- Add retry mechanism"
|
||||
|
||||
# Create tag for specific commit
|
||||
git tag -a "1.2.0" <commit-hash> -m "message"
|
||||
|
||||
# Monorepo tag
|
||||
git tag -a "ios-1.2.0" -m "feat(ios): add feature"
|
||||
```
|
||||
|
||||
### List Tags
|
||||
|
||||
```bash
|
||||
# List all tags
|
||||
git tag
|
||||
|
||||
# List tags with pattern
|
||||
git tag -l "v1.*"
|
||||
|
||||
# List recent tags (sorted)
|
||||
git tag --list | sort -V | tail -5
|
||||
|
||||
# Show tag details
|
||||
git show <tag-name>
|
||||
```
|
||||
|
||||
### Push Tags
|
||||
|
||||
```bash
|
||||
# Push single tag
|
||||
git push origin <tag-name>
|
||||
|
||||
# Push all tags
|
||||
git push --tags
|
||||
# or
|
||||
git push origin --tags
|
||||
|
||||
# Push commit and tag together
|
||||
git push origin main && git push origin 1.2.0
|
||||
```
|
||||
|
||||
### Delete Tags
|
||||
|
||||
```bash
|
||||
# Delete local tag
|
||||
git tag -d <tag-name>
|
||||
|
||||
# Delete remote tag
|
||||
git push origin --delete <tag-name>
|
||||
# or
|
||||
git push origin :refs/tags/<tag-name>
|
||||
|
||||
# Delete multiple tags
|
||||
git tag -d tag1 tag2 tag3
|
||||
```
|
||||
|
||||
## Branch Operations
|
||||
|
||||
### View Branches
|
||||
|
||||
```bash
|
||||
# Show current branch
|
||||
git branch --show-current
|
||||
|
||||
# List local branches
|
||||
git branch
|
||||
|
||||
# List all branches (local + remote)
|
||||
git branch -a
|
||||
|
||||
# List remote branches only
|
||||
git branch -r
|
||||
|
||||
# Show branch with last commit
|
||||
git branch -v
|
||||
```
|
||||
|
||||
### Create and Switch Branches
|
||||
|
||||
```bash
|
||||
# Create new branch
|
||||
git branch <branch-name>
|
||||
|
||||
# Create and switch to new branch (old way)
|
||||
git checkout -b <branch-name>
|
||||
|
||||
# Create and switch to new branch (modern)
|
||||
git switch -c <branch-name>
|
||||
|
||||
# Switch to existing branch (old way)
|
||||
git checkout <branch-name>
|
||||
|
||||
# Switch to existing branch (modern)
|
||||
git switch <branch-name>
|
||||
|
||||
# Switch to previous branch
|
||||
git switch -
|
||||
```
|
||||
|
||||
### Delete Branches
|
||||
|
||||
```bash
|
||||
# Delete local branch (safe)
|
||||
git branch -d <branch-name>
|
||||
|
||||
# Delete local branch (force)
|
||||
git branch -D <branch-name>
|
||||
|
||||
# Delete remote branch
|
||||
git push origin --delete <branch-name>
|
||||
# or
|
||||
git push origin :<branch-name>
|
||||
```
|
||||
|
||||
## Pushing and Pulling
|
||||
|
||||
### Push Changes
|
||||
|
||||
```bash
|
||||
# Push current branch
|
||||
git push
|
||||
|
||||
# Push to specific remote and branch
|
||||
git push origin main
|
||||
|
||||
# Push current branch to remote
|
||||
git push origin $(git branch --show-current)
|
||||
|
||||
# Push with upstream tracking
|
||||
git push -u origin <branch-name>
|
||||
|
||||
# Push all branches
|
||||
git push --all
|
||||
|
||||
# Push all tags
|
||||
git push --tags
|
||||
|
||||
# Force push (dangerous!)
|
||||
git push --force
|
||||
# Better: force push with lease
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
### Pull Changes
|
||||
|
||||
```bash
|
||||
# Pull from tracked remote
|
||||
git pull
|
||||
|
||||
# Pull from specific remote and branch
|
||||
git pull origin main
|
||||
|
||||
# Pull with rebase
|
||||
git pull --rebase
|
||||
|
||||
# Pull and prune deleted remote branches
|
||||
git pull --prune
|
||||
```
|
||||
|
||||
### Fetch Changes
|
||||
|
||||
```bash
|
||||
# Fetch from all remotes
|
||||
git fetch
|
||||
|
||||
# Fetch from specific remote
|
||||
git fetch origin
|
||||
|
||||
# Fetch and prune deleted remote branches
|
||||
git fetch --prune
|
||||
|
||||
# Fetch all branches and tags
|
||||
git fetch --all --tags
|
||||
```
|
||||
|
||||
## History and Logs
|
||||
|
||||
### View Commit History
|
||||
|
||||
```bash
|
||||
# View recent commits
|
||||
git log
|
||||
|
||||
# View compact history
|
||||
git log --oneline
|
||||
|
||||
# View recent 10 commits
|
||||
git log --oneline -10
|
||||
|
||||
# View history with graph
|
||||
git log --graph --oneline --all
|
||||
|
||||
# View history with stats
|
||||
git log --stat
|
||||
|
||||
# View history with patches
|
||||
git log -p
|
||||
```
|
||||
|
||||
### Search History
|
||||
|
||||
```bash
|
||||
# Search commits by message
|
||||
git log --grep="feature"
|
||||
|
||||
# Search by author
|
||||
git log --author="John"
|
||||
|
||||
# Search by date
|
||||
git log --since="2024-01-01"
|
||||
git log --after="2 weeks ago"
|
||||
git log --before="yesterday"
|
||||
|
||||
# Search by file
|
||||
git log -- <file-path>
|
||||
|
||||
# Search code changes
|
||||
git log -S "function_name"
|
||||
```
|
||||
|
||||
### View Commit Details
|
||||
|
||||
```bash
|
||||
# Show specific commit
|
||||
git show <commit-hash>
|
||||
|
||||
# Show specific tag
|
||||
git show <tag-name>
|
||||
|
||||
# Show HEAD commit
|
||||
git show HEAD
|
||||
|
||||
# Show previous commit
|
||||
git show HEAD~1
|
||||
git show HEAD^
|
||||
```
|
||||
|
||||
## Undoing Changes
|
||||
|
||||
### Discard Changes
|
||||
|
||||
```bash
|
||||
# Discard unstaged changes in file
|
||||
git checkout -- <file-path>
|
||||
# or (modern)
|
||||
git restore <file-path>
|
||||
|
||||
# Discard all unstaged changes
|
||||
git checkout -- .
|
||||
# or (modern)
|
||||
git restore .
|
||||
|
||||
# Unstage file (keep changes)
|
||||
git reset HEAD <file-path>
|
||||
# or (modern)
|
||||
git restore --staged <file-path>
|
||||
|
||||
# Unstage all files
|
||||
git reset HEAD
|
||||
# or (modern)
|
||||
git restore --staged .
|
||||
```
|
||||
|
||||
### Reset Commits
|
||||
|
||||
```bash
|
||||
# Undo last commit, keep changes staged
|
||||
git reset --soft HEAD~1
|
||||
|
||||
# Undo last commit, keep changes unstaged
|
||||
git reset HEAD~1
|
||||
# or
|
||||
git reset --mixed HEAD~1
|
||||
|
||||
# Undo last commit, discard changes (dangerous!)
|
||||
git reset --hard HEAD~1
|
||||
|
||||
# Reset to specific commit
|
||||
git reset --hard <commit-hash>
|
||||
```
|
||||
|
||||
### Revert Commits
|
||||
|
||||
```bash
|
||||
# Create new commit that undoes a commit
|
||||
git revert <commit-hash>
|
||||
|
||||
# Revert without committing
|
||||
git revert -n <commit-hash>
|
||||
|
||||
# Revert multiple commits
|
||||
git revert <commit1>..<commit2>
|
||||
```
|
||||
|
||||
## Stash Operations
|
||||
|
||||
### Save Changes
|
||||
|
||||
```bash
|
||||
# Stash current changes
|
||||
git stash
|
||||
|
||||
# Stash with message
|
||||
git stash save "work in progress"
|
||||
|
||||
# Stash including untracked files
|
||||
git stash -u
|
||||
|
||||
# Stash including untracked and ignored files
|
||||
git stash -a
|
||||
```
|
||||
|
||||
### Apply Stash
|
||||
|
||||
```bash
|
||||
# Apply most recent stash
|
||||
git stash apply
|
||||
|
||||
# Apply and remove from stash list
|
||||
git stash pop
|
||||
|
||||
# Apply specific stash
|
||||
git stash apply stash@{2}
|
||||
```
|
||||
|
||||
### Manage Stash
|
||||
|
||||
```bash
|
||||
# List all stashes
|
||||
git stash list
|
||||
|
||||
# Show stash changes
|
||||
git stash show
|
||||
git stash show -p
|
||||
|
||||
# Drop specific stash
|
||||
git stash drop stash@{1}
|
||||
|
||||
# Clear all stashes
|
||||
git stash clear
|
||||
```
|
||||
|
||||
## Remote Operations
|
||||
|
||||
### View Remotes
|
||||
|
||||
```bash
|
||||
# List remotes
|
||||
git remote
|
||||
|
||||
# List remotes with URLs
|
||||
git remote -v
|
||||
|
||||
# Show remote details
|
||||
git remote show origin
|
||||
```
|
||||
|
||||
### Manage Remotes
|
||||
|
||||
```bash
|
||||
# Add remote
|
||||
git remote add <name> <url>
|
||||
|
||||
# Remove remote
|
||||
git remote remove <name>
|
||||
|
||||
# Rename remote
|
||||
git remote rename <old-name> <new-name>
|
||||
|
||||
# Change remote URL
|
||||
git remote set-url <name> <new-url>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### View Configuration
|
||||
|
||||
```bash
|
||||
# View all config
|
||||
git config --list
|
||||
|
||||
# View global config
|
||||
git config --global --list
|
||||
|
||||
# View local config
|
||||
git config --local --list
|
||||
|
||||
# View specific config
|
||||
git config user.name
|
||||
git config user.email
|
||||
```
|
||||
|
||||
### Set Configuration
|
||||
|
||||
```bash
|
||||
# Set user name
|
||||
git config --global user.name "Your Name"
|
||||
|
||||
# Set user email
|
||||
git config --global user.email "your.email@example.com"
|
||||
|
||||
# Set default branch name
|
||||
git config --global init.defaultBranch main
|
||||
|
||||
# Set default editor
|
||||
git config --global core.editor "code --wait"
|
||||
|
||||
# Set credential helper
|
||||
git config --global credential.helper store
|
||||
```
|
||||
|
||||
## Workflow Examples
|
||||
|
||||
### Standard Commit and Tag Workflow
|
||||
|
||||
```bash
|
||||
# 1. Check status
|
||||
git status
|
||||
git diff --cached --name-only
|
||||
|
||||
# 2. Stage changes
|
||||
git add .
|
||||
|
||||
# 3. Commit
|
||||
git commit -m "feat: add user authentication"
|
||||
|
||||
# 4. Create tag
|
||||
git tag -a "1.2.0" -m "feat: add user authentication"
|
||||
|
||||
# 5. Push commit and tag
|
||||
git push origin main
|
||||
git push origin 1.2.0
|
||||
```
|
||||
|
||||
### Complete Staging to Push Workflow
|
||||
|
||||
```bash
|
||||
# Check what files changed
|
||||
git status
|
||||
|
||||
# View changes
|
||||
git diff
|
||||
|
||||
# Stage specific files
|
||||
git add src/auth.js src/api.js
|
||||
|
||||
# Verify staging
|
||||
git diff --cached --name-only
|
||||
|
||||
# Commit with message
|
||||
git commit -m "feat: implement OAuth2 authentication"
|
||||
|
||||
# Push to remote
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Push All Tags Workflow
|
||||
|
||||
```bash
|
||||
# List local tags
|
||||
git tag
|
||||
|
||||
# View recent tags
|
||||
git tag --list | sort -V | tail -5
|
||||
|
||||
# Push all tags to remote
|
||||
git push --tags
|
||||
|
||||
# Verify tags on remote
|
||||
git ls-remote --tags origin
|
||||
```
|
||||
|
||||
### Quick Status Check
|
||||
|
||||
```bash
|
||||
# Full status
|
||||
git status
|
||||
|
||||
# Changed files only
|
||||
git diff --name-only
|
||||
git diff --cached --name-only
|
||||
|
||||
# Recent commits and tags
|
||||
git log --oneline -5
|
||||
git tag --list | sort -V | tail -5
|
||||
|
||||
# Current branch
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
## Tips and Tricks
|
||||
|
||||
### Aliases
|
||||
|
||||
Add to `~/.gitconfig`:
|
||||
|
||||
```ini
|
||||
[alias]
|
||||
st = status
|
||||
co = checkout
|
||||
br = branch
|
||||
ci = commit
|
||||
unstage = restore --staged
|
||||
last = log -1 HEAD
|
||||
lg = log --graph --oneline --all
|
||||
tags = tag -l --sort=-v:refname
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
git st
|
||||
git co main
|
||||
git lg
|
||||
```
|
||||
|
||||
### Useful One-Liners
|
||||
|
||||
```bash
|
||||
# Delete all merged branches
|
||||
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
|
||||
|
||||
# View file in specific commit
|
||||
git show <commit>:<file-path>
|
||||
|
||||
# Count commits by author
|
||||
git shortlog -sn
|
||||
|
||||
# Find when a line was changed
|
||||
git blame <file-path>
|
||||
|
||||
# Show what changed in each commit for a file
|
||||
git log -p <file-path>
|
||||
|
||||
# List files in a commit
|
||||
git diff-tree --no-commit-id --name-only -r <commit>
|
||||
```
|
||||
@@ -58,6 +58,7 @@ C:\Users\YourUsername\.config\gitea\
|
||||
|---------|------|------|
|
||||
| 环境配置 | [setup-guide.md](./setup-guide.md) | 首次使用引导,配置 Gitea URL 和 Token |
|
||||
| Runner 管理 | [runner-management.md](./runner-management.md) | 创建、注册、管理 Gitea Act Runner |
|
||||
| 自动创建脚本 | [create-runner.md](./create-runner.md) | 包含完整的 Runner 创建 Bash 脚本 |
|
||||
| Workflow 生成 | [workflow-generator.md](./workflow-generator.md) | 根据项目类型生成 CI/CD workflow |
|
||||
| 仓库操作 | [repository-operations.md](./repository-operations.md) | 创建和配置 Gitea 仓库 |
|
||||
| API 参考 | [api-reference.md](./api-reference.md) | Gitea API 常用接口 |
|
||||
|
||||
416
skill/gitea/create-runner.md
Normal file
416
skill/gitea/create-runner.md
Normal file
@@ -0,0 +1,416 @@
|
||||
---
|
||||
description: 创建并启动 Gitea Actions Runner 的完整脚本
|
||||
agent: general
|
||||
---
|
||||
|
||||
# Create Runner Script
|
||||
|
||||
本文档包含用于创建 Gitea Actions Runner 的完整 Bash 脚本。该脚本支持 Host 模式和 Docker 模式。
|
||||
|
||||
## 脚本文件
|
||||
|
||||
你可以将以下内容保存为 `create_runner.sh` 并赋予执行权限 (`chmod +x create_runner.sh`)。
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Gitea Runner Creation Script
|
||||
# Generated by OpenCode Skill
|
||||
|
||||
set -e
|
||||
|
||||
# ==========================================
|
||||
# 1. Choose Mode & Check Dependencies
|
||||
# ==========================================
|
||||
|
||||
echo "请选择 Runner 运行模式:"
|
||||
echo " 1. Host Mode (直接在宿主机运行,支持 macOS/iOS 原生构建)"
|
||||
echo " 2. Docker Mode (在容器中运行,环境隔离,适合标准 Linux 构建)"
|
||||
echo ""
|
||||
read -p "请输入选项 [1/2] (默认 1): " mode_choice
|
||||
|
||||
if [ "$mode_choice" = "2" ]; then
|
||||
RUNNER_MODE="docker"
|
||||
echo "✅ 已选择: Docker Mode"
|
||||
else
|
||||
RUNNER_MODE="host"
|
||||
echo "✅ 已选择: Host Mode"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check dependencies based on mode
|
||||
if [ "$RUNNER_MODE" = "host" ]; then
|
||||
echo "检查 act_runner 安装状态..."
|
||||
if command -v act_runner &> /dev/null; then
|
||||
version=$(act_runner --version 2>&1 | head -n1)
|
||||
echo "✓ act_runner 已安装: $version"
|
||||
else
|
||||
echo "⚠️ act_runner 未安装"
|
||||
echo "正在使用 Homebrew 安装..."
|
||||
if ! command -v brew &> /dev/null; then
|
||||
echo "❌ 需要先安装 Homebrew"
|
||||
exit 1
|
||||
fi
|
||||
brew install act_runner
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✓ act_runner 安装成功"
|
||||
else
|
||||
echo "❌ act_runner 安装失败"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Docker mode checks
|
||||
echo "检查 Docker 环境..."
|
||||
if command -v docker &> /dev/null; then
|
||||
if docker info &> /dev/null; then
|
||||
docker_ver=$(docker --version)
|
||||
echo "✓ Docker 已安装并运行: $docker_ver"
|
||||
else
|
||||
echo "❌ Docker 已安装但未运行"
|
||||
echo " 请启动 Docker Desktop"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "❌ Docker 未安装"
|
||||
echo " Docker 模式需要预先安装 Docker"
|
||||
echo " 请访问 https://www.docker.com/products/docker-desktop/ 下载安装"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 2. Load Gitea Configuration
|
||||
# ==========================================
|
||||
|
||||
config_file="$HOME/.config/gitea/config.env"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "❌ Gitea 配置不存在,请先运行 /gitea-reset"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$config_file"
|
||||
|
||||
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
|
||||
echo "❌ Gitea 配置不完整 (缺少 URL 或 TOKEN)"
|
||||
echo " 请运行 /gitea-reset 重新配置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 已加载 Gitea 配置: $GITEA_URL"
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 3. Generate Runner Name
|
||||
# ==========================================
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
runner_name="$1"
|
||||
echo "使用指定的 Runner 名称: $runner_name"
|
||||
else
|
||||
hostname=$(hostname -s 2>/dev/null || echo "unknown")
|
||||
runner_name="runner-$hostname-$RUNNER_MODE"
|
||||
echo "生成 Runner 名称: $runner_name"
|
||||
fi
|
||||
|
||||
if [[ ! "$runner_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
echo "❌ Runner 名称无效 (仅限字母、数字、下划线、连字符)"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 4. Check Runner Existence
|
||||
# ==========================================
|
||||
|
||||
runners_dir="$HOME/.config/gitea/runners"
|
||||
runner_dir="$runners_dir/$runner_name"
|
||||
|
||||
if [ "$RUNNER_MODE" = "host" ]; then
|
||||
if [ -d "$runner_dir" ]; then
|
||||
echo "❌ Runner 目录已存在: $runner_dir"
|
||||
echo " 请使用 /gitea-delete-runner 删除旧 Runner 或指定新名称"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Docker mode: check directory AND container
|
||||
if [ -d "$runner_dir" ]; then
|
||||
echo "❌ Runner 配置目录已存在: $runner_dir"
|
||||
exit 1
|
||||
fi
|
||||
if docker ps -a --format '{{.Names}}' | grep -q "^${runner_name}$"; then
|
||||
echo "❌ Docker 容器已存在: $runner_name"
|
||||
echo " 请先删除旧容器: docker rm -f $runner_name"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ==========================================
|
||||
# 5. Detect System Environment & Labels
|
||||
# ==========================================
|
||||
|
||||
echo "生成 Labels..."
|
||||
|
||||
if [ "$RUNNER_MODE" = "host" ]; then
|
||||
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
|
||||
|
||||
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
|
||||
labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
|
||||
|
||||
else
|
||||
# Docker mode uses standard labels mapping to images
|
||||
# Format: label:docker://image
|
||||
labels="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-buster,linux:docker://node:16-bullseye"
|
||||
fi
|
||||
|
||||
echo "✓ Labels ($RUNNER_MODE):"
|
||||
echo " $labels"
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 6. Create Runner Directory
|
||||
# ==========================================
|
||||
|
||||
echo "创建 Runner 目录..."
|
||||
mkdir -p "$runner_dir"/{cache,workspace}
|
||||
if [ "$RUNNER_MODE" = "docker" ]; then
|
||||
# Docker mode might strictly need data dir mapping
|
||||
mkdir -p "$runner_dir/data"
|
||||
fi
|
||||
echo "✓ 目录: $runner_dir"
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 7. Get Registration Token
|
||||
# ==========================================
|
||||
|
||||
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
|
||||
|
||||
# Need jq for parsing json
|
||||
if ! command -v jq &> /dev/null; then
|
||||
# Simple grep fallback if jq not available, but jq is better
|
||||
registration_token=$(echo "$body" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||||
else
|
||||
registration_token=$(echo "$body" | jq -r '.token')
|
||||
fi
|
||||
|
||||
if [ -z "$registration_token" ]; then
|
||||
echo "❌ 无法解析注册 Token"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ 注册 Token 已获取"
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 8. Start Runner (Register & Run)
|
||||
# ==========================================
|
||||
|
||||
echo "启动 Runner..."
|
||||
|
||||
if [ "$RUNNER_MODE" = "host" ]; then
|
||||
# Host Mode Config
|
||||
cat > "$runner_dir/config.yaml" << EOF
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: .runner
|
||||
capacity: 1
|
||||
timeout: 3h
|
||||
shutdown_timeout: 30s
|
||||
insecure: false
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels: []
|
||||
cache:
|
||||
enabled: true
|
||||
dir: "$runner_dir/cache"
|
||||
host: "127.0.0.1"
|
||||
port: 0
|
||||
host:
|
||||
workdir_parent: "$runner_dir/workspace"
|
||||
EOF
|
||||
|
||||
echo "注册 Host Runner..."
|
||||
act_runner register \
|
||||
--config "$runner_dir/config.yaml" \
|
||||
--instance "$GITEA_URL" \
|
||||
--token "$registration_token" \
|
||||
--name "$runner_name" \
|
||||
--labels "$labels" \
|
||||
--no-interactive
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ 注册失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "启动后台进程..."
|
||||
nohup act_runner daemon --config "$runner_dir/config.yaml" \
|
||||
> "$runner_dir/runner.log" 2>&1 &
|
||||
runner_pid=$!
|
||||
sleep 3
|
||||
|
||||
if ps -p $runner_pid > /dev/null 2>&1; then
|
||||
echo "✓ Host Runner 正在后台运行 (PID: $runner_pid)"
|
||||
# Save PID
|
||||
echo $runner_pid > "$runner_dir/pid"
|
||||
else
|
||||
echo "❌ 启动失败,请检查日志"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# Docker Mode
|
||||
# Strategy: Use environment variables for auto-registration on startup
|
||||
# This avoids the "Instance Address Empty" issue seen with 'act_runner register' inside containers
|
||||
|
||||
cat > "$runner_dir/config.yaml" << EOF
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: /data/.runner
|
||||
capacity: 2
|
||||
timeout: 3h
|
||||
shutdown_timeout: 30s
|
||||
insecure: false
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels: []
|
||||
cache:
|
||||
enabled: true
|
||||
dir: "/data/cache"
|
||||
host: "host.docker.internal"
|
||||
port: 9040
|
||||
container:
|
||||
# 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
|
||||
network: "host"
|
||||
privileged: false
|
||||
options:
|
||||
workdir_parent: /data/workspace
|
||||
valid_volumes: []
|
||||
docker_host: ""
|
||||
force_pull: false
|
||||
host:
|
||||
workdir_parent: /data/workspace
|
||||
EOF
|
||||
|
||||
echo "启动 Docker 容器 (自动注册)..."
|
||||
|
||||
# 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
|
||||
docker run -d \
|
||||
--name "$runner_name" \
|
||||
--restart always \
|
||||
--network host \
|
||||
-v "$runner_dir/config.yaml:/config.yaml" \
|
||||
-v "$runner_dir/data:/data" \
|
||||
-v "/var/run/docker.sock:/var/run/docker.sock" \
|
||||
-e GITEA_INSTANCE_URL="$GITEA_URL" \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN="$registration_token" \
|
||||
-e GITEA_RUNNER_NAME="$runner_name" \
|
||||
-e GITEA_RUNNER_LABELS="$labels" \
|
||||
gitea/act_runner:latest daemon --config /config.yaml
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✓ Docker Runner 容器已启动: $runner_name"
|
||||
# 等待容器启动并查看日志
|
||||
sleep 5
|
||||
echo "容器日志:"
|
||||
docker logs "$runner_name" 2>&1 | tail -20
|
||||
else
|
||||
echo "❌ 容器启动失败"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 9. Display Summary
|
||||
# ==========================================
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "✅ Runner 创建成功!"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "基本信息:"
|
||||
echo " 名称: $runner_name"
|
||||
echo " 模式: $RUNNER_MODE"
|
||||
echo " 状态: 🟢 运行中"
|
||||
|
||||
if [ "$RUNNER_MODE" = "host" ]; then
|
||||
echo " PID: $runner_pid"
|
||||
echo " 日志: $runner_dir/runner.log"
|
||||
echo " 停止: kill \$(cat $runner_dir/pid)"
|
||||
else
|
||||
echo " 容器: $runner_name"
|
||||
echo " 命令: docker logs -f $runner_name"
|
||||
echo " docker stop $runner_name"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "配置文件: $runner_dir/config.yaml"
|
||||
echo "Labels: $labels"
|
||||
echo ""
|
||||
```
|
||||
303
skill/gitea/delete-runner.md
Normal file
303
skill/gitea/delete-runner.md
Normal file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
description: 交互式批量删除 Gitea Runners 脚本
|
||||
agent: general
|
||||
---
|
||||
|
||||
# Delete Runner Script
|
||||
|
||||
本文档包含用于交互式批量删除 Gitea Actions Runner 的完整 Bash 脚本。
|
||||
|
||||
## 功能特点
|
||||
- **多选支持**:支持输入多个序号(如 `1,3` 或 `1 3`)或 `all` 进行批量删除。
|
||||
- **双重清理**:同时从 Gitea 服务器注销 Runner 和删除本地配置/容器。
|
||||
- **智能识别**:自动关联远程 Runner 状态与本地 Runner 目录。
|
||||
- **安全检查**:删除前强制二次确认,防止误删。
|
||||
|
||||
## 脚本文件
|
||||
|
||||
你可以将以下内容保存为 `delete_runner.sh` 并赋予执行权限 (`chmod +x delete_runner.sh`)。
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Gitea Runner Deletion Script
|
||||
# Generated by OpenCode Skill
|
||||
|
||||
set -e
|
||||
|
||||
# ==========================================
|
||||
# 1. Setup & Config
|
||||
# ==========================================
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Config
|
||||
CONFIG_FILE="$HOME/.config/gitea/config.env"
|
||||
RUNNERS_BASE_DIR="$HOME/.config/gitea/runners"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo -e "${RED}❌ 配置文件不存在: $CONFIG_FILE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
|
||||
echo -e "${RED}❌ 配置无效: 缺少 URL 或 Token${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check requirements
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo -e "${RED}❌ 需要安装 jq 工具来解析 JSON${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "正在获取 Runner 列表..."
|
||||
|
||||
# ==========================================
|
||||
# 2. Data Collection
|
||||
# ==========================================
|
||||
|
||||
# Temporary files
|
||||
REMOTE_LIST=$(mktemp)
|
||||
LOCAL_MAP=$(mktemp)
|
||||
FINAL_LIST=$(mktemp)
|
||||
|
||||
# 2.1 Fetch Remote Runners (Try Admin first, then Org)
|
||||
# Note: Admin endpoint /api/v1/admin/runners lists all runners
|
||||
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REMOTE_LIST" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/runners?page=1&limit=100")
|
||||
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
# Fallback to Org level if defined
|
||||
if [ -n "$GITEA_DEFAULT_ORG" ]; then
|
||||
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REMOTE_LIST" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/orgs/${GITEA_DEFAULT_ORG}/actions/runners?page=1&limit=100")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
echo -e "${RED}❌ 无法获取 Runner 列表 (HTTP $HTTP_CODE)${NC}"
|
||||
cat "$REMOTE_LIST"
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2.2 Scan Local Directories to map UUID -> Path
|
||||
# We need to find which local directory corresponds to which runner ID/UUID
|
||||
echo "{}" > "$LOCAL_MAP"
|
||||
|
||||
if [ -d "$RUNNERS_BASE_DIR" ]; then
|
||||
for d in "$RUNNERS_BASE_DIR"/*; do
|
||||
if [ -d "$d" ]; then
|
||||
# Check Host mode .runner
|
||||
if [ -f "$d/.runner" ]; then
|
||||
uuid=$(jq -r '.uuid' "$d/.runner" 2>/dev/null)
|
||||
if [ -n "$uuid" ] && [ "$uuid" != "null" ]; then
|
||||
# Add to JSON map
|
||||
tmp=$(mktemp)
|
||||
jq --arg uuid "$uuid" --arg path "$d" '.[$uuid] = $path' "$LOCAL_MAP" > "$tmp" && mv "$tmp" "$LOCAL_MAP"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check Docker mode data/.runner
|
||||
if [ -f "$d/data/.runner" ]; then
|
||||
uuid=$(jq -r '.uuid' "$d/data/.runner" 2>/dev/null)
|
||||
if [ -n "$uuid" ] && [ "$uuid" != "null" ]; then
|
||||
tmp=$(mktemp)
|
||||
jq --arg uuid "$uuid" --arg path "$d" '.[$uuid] = $path' "$LOCAL_MAP" > "$tmp" && mv "$tmp" "$LOCAL_MAP"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ==========================================
|
||||
# 3. Display Interface
|
||||
# ==========================================
|
||||
|
||||
# Combine Remote and Local info
|
||||
# Output format: index | id | name | status | local_path
|
||||
jq -r --slurpfile local "$LOCAL_MAP" '
|
||||
.runners[] |
|
||||
[.id, .uuid, .name, .status, ($local[0][.uuid] // "")] |
|
||||
@tsv
|
||||
' "$REMOTE_LIST" > "$FINAL_LIST"
|
||||
|
||||
count=$(wc -l < "$FINAL_LIST" | tr -d ' ')
|
||||
|
||||
if [ "$count" -eq 0 ]; then
|
||||
echo "没有发现任何 Runners。"
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Gitea Runners 列表 (共 $count 个)${NC}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
printf "%-4s | %-8s | %-20s | %-10s | %-30s\n" "序号" "ID" "名称" "状态" "本地目录"
|
||||
echo "----------------------------------------------------------------------------"
|
||||
|
||||
i=1
|
||||
declare -a runner_ids
|
||||
declare -a runner_names
|
||||
declare -a runner_paths
|
||||
|
||||
while IFS=$'\t' read -r id uuid name status local_path; do
|
||||
status_icon="🔴"
|
||||
if [ "$status" = "online" ] || [ "$status" = "idle" ] || [ "$status" = "active" ]; then
|
||||
status_icon="🟢"
|
||||
fi
|
||||
|
||||
local_mark=""
|
||||
if [ -n "$local_path" ]; then
|
||||
local_mark="$(basename "$local_path")"
|
||||
else
|
||||
local_mark="-"
|
||||
fi
|
||||
|
||||
printf "%-4d | %-8s | %-20s | %s %-8s | %-30s\n" "$i" "$id" "${name:0:20}" "$status_icon" "$status" "$local_mark"
|
||||
|
||||
runner_ids[$i]=$id
|
||||
runner_names[$i]=$name
|
||||
runner_paths[$i]=$local_path
|
||||
|
||||
i=$((i+1))
|
||||
done < "$FINAL_LIST"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# ==========================================
|
||||
# 4. User Selection
|
||||
# ==========================================
|
||||
|
||||
echo "请输入要删除的序号:"
|
||||
echo " - 单个: 1"
|
||||
echo " - 多选: 1,3,5 或 1 3 5"
|
||||
echo " - 全部: all"
|
||||
echo " - 退出: q"
|
||||
echo ""
|
||||
read -p "选择 > " selection
|
||||
|
||||
if [[ "$selection" =~ ^[qQ] ]]; then
|
||||
echo "已取消。"
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
target_indices=()
|
||||
|
||||
if [ "$selection" = "all" ]; then
|
||||
for ((j=1; j<=count; j++)); do
|
||||
target_indices+=($j)
|
||||
done
|
||||
else
|
||||
# Replace commas with spaces and iterate
|
||||
for idx in ${selection//,/ }; do
|
||||
# Validate number
|
||||
if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le "$count" ]; then
|
||||
target_indices+=($idx)
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ 忽略无效序号: $idx${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${#target_indices[@]} -eq 0 ]; then
|
||||
echo -e "${RED}未选择任何有效 Runner。${NC}"
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==========================================
|
||||
# 5. Confirmation
|
||||
# ==========================================
|
||||
|
||||
echo ""
|
||||
echo -e "${RED}⚠️ 警告: 即将删除以下 ${#target_indices[@]} 个 Runner:${NC}"
|
||||
for idx in "${target_indices[@]}"; do
|
||||
echo " - [${runner_ids[$idx]}] ${runner_names[$idx]}"
|
||||
if [ -n "${runner_paths[$idx]}" ]; then
|
||||
echo " └─ 本地目录: ${runner_paths[$idx]}"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
echo "此操作将从服务器注销 Runner 并删除本地文件/容器。"
|
||||
read -p "确认删除? (输入 yes 继续): " confirm
|
||||
|
||||
if [ "$confirm" != "yes" ]; then
|
||||
echo "操作已取消。"
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ==========================================
|
||||
# 6. Execution
|
||||
# ==========================================
|
||||
|
||||
echo ""
|
||||
echo "开始执行删除..."
|
||||
|
||||
for idx in "${target_indices[@]}"; do
|
||||
r_id="${runner_ids[$idx]}"
|
||||
r_name="${runner_names[$idx]}"
|
||||
r_path="${runner_paths[$idx]}"
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "正在处理: $r_name (ID: $r_id)"
|
||||
|
||||
# 6.1 Delete from Server
|
||||
echo -n " 1. 从服务器注销... "
|
||||
del_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/actions/runners/${r_id}")
|
||||
|
||||
if [ "$del_code" = "204" ] || [ "$del_code" = "404" ]; then
|
||||
echo -e "${GREEN}成功${NC}"
|
||||
else
|
||||
echo -e "${RED}失败 (HTTP $del_code)${NC}"
|
||||
# Continue cleanup anyway
|
||||
fi
|
||||
|
||||
# 6.2 Cleanup Local
|
||||
if [ -n "$r_path" ] && [ -d "$r_path" ]; then
|
||||
dir_name=$(basename "$r_path")
|
||||
|
||||
# Stop Docker container if name matches folder name (common convention)
|
||||
if docker ps -a --format '{{.Names}}' | grep -q "^${dir_name}$"; then
|
||||
echo -n " 2. 停止并删除 Docker 容器 ($dir_name)... "
|
||||
docker rm -f "$dir_name" >/dev/null 2>&1
|
||||
echo -e "${GREEN}完成${NC}"
|
||||
fi
|
||||
|
||||
# Stop Host process (if PID file exists)
|
||||
if [ -f "$r_path/pid" ]; then
|
||||
pid=$(cat "$r_path/pid")
|
||||
echo -n " 2. 停止本地进程 (PID: $pid)... "
|
||||
kill "$pid" >/dev/null 2>&1 || true
|
||||
echo -e "${GREEN}完成${NC}"
|
||||
fi
|
||||
|
||||
echo -n " 3. 删除本地目录... "
|
||||
rm -rf "$r_path"
|
||||
echo -e "${GREEN}完成${NC}"
|
||||
else
|
||||
echo " - 本地目录未找到或已清理"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo -e "${GREEN}✅ 批量删除操作完成${NC}"
|
||||
|
||||
# Cleanup temps
|
||||
rm "$REMOTE_LIST" "$LOCAL_MAP" "$FINAL_LIST"
|
||||
```
|
||||
@@ -267,6 +267,8 @@ act_runner --version
|
||||
7. 获取注册 token(优先全局)
|
||||
8. 注册并启动 runner
|
||||
|
||||
> **提示**:你可以从 [create-runner.md](./create-runner.md) 获取完整的 Bash 脚本。
|
||||
|
||||
### 详细创建流程
|
||||
|
||||
当运行 `/gitea-create-runner` 命令时,会执行以下步骤:
|
||||
@@ -640,23 +642,58 @@ log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: /path/to/.runner
|
||||
file: /data/.runner # 容器内路径
|
||||
capacity: 2
|
||||
timeout: 3h
|
||||
labels:
|
||||
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
|
||||
shutdown_timeout: 30s
|
||||
insecure: false
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels: [] # 通过环境变量设置
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: "/path/to/cache"
|
||||
host: "192.168.0.103" # 主机 IP(非 127.0.0.1)
|
||||
port: 9000
|
||||
dir: "/data/cache" # 容器内缓存目录
|
||||
host: "host.docker.internal" # 宿主机地址(Docker 特殊 DNS)
|
||||
port: 9040 # 缓存服务端口
|
||||
|
||||
container:
|
||||
options: "--platform=linux/amd64" # 容器选项
|
||||
network: "host" # 网络模式
|
||||
# 使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
|
||||
network: "host"
|
||||
privileged: false
|
||||
options:
|
||||
workdir_parent: /data/workspace
|
||||
valid_volumes: []
|
||||
docker_host: ""
|
||||
force_pull: false
|
||||
|
||||
host:
|
||||
workdir_parent: /data/workspace
|
||||
```
|
||||
|
||||
**Docker 容器启动命令**:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name "$runner_name" \
|
||||
--restart always \
|
||||
--network host \
|
||||
-v "$runner_dir/config.yaml:/config.yaml" \
|
||||
-v "$runner_dir/data:/data" \
|
||||
-v "/var/run/docker.sock:/var/run/docker.sock" \
|
||||
-e GITEA_INSTANCE_URL="$GITEA_URL" \
|
||||
-e GITEA_RUNNER_REGISTRATION_TOKEN="$token" \
|
||||
-e GITEA_RUNNER_NAME="$runner_name" \
|
||||
-e GITEA_RUNNER_LABELS="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,linux:docker://node:16-bullseye" \
|
||||
gitea/act_runner:latest daemon --config /config.yaml
|
||||
```
|
||||
|
||||
**关键配置说明**:
|
||||
- `--network host`:使用 host 网络模式,确保 runner 和 job 容器共处一个网络,以便 cache 能够正常访问
|
||||
- `host.docker.internal`:Docker 内部 DNS,指向宿主机
|
||||
- 环境变量自动注册:容器启动时自动完成 Runner 注册
|
||||
- `/var/run/docker.sock`:允许容器内创建兄弟容器执行 jobs
|
||||
|
||||
## 多 Runner 缓存共享
|
||||
|
||||
### 方案 A: Master-Slave 模式(推荐 2-3 个 runner)
|
||||
@@ -778,6 +815,64 @@ crontab -e
|
||||
/gitea-list-runners
|
||||
```
|
||||
|
||||
**API 调用详情**:
|
||||
|
||||
1. **加载配置**:
|
||||
```bash
|
||||
source ~/.config/gitea/config.env
|
||||
```
|
||||
|
||||
2. **调用 API**:
|
||||
```bash
|
||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/actions/runners"
|
||||
```
|
||||
|
||||
3. **响应结构**:
|
||||
```json
|
||||
{
|
||||
"runners": [...],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
4. **解析每个 Runner**:
|
||||
- `id`: Runner ID
|
||||
- `name`: Runner 名称
|
||||
- `status`: 状态("online"/"offline")
|
||||
- `busy`: 是否忙碌(true/false)
|
||||
- `ephemeral`: 是否临时(true/false)
|
||||
- `labels`: 标签数组
|
||||
|
||||
5. **状态图标**:
|
||||
- 🟢 在线 - `status: "online"`
|
||||
- 🔴 离线 - `status: "offline"`
|
||||
- ⚠️ 未知 - 无法确定
|
||||
|
||||
6. **输出格式**:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Gitea 全局 Runners
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
服务器: [server_url]
|
||||
总计: N 个全局 runner
|
||||
|
||||
[runner-name]
|
||||
状态: 🟢/🔴 [在线/离线]
|
||||
ID: [id]
|
||||
忙碌: 是/否
|
||||
临时: 是/否
|
||||
标签: [comma-separated labels]
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 需要管理员 API Token
|
||||
- 正确的 API 端点是 `/api/v1/admin/actions/runners`(不是 `/api/v1/admin/runners`)
|
||||
- 使用 `jq` 解析 JSON 响应
|
||||
|
||||
### 启动 Runner
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user