docs: 重构命令和技能文档体系,规范化文档格式和内容组织
This commit is contained in:
@@ -2,169 +2,64 @@
|
|||||||
description: Stage changes with automatic filtering of sensitive files
|
description: Stage changes with automatic filtering of sensitive files
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-add
|
|
||||||
|
|
||||||
Intelligently stage changes while automatically filtering security-sensitive files.
|
Intelligently stage changes while automatically filtering security-sensitive files.
|
||||||
|
|
||||||
## What It Does
|
Please perform the following:
|
||||||
|
|
||||||
- Detects all unstaged changes
|
1. **Detect all unstaged changes:**
|
||||||
- Automatically excludes common sensitive files (credentials, secrets, etc.)
|
|
||||||
- Previews files that will be staged
|
|
||||||
- Asks for confirmation before staging
|
|
||||||
- Shows excluded sensitive files for awareness
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
Use this command when you want to safely stage changes without accidentally committing sensitive information.
|
|
||||||
|
|
||||||
## Sensitive Files Filtered
|
|
||||||
|
|
||||||
**Always excluded:**
|
|
||||||
- `.env*` - Environment files
|
|
||||||
- `*.key`, `*.pem`, `*.p8` - Private keys
|
|
||||||
- `.aws/*`, `.gcloud/*` - Cloud credentials
|
|
||||||
- `.ssh/*` - SSH keys
|
|
||||||
- `credentials.json`, `secrets.json` - Credential files
|
|
||||||
- `package-lock.json`, `yarn.lock` (optional, can override)
|
|
||||||
- `node_modules/`, `vendor/`, `.venv/` - Dependencies
|
|
||||||
- `dist/`, `build/`, `.next/` - Build artifacts
|
|
||||||
- `.DS_Store`, `Thumbs.db` - System files
|
|
||||||
|
|
||||||
**Custom exclusions:**
|
|
||||||
- Can be specified in project `.gitignore` or `.secretsignore`
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1. Detect All Unstaged Changes
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status --porcelain
|
|
||||||
git diff --name-only
|
|
||||||
```
|
|
||||||
|
|
||||||
Categories:
|
|
||||||
- Modified files (M)
|
- Modified files (M)
|
||||||
- Deleted files (D)
|
- Deleted files (D)
|
||||||
- Untracked files (??) - **重要:第一次就显示并提供选项**
|
- Untracked files (??) - **重要:第一次就显示并提供选项**
|
||||||
|
|
||||||
### 2. Filter Sensitive Files
|
2. **Filter sensitive files** - Automatically exclude:
|
||||||
|
- `.env*` - Environment files
|
||||||
|
- `*.key`, `*.pem`, `*.p8` - Private keys
|
||||||
|
- `.aws/*`, `.gcloud/*`, `.ssh/*` - Cloud/SSH credentials
|
||||||
|
- `credentials.json`, `secrets.json` - Credential files
|
||||||
|
- `node_modules/`, `vendor/`, `.venv/` - Dependencies
|
||||||
|
- `dist/`, `build/`, `.next/` - Build artifacts
|
||||||
|
- `.DS_Store`, `Thumbs.db` - System files
|
||||||
|
|
||||||
Build exclusion list:
|
3. **Categorize files:**
|
||||||
- Read `.gitignore` for patterns
|
- **已跟踪的修改/删除** (tracked modified/deleted)
|
||||||
- Read `.secretsignore` if exists (project-specific rules)
|
- **未跟踪的安全文件** (untracked safe files)
|
||||||
- Apply built-in security patterns
|
- **敏感文件** (sensitive files - filtered)
|
||||||
- Check for `.env*`, `*.key`, `credentials.json`, etc.
|
|
||||||
|
|
||||||
Separate files into:
|
|
||||||
- **Modified/Deleted files (tracked)**: 已跟踪的修改和删除
|
|
||||||
- **Untracked files (safe)**: 未跟踪但安全的新文件
|
|
||||||
- **Sensitive files**: 敏感文件(需要 force 才能暂存)
|
|
||||||
|
|
||||||
**关键逻辑:**
|
|
||||||
- 默认选项 (y): 只暂存已跟踪的修改/删除
|
|
||||||
- all/u 选项: 暂存所有安全文件(包括未跟踪)
|
|
||||||
- force 选项: 暂存所有文件(包括敏感)
|
|
||||||
- 一次性显示所有选项,不需要二次运行命令
|
|
||||||
|
|
||||||
### 3. Display Preview
|
|
||||||
|
|
||||||
Show clear summary in format:
|
|
||||||
|
|
||||||
|
4. **Display preview in Chinese:**
|
||||||
```
|
```
|
||||||
=== 将要暂存的文件 (3) ===
|
=== 将要暂存的文件 (N) ===
|
||||||
M src/index.js
|
M [tracked modified files]
|
||||||
M src/utils.js
|
D [tracked deleted files]
|
||||||
D old-file.js
|
|
||||||
|
|
||||||
=== 未跟踪的文件 (2) ===
|
=== 未跟踪的文件 (N) ===
|
||||||
?? new-feature.js
|
?? [untracked safe files]
|
||||||
?? tests/new-test.js
|
|
||||||
|
|
||||||
=== 敏感文件已过滤 (2) ===
|
=== 敏感文件已过滤 (N) ===
|
||||||
⚠ .env.local (Environment file)
|
⚠ [sensitive files with reasons]
|
||||||
⚠ config/secrets.json (Credential file)
|
|
||||||
|
|
||||||
=== 操作选项 ===
|
=== 操作选项 ===
|
||||||
- 输入 "y" 或 "yes" 暂存已修改/已删除的文件(不包括未跟踪文件)
|
- 输入 "y" 或 "yes" 暂存已修改/已删除的文件(不包括未跟踪文件)
|
||||||
- 输入 "all" 暂存所有文件(包括未跟踪文件,但排除敏感文件)
|
- 输入 "all" 或 "u" 暂存所有安全文件(包括未跟踪文件)✓ 推荐
|
||||||
- 输入 "with-untracked" 或 "u" 暂存所有文件(包括未跟踪文件)
|
- 输入 "force" 强制暂存所有文件(包括敏感文件)⚠️ 谨慎使用
|
||||||
- 输入 "force" 强制暂存所有文件(包括敏感文件,谨慎使用)
|
|
||||||
- 输入 "no" 或 "cancel" 取消操作
|
- 输入 "no" 或 "cancel" 取消操作
|
||||||
- 输入文件路径 暂存特定文件
|
- 输入文件路径 暂存特定文件
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. User Confirmation
|
5. **Wait for user confirmation**
|
||||||
|
|
||||||
Prompt user:
|
6. **Execute staging based on user choice:**
|
||||||
```
|
- `y/yes`: Stage tracked modified/deleted only
|
||||||
是否确认暂存上述文件? (y/all/u/no)
|
- `all/u`: Stage all safe files (including untracked)
|
||||||
```
|
- `force`: Show warning, require "confirm" input, then stage everything
|
||||||
|
- `no/cancel`: Abort
|
||||||
**Options:**
|
- File path: Stage specific file(s)
|
||||||
- `y` or `yes`: Stage modified/deleted files only (exclude untracked)
|
|
||||||
- `all` or `with-untracked` or `u`: Stage all including untracked files (exclude sensitive)
|
|
||||||
- `force`: Stage everything including sensitive files (show warning)
|
|
||||||
- `no` or `cancel`: Abort
|
|
||||||
- File path: Stage only specific file(s)
|
|
||||||
|
|
||||||
**智能提示:**
|
|
||||||
- 如果没有未跟踪文件,只显示 y/no 选项
|
|
||||||
- 如果有未跟踪文件,显示 y/all/u/no 选项,并高亮推荐使用 "all" 或 "u"
|
|
||||||
- 如果有敏感文件,额外显示 force 选项并警告风险
|
|
||||||
|
|
||||||
### 5. Execute Staging
|
|
||||||
|
|
||||||
If user confirms:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Option 1: Stage modified/deleted only (y)
|
|
||||||
git add <modified-file-1> <modified-file-2> ...
|
|
||||||
|
|
||||||
# Option 2: Stage all including untracked (all/u)
|
|
||||||
git add <all-safe-files-including-untracked>
|
|
||||||
|
|
||||||
# Option 3: Stage everything including sensitive (force)
|
|
||||||
git add .
|
|
||||||
```
|
|
||||||
|
|
||||||
**Warning for "force" option:**
|
|
||||||
```
|
|
||||||
⚠️ 警告:你选择暂存所有文件,包括敏感文件!
|
|
||||||
请确认这是有意的,避免意外提交凭证或密钥。
|
|
||||||
|
|
||||||
已暂存的敏感文件:
|
|
||||||
- .env.local
|
|
||||||
- config/secrets.json
|
|
||||||
|
|
||||||
输入 "confirm" 继续,或 "cancel" 取消操作
|
|
||||||
```
|
|
||||||
|
|
||||||
**Success message for "all/u" option:**
|
|
||||||
```
|
|
||||||
✓ 已暂存所有文件(包括未跟踪文件)
|
|
||||||
|
|
||||||
已暂存 5 个文件:
|
|
||||||
M src/index.js
|
|
||||||
M src/utils.js
|
|
||||||
D old-file.js
|
|
||||||
A new-feature.js
|
|
||||||
A tests/new-test.js
|
|
||||||
|
|
||||||
敏感文件已自动过滤并排除。
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Display Result
|
|
||||||
|
|
||||||
Show success message in Chinese:
|
|
||||||
|
|
||||||
|
7. **Display result in Chinese:**
|
||||||
```
|
```
|
||||||
✓ 暂存成功
|
✓ 暂存成功
|
||||||
|
|
||||||
已暂存 3 个文件:
|
已暂存 N 个文件:
|
||||||
M src/index.js
|
[列出已暂存的文件]
|
||||||
M src/utils.js
|
|
||||||
A command/git-add.md
|
|
||||||
|
|
||||||
敏感文件已过滤并排除,保护了你的凭证信息。
|
敏感文件已过滤并排除,保护了你的凭证信息。
|
||||||
|
|
||||||
@@ -173,149 +68,4 @@ Show success message in Chinese:
|
|||||||
- 运行 /git-status 查看暂存区状态
|
- 运行 /git-status 查看暂存区状态
|
||||||
```
|
```
|
||||||
|
|
||||||
## Safety Features
|
**重要:第一次运行就显示所有选项,包括未跟踪文件的处理方式,不需要用户多次运行命令。**
|
||||||
|
|
||||||
### Automatic Filters
|
|
||||||
|
|
||||||
| Pattern | Why | Can Override |
|
|
||||||
|---------|-----|--------------|
|
|
||||||
| `.env*` | Environment variables | No |
|
|
||||||
| `*.key`, `*.pem` | Private keys | No |
|
|
||||||
| `credentials.json` | API credentials | No |
|
|
||||||
| `secrets.json` | Secrets | No |
|
|
||||||
| `.aws/*`, `.gcloud/*` | Cloud credentials | No |
|
|
||||||
| `.ssh/*` | SSH keys | No |
|
|
||||||
| `package-lock.json` | Lock files (optional) | Yes |
|
|
||||||
|
|
||||||
### Warnings
|
|
||||||
|
|
||||||
- Show count of filtered files
|
|
||||||
- List filtered file names for transparency
|
|
||||||
- Warn when using "all" option
|
|
||||||
- Explain why each sensitive file was excluded
|
|
||||||
|
|
||||||
## Use Cases
|
|
||||||
|
|
||||||
- Stage changes safely before commit
|
|
||||||
- Prevent accidental credential leaks
|
|
||||||
- Review what will be committed before staging
|
|
||||||
- Follow security best practices
|
|
||||||
|
|
||||||
## Related Commands
|
|
||||||
|
|
||||||
- `/git-status` - Check file changes before staging
|
|
||||||
- `/git-commit` - Commit staged files
|
|
||||||
- `/git-push` - Push commits to remote
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Normal Usage (无未跟踪文件)
|
|
||||||
```bash
|
|
||||||
/git-add
|
|
||||||
# 显示:3 个已修改文件
|
|
||||||
# 提示:是否确认暂存? (y/no)
|
|
||||||
# 输入 "y" 暂存所有已修改文件
|
|
||||||
```
|
|
||||||
|
|
||||||
### 包含未跟踪文件的情况
|
|
||||||
```bash
|
|
||||||
/git-add
|
|
||||||
# 显示:
|
|
||||||
# - 3 个已修改/已删除文件
|
|
||||||
# - 2 个未跟踪文件
|
|
||||||
# 提示:是否确认暂存? (y/all/u/no)
|
|
||||||
# 输入 "y" 仅暂存已修改文件
|
|
||||||
# 输入 "all" 或 "u" 暂存所有文件(包括未跟踪)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 强制暂存敏感文件
|
|
||||||
```bash
|
|
||||||
/git-add
|
|
||||||
# 显示:包含 2 个敏感文件
|
|
||||||
# 提示:是否确认暂存? (y/all/force/no)
|
|
||||||
# 输入 "force" 强制暂存所有文件
|
|
||||||
# ⚠️ 显示二次确认警告
|
|
||||||
```
|
|
||||||
|
|
||||||
### 暂存特定文件
|
|
||||||
```bash
|
|
||||||
/git-add
|
|
||||||
# 显示预览
|
|
||||||
# 输入文件路径:src/index.js
|
|
||||||
# 仅暂存指定的文件
|
|
||||||
```
|
|
||||||
|
|
||||||
### 取消操作
|
|
||||||
```bash
|
|
||||||
/git-add
|
|
||||||
# 显示预览
|
|
||||||
# 输入 "no" 或 "cancel"
|
|
||||||
# 操作中止
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementation Guide
|
|
||||||
|
|
||||||
### 关键实现要点
|
|
||||||
|
|
||||||
**1. 文件分类逻辑**
|
|
||||||
```bash
|
|
||||||
# 获取所有状态
|
|
||||||
git status --porcelain
|
|
||||||
|
|
||||||
# 分类处理
|
|
||||||
tracked_modified=() # M 状态
|
|
||||||
tracked_deleted=() # D 状态
|
|
||||||
untracked_safe=() # ?? 状态且非敏感
|
|
||||||
untracked_sensitive=() # ?? 状态且敏感
|
|
||||||
tracked_sensitive=() # M/D 状态但匹配敏感规则
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. 选项显示逻辑**
|
|
||||||
```python
|
|
||||||
if has_untracked_files:
|
|
||||||
if has_sensitive_files:
|
|
||||||
prompt = "是否确认暂存? (y/all/force/no)"
|
|
||||||
options = {
|
|
||||||
"y": "仅暂存已跟踪的修改/删除",
|
|
||||||
"all/u": "暂存所有安全文件(含未跟踪)",
|
|
||||||
"force": "暂存所有文件(含敏感)⚠️",
|
|
||||||
"no": "取消操作"
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
prompt = "是否确认暂存? (y/all/no)"
|
|
||||||
options = {
|
|
||||||
"y": "仅暂存已跟踪的修改/删除",
|
|
||||||
"all/u": "暂存所有文件(含未跟踪)✓ 推荐",
|
|
||||||
"no": "取消操作"
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
prompt = "是否确认暂存? (y/no)"
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. 执行逻辑**
|
|
||||||
```bash
|
|
||||||
case $choice in
|
|
||||||
y|yes)
|
|
||||||
git add "${tracked_modified[@]}" "${tracked_deleted[@]}"
|
|
||||||
;;
|
|
||||||
all|u|with-untracked)
|
|
||||||
git add "${tracked_modified[@]}" "${tracked_deleted[@]}" "${untracked_safe[@]}"
|
|
||||||
;;
|
|
||||||
force)
|
|
||||||
# 二次确认
|
|
||||||
read -p "⚠️ 确认暂存敏感文件? (输入 confirm): " confirm
|
|
||||||
if [[ "$confirm" == "confirm" ]]; then
|
|
||||||
git add .
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- This command prioritizes security over convenience
|
|
||||||
- Sensitive files must be explicitly forced to stage
|
|
||||||
- **重要:第一次运行就显示所有选项,不需要用户多次运行命令**
|
|
||||||
- Untracked files are displayed upfront with clear options
|
|
||||||
- Use `.secretsignore` file for project-specific exclusion patterns
|
|
||||||
- Consider setting up git hooks for additional security
|
|
||||||
|
|||||||
@@ -2,188 +2,51 @@
|
|||||||
description: Commit staged files with auto-generated message and create version tag
|
description: Commit staged files with auto-generated message and create version tag
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-commit
|
Auto-generate a commit message for staged files, commit to the local repository, and create a version tag following semantic versioning.
|
||||||
|
|
||||||
Auto-generate commit message for staged files, commit to local repository, and create version tag.
|
Please follow the git workflow defined in `@skill/git/SKILL.md`:
|
||||||
|
|
||||||
## What It Does
|
1. **Check staging area** - Verify files are staged with `git diff --cached --name-only`
|
||||||
|
- If empty, inform the user and stop
|
||||||
- Analyzes staged changes
|
2. **Collect information** - Run these commands in parallel:
|
||||||
- Auto-generates meaningful commit message following Conventional Commits
|
- `git status`
|
||||||
- Detects project type and updates version number if needed
|
- `git diff --cached`
|
||||||
- Creates appropriate git tag (polyrepo or monorepo format)
|
- `git log --oneline -10`
|
||||||
- Does NOT push to remote (local only)
|
- `git tag --list | sort -V | tail -5`
|
||||||
|
- Read `@AGENTS.md` if it exists (repository type, version rules, project structure)
|
||||||
## Quick Start
|
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:
|
||||||
Use this command when you have files in staging area and want to commit with proper version tagging.
|
|
||||||
|
|
||||||
## Workflow
|
|
||||||
|
|
||||||
This command follows the git workflow defined in `skill/git/SKILL.md`:
|
|
||||||
|
|
||||||
1. ✓ Check staging area (must have files)
|
|
||||||
2. ✓ Analyze changes and repository type
|
|
||||||
3. ✓ Detect project type and version file
|
|
||||||
4. ✓ Generate commit message (Conventional Commits)
|
|
||||||
5. ✓ Update version number if needed
|
|
||||||
6. ✓ Commit with generated message
|
|
||||||
7. ✓ Create version tag
|
|
||||||
8. ✗ Skip push (use `/git-push` to push)
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
**Staging area must not be empty:**
|
|
||||||
```bash
|
|
||||||
git add <files>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
User can optionally input:
|
|
||||||
- **"skip tag"** or **"skip"**: Skip tag creation, only commit
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1. Check Staging Area
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git diff --cached --name-only
|
|
||||||
```
|
|
||||||
|
|
||||||
**If empty:**
|
|
||||||
- Display: "暂存区为空,请先使用 `git add` 添加文件。"
|
|
||||||
- **Terminate execution**
|
|
||||||
|
|
||||||
### 2. Collect Information (parallel)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git diff --cached
|
|
||||||
git log --oneline -10
|
|
||||||
git tag --list | sort -V | tail -5
|
|
||||||
```
|
|
||||||
|
|
||||||
If `AGENTS.md` exists, read it for:
|
|
||||||
- Repository type (polyrepo/monorepo)
|
|
||||||
- Version update rules
|
|
||||||
- Project structure
|
|
||||||
|
|
||||||
### 3. Detect Repository Type
|
|
||||||
|
|
||||||
- **Polyrepo**: Single project, tag format `1.2.0`
|
|
||||||
- **Monorepo**: Multiple subprojects, tag format `<subproject>-1.2.0`
|
|
||||||
|
|
||||||
Detection:
|
|
||||||
- Check `AGENTS.md` for monorepo indicator
|
|
||||||
- Check directory structure (`packages/`, `apps/`, etc.)
|
|
||||||
- Analyze changed file paths for subproject scope
|
|
||||||
|
|
||||||
### 4. Detect Project Type and Version
|
|
||||||
|
|
||||||
Follow `skill/git/SKILL.md` guidelines:
|
|
||||||
|
|
||||||
**Common project types:**
|
|
||||||
- iOS: `*.xcodeproj/project.pbxproj` → `MARKETING_VERSION`
|
- iOS: `*.xcodeproj/project.pbxproj` → `MARKETING_VERSION`
|
||||||
- Node.js: `package.json` → `version`
|
- Node.js: `package.json` → `version`
|
||||||
- Android: `build.gradle(.kts)` → `versionName`
|
- Android: `build.gradle(.kts)` → `versionName`
|
||||||
- Go: Git tag only (no version file)
|
- Go: Git tag only
|
||||||
- etc.
|
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"`
|
||||||
|
|
||||||
**Version increment rules:**
|
**Options:**
|
||||||
- `feat`: minor +1 → `1.2.0` → `1.3.0`
|
- User can input "skip tag" or "skip" to skip tag creation
|
||||||
- `fix`: patch +1 → `1.2.3` → `1.2.4`
|
|
||||||
- `perf`: patch +1
|
|
||||||
- Breaking change: major +1 → `1.2.3` → `2.0.0`
|
|
||||||
|
|
||||||
**Only update version for user-perceivable changes:**
|
**Display result in Chinese:**
|
||||||
- ✓ feat, fix, perf, breaking changes
|
|
||||||
- ✗ docs, test, refactor, style, chore, ci, build
|
|
||||||
|
|
||||||
### 5. Generate Commit Message
|
|
||||||
|
|
||||||
Follow Conventional Commits specification:
|
|
||||||
|
|
||||||
**Format:**
|
|
||||||
```
|
|
||||||
<type>(<scope>): <subject>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Commit language:**
|
|
||||||
- macOS/Linux: Chinese (中文)
|
|
||||||
- Windows: English (encoding issue)
|
|
||||||
|
|
||||||
**Monorepo scope:**
|
|
||||||
- If changes affect single subproject: `feat(ios): 添加新功能`
|
|
||||||
- If multiple subprojects: `feat: 添加新功能`
|
|
||||||
|
|
||||||
### 6. Update Version Number
|
|
||||||
|
|
||||||
If version update is needed:
|
|
||||||
|
|
||||||
1. Update version file with new version
|
|
||||||
2. Add version file to staging: `git add <version-file>`
|
|
||||||
3. Verify: `git diff --cached --name-only`
|
|
||||||
|
|
||||||
### 7. Commit Changes
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# macOS/Linux (Chinese)
|
|
||||||
git commit -m "feat(android): 添加用户认证"
|
|
||||||
|
|
||||||
# Windows (English)
|
|
||||||
git commit -m "feat(android): add user authentication"
|
|
||||||
|
|
||||||
# Multi-line (macOS/Linux)
|
|
||||||
git commit -m "$(cat <<'EOF'
|
|
||||||
feat: add user authentication
|
|
||||||
|
|
||||||
- Add OAuth2 support
|
|
||||||
- Implement JWT tokens
|
|
||||||
EOF
|
|
||||||
)"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Create Tag
|
|
||||||
|
|
||||||
**Only if:**
|
|
||||||
- Version update occurred
|
|
||||||
- User didn't input "skip tag"
|
|
||||||
|
|
||||||
**Tag format:**
|
|
||||||
- Polyrepo: `git tag -a "1.2.0" -m "feat: add feature"`
|
|
||||||
- Monorepo: `git tag -a "ios-1.2.0" -m "feat(ios): add feature"`
|
|
||||||
|
|
||||||
**Tag annotation:**
|
|
||||||
- Use same content as commit message
|
|
||||||
- Multi-line commits → multi-line annotations
|
|
||||||
|
|
||||||
### 9. Display Result
|
|
||||||
|
|
||||||
Show summary in Chinese:
|
|
||||||
```
|
```
|
||||||
✓ 提交成功
|
✓ 提交成功
|
||||||
|
|
||||||
提交信息:feat(android): 添加用户认证
|
提交信息:[commit message]
|
||||||
版本标签:android-1.3.0
|
版本标签:[tag] (如果创建了)
|
||||||
|
|
||||||
要推送到远程仓库,请运行:/git-push
|
要推送到远程仓库,请运行:/git-push
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Cases
|
**Important:** This command does NOT push to remote. Use `/git-push` to push commits and tags.
|
||||||
|
|
||||||
- Commit staged changes with proper versioning
|
|
||||||
- Create local version tag for release preparation
|
|
||||||
- Follow semantic versioning automatically
|
|
||||||
|
|
||||||
## Related Commands
|
|
||||||
|
|
||||||
- `/git-status` - Check file changes before commit
|
|
||||||
- `/git-push` - Push commits and tags to remote
|
|
||||||
- `/git-push-tags` - Push tags only
|
|
||||||
|
|
||||||
## Reference
|
|
||||||
|
|
||||||
Complete workflow documentation: `skill/git/SKILL.md`
|
|
||||||
|
|||||||
@@ -2,84 +2,22 @@
|
|||||||
description: Pull latest changes from remote repository
|
description: Pull latest changes from remote repository
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-pull
|
Pull the latest changes from the remote repository for the current branch.
|
||||||
|
|
||||||
Pull latest changes from remote repository for current branch.
|
Please perform the following tasks:
|
||||||
|
|
||||||
## What It Does
|
1. **Run `git pull`** to fetch and merge remote changes
|
||||||
|
2. **Handle merge conflicts if they occur:**
|
||||||
|
- Check conflict files with `git status`
|
||||||
|
- Guide me through conflict resolution
|
||||||
|
- Help stage resolved files with `git add <file>`
|
||||||
|
- Complete the merge with `git commit`
|
||||||
|
3. **Show the result** with branch status and changes summary
|
||||||
|
|
||||||
- Fetches latest changes from remote
|
If there are any errors or conflicts, explain them clearly in Chinese and provide step-by-step guidance for resolution.
|
||||||
- Merges remote changes into local branch
|
|
||||||
- Updates working directory
|
|
||||||
|
|
||||||
## Quick Start
|
Present the final result showing:
|
||||||
|
- Branch name
|
||||||
Use this command to synchronize your local branch with the latest remote changes.
|
- Number of commits pulled
|
||||||
|
- Files changed
|
||||||
## Steps
|
- Any conflicts that need attention
|
||||||
|
|
||||||
### 1. Execute Pull
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git pull
|
|
||||||
```
|
|
||||||
|
|
||||||
This command will:
|
|
||||||
- Fetch updates from remote repository
|
|
||||||
- Automatically merge changes into current branch
|
|
||||||
- Update your working directory
|
|
||||||
|
|
||||||
### 2. Handle Conflicts (if any)
|
|
||||||
|
|
||||||
If merge conflicts occur:
|
|
||||||
- Git will mark conflicting files
|
|
||||||
- Resolve conflicts manually
|
|
||||||
- Stage resolved files: `git add <file>`
|
|
||||||
- Complete merge: `git commit`
|
|
||||||
|
|
||||||
Or use: `/git-status` to check conflict status
|
|
||||||
|
|
||||||
### 3. Display Result
|
|
||||||
|
|
||||||
Show result message:
|
|
||||||
|
|
||||||
```
|
|
||||||
✓ 拉取成功
|
|
||||||
|
|
||||||
分支已更新至最新状态。
|
|
||||||
```
|
|
||||||
|
|
||||||
Or if conflicts:
|
|
||||||
|
|
||||||
```
|
|
||||||
⚠️ 发生合并冲突
|
|
||||||
|
|
||||||
请解决以下文件中的冲突:
|
|
||||||
- src/index.js
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
然后运行:
|
|
||||||
git add <file>
|
|
||||||
git commit
|
|
||||||
|
|
||||||
或使用 /git-status 查看详细状态
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use Cases
|
|
||||||
|
|
||||||
- Sync local branch with remote updates
|
|
||||||
- Get latest changes from team
|
|
||||||
- Before starting new feature work
|
|
||||||
- Before pushing your changes
|
|
||||||
|
|
||||||
## Related Commands
|
|
||||||
|
|
||||||
- `/git-status` - Check file changes and merge status
|
|
||||||
- `/git-push` - Push local changes to remote
|
|
||||||
- `/git-commit` - Commit local changes
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Pulls from tracking remote branch (usually origin/main)
|
|
||||||
- Uses default merge strategy (recursive merge)
|
|
||||||
- If conflicts occur, resolve them before committing
|
|
||||||
|
|||||||
@@ -2,90 +2,54 @@
|
|||||||
description: Push all local tags to remote repository
|
description: Push all local tags to remote repository
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-push-tags
|
|
||||||
|
|
||||||
Push all local tags to the remote repository.
|
Push all local tags to the remote repository.
|
||||||
|
|
||||||
## What It Does
|
Please perform the following:
|
||||||
|
|
||||||
1. Lists all local tags
|
|
||||||
2. Shows which tags are not yet on remote
|
|
||||||
3. Pushes all tags to remote (origin)
|
|
||||||
4. Confirms successful push
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1. List Local Tags
|
|
||||||
|
|
||||||
|
1. **List local tags:**
|
||||||
```bash
|
```bash
|
||||||
echo "=== Local Tags ==="
|
|
||||||
git tag --list | sort -V
|
git tag --list | sort -V
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Check Remote Tags
|
2. **Check remote tags:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "=== Remote Tags ==="
|
git ls-remote --tags origin
|
||||||
git ls-remote --tags origin | awk '{print $2}' | sed 's|refs/tags/||' | sort -V
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Identify Unpushed Tags
|
3. **Identify unpushed tags** - Compare local and remote to find tags that need to be pushed
|
||||||
|
|
||||||
Compare local and remote tags to identify which tags need to be pushed.
|
4. **Display summary in Chinese:**
|
||||||
|
|
||||||
### 4. Confirm Before Push
|
|
||||||
|
|
||||||
Display summary in Chinese:
|
|
||||||
```
|
```
|
||||||
本地标签总数:15 个
|
本地标签总数:N 个
|
||||||
远程标签总数:12 个
|
远程标签总数:M 个
|
||||||
待推送标签:3 个
|
待推送标签:K 个
|
||||||
- 1.3.0
|
- [list of unpushed tags]
|
||||||
- 1.3.1
|
|
||||||
- ios-2.0.0
|
|
||||||
|
|
||||||
确认推送所有标签到 origin?
|
确认推送所有标签到 origin?
|
||||||
```
|
```
|
||||||
|
|
||||||
If user confirms or no confirmation needed, proceed to push.
|
5. **Wait for user confirmation** (or proceed if no confirmation needed)
|
||||||
|
|
||||||
### 5. Push All Tags
|
|
||||||
|
|
||||||
|
6. **Push all tags:**
|
||||||
```bash
|
```bash
|
||||||
git push --tags
|
git push --tags
|
||||||
# or
|
|
||||||
git push origin --tags
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Verify Push
|
7. **Verify and display result in Chinese:**
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "=== Push Result ==="
|
|
||||||
git ls-remote --tags origin | tail -5
|
|
||||||
```
|
|
||||||
|
|
||||||
Display confirmation in Chinese:
|
|
||||||
```
|
```
|
||||||
✓ 已成功推送所有标签到 origin
|
✓ 已成功推送所有标签到 origin
|
||||||
|
|
||||||
最近 5 个远程标签:
|
最近 5 个远程标签:
|
||||||
- 1.3.0
|
- [list of recent tags]
|
||||||
- 1.3.1
|
|
||||||
- ios-2.0.0
|
|
||||||
- android-1.5.0
|
|
||||||
- electron-3.0.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Cases
|
**Use cases:**
|
||||||
|
|
||||||
- After creating multiple local tags
|
- After creating multiple local tags
|
||||||
- Sync tags with remote repository
|
- Sync tags with remote repository
|
||||||
- Before triggering CI/CD release workflows
|
- Before triggering CI/CD release workflows
|
||||||
- Share version tags with team
|
- Share version tags with team
|
||||||
|
|
||||||
## Notes
|
**Notes:**
|
||||||
|
- Pushes ALL local tags, not just one
|
||||||
- **Safe operation**: Pushing tags does not affect commits
|
- To push a specific tag: `git push origin <tag-name>`
|
||||||
- **No force push**: Uses standard push, won't overwrite existing tags
|
- Safe operation: won't overwrite existing tags (no force push)
|
||||||
- **All tags**: Pushes ALL local tags, not just one
|
|
||||||
- If you only want to push a specific tag, use: `git push origin <tag-name>`
|
|
||||||
|
|||||||
@@ -2,189 +2,54 @@
|
|||||||
description: Commit staged files, create version tag, and push to remote repository
|
description: Commit staged files, create version tag, and push to remote repository
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-push
|
Complete workflow: auto-generate commit message, create version tag, commit, and push everything to remote repository.
|
||||||
|
|
||||||
Complete workflow: auto-generate commit message, create version tag, and push everything to remote repository.
|
This is the **all-in-one command** that combines `/git-commit` + push operations.
|
||||||
|
|
||||||
## What It Does
|
Please perform the following:
|
||||||
|
|
||||||
This is the **all-in-one command** that:
|
1-7. **Follow the same steps as `/git-commit`:**
|
||||||
1. ✓ Analyzes and commits staged changes (like `/git-commit`)
|
|
||||||
2. ✓ Creates version tag if needed
|
|
||||||
3. ✓ Pushes commit to remote repository
|
|
||||||
4. ✓ Pushes tag to remote repository
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
Use this command when you want to commit AND push in one step.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
**Staging area must have files:**
|
|
||||||
```bash
|
|
||||||
git add <files>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
User can optionally input:
|
|
||||||
- **"skip tag"** or **"skip"**: Skip tag creation, only commit and push
|
|
||||||
|
|
||||||
## Workflow
|
|
||||||
|
|
||||||
This command combines `/git-commit` + push operations:
|
|
||||||
|
|
||||||
1. ✓ Check staging area
|
|
||||||
2. ✓ Analyze changes and repository type
|
|
||||||
3. ✓ Detect project type and version
|
|
||||||
4. ✓ Generate commit message
|
|
||||||
5. ✓ Update version number if needed
|
|
||||||
6. ✓ Commit with generated message
|
|
||||||
7. ✓ Create version tag
|
|
||||||
8. ✓ Push commit to remote
|
|
||||||
9. ✓ Push tag to remote
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1-8. Commit and Tag
|
|
||||||
|
|
||||||
Execute the same steps as `/git-commit`:
|
|
||||||
- Check staging area (must not be empty)
|
- Check staging area (must not be empty)
|
||||||
- Collect information (status, diff, logs, tags, AGENTS.md)
|
- Analyze changes and repository type
|
||||||
- Detect repository type (polyrepo/monorepo)
|
- Detect project type and version
|
||||||
- Detect project type and version file
|
- Generate commit message (Conventional Commits, Chinese)
|
||||||
- Generate commit message (Conventional Commits, Chinese/English)
|
|
||||||
- Update version number if needed
|
- Update version number if needed
|
||||||
- Commit changes
|
- Commit changes
|
||||||
- Create tag if needed
|
- Create version tag
|
||||||
|
|
||||||
Refer to `/git-commit` for detailed steps or see `skill/git/SKILL.md`.
|
Refer to `/git-commit` for detailed steps or `@skill/git/SKILL.md` for complete workflow.
|
||||||
|
|
||||||
### 9. Push Commit to Remote
|
|
||||||
|
|
||||||
|
8. **Push commit to remote:**
|
||||||
```bash
|
```bash
|
||||||
# Push current branch to origin
|
|
||||||
git push origin $(git branch --show-current)
|
git push origin $(git branch --show-current)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10. Push Tag to Remote
|
9. **Push tag to remote** (only if tag was created):
|
||||||
|
- Polyrepo: `git push origin <version>`
|
||||||
|
- Monorepo: `git push origin <subproject>-<version>`
|
||||||
|
|
||||||
**Only if tag was created:**
|
10. **Display result in Chinese:**
|
||||||
|
|
||||||
**Polyrepo:**
|
|
||||||
```bash
|
|
||||||
git push origin <version>
|
|
||||||
# Example: git push origin 1.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
**Monorepo:**
|
|
||||||
```bash
|
|
||||||
git push origin <subproject>-<version>
|
|
||||||
# Example: git push origin ios-1.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### 11. Display Result
|
|
||||||
|
|
||||||
Show summary in Chinese:
|
|
||||||
```
|
```
|
||||||
✓ 提交并推送成功
|
✓ 提交并推送成功
|
||||||
|
|
||||||
分支:main
|
分支:[branch]
|
||||||
提交信息:feat(android): 添加用户认证
|
提交信息:[commit message]
|
||||||
版本标签:android-1.3.0
|
版本标签:[tag] (如果创建了)
|
||||||
|
|
||||||
已推送到远程仓库:origin
|
已推送到远程仓库:origin
|
||||||
- 提交:a1b2c3d
|
- 提交:[commit hash]
|
||||||
- 标签:android-1.3.0
|
- 标签:[tag]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Comparison with Other Commands
|
**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
|
||||||
|
|
||||||
| Command | Commit | Tag | Push Commit | Push Tag |
|
**Options:**
|
||||||
|---------|--------|-----|-------------|----------|
|
- User can input "skip tag" or "skip" to skip tag creation
|
||||||
| `/git-commit` | ✓ | ✓ | ✗ | ✗ |
|
|
||||||
| `/git-push` | ✓ | ✓ | ✓ | ✓ |
|
|
||||||
| `/git-push-tags` | ✗ | ✗ | ✗ | ✓ (all tags) |
|
|
||||||
|
|
||||||
## Use Cases
|
**When to use:**
|
||||||
|
- `/git-commit`: Local only, review before pushing
|
||||||
- **Quick workflow**: Commit and push in one command
|
- `/git-push`: Commit and push immediately
|
||||||
- **Release preparation**: Create version tag and push for CI/CD
|
- `/git-push-tags`: Push tags only (no commits)
|
||||||
- **Daily development**: Commit and sync with remote immediately
|
|
||||||
|
|
||||||
## When to Use Which Command
|
|
||||||
|
|
||||||
**Use `/git-commit`** (local only):
|
|
||||||
- You want to review before pushing
|
|
||||||
- Working on feature branch not ready to share
|
|
||||||
- Creating multiple commits before one push
|
|
||||||
|
|
||||||
**Use `/git-push`** (commit + push):
|
|
||||||
- Ready to share changes immediately
|
|
||||||
- Main branch development with CI/CD
|
|
||||||
- Quick fixes that should be synced now
|
|
||||||
|
|
||||||
**Use `/git-push-tags`** (tags only):
|
|
||||||
- Already committed but forgot to push tags
|
|
||||||
- Want to push multiple accumulated tags at once
|
|
||||||
- Tag-only sync without new commits
|
|
||||||
|
|
||||||
## Error Handling
|
|
||||||
|
|
||||||
### If Staging Area is Empty
|
|
||||||
|
|
||||||
```
|
|
||||||
暂存区为空,请先使用 `git add` 添加文件。
|
|
||||||
```
|
|
||||||
**Action:** Terminate, user must stage files first.
|
|
||||||
|
|
||||||
### If Push Fails
|
|
||||||
|
|
||||||
Common reasons:
|
|
||||||
- Remote branch protection
|
|
||||||
- Need to pull first (diverged history)
|
|
||||||
- No permission to push
|
|
||||||
|
|
||||||
**Action:** Display error in Chinese, suggest solutions:
|
|
||||||
```
|
|
||||||
✗ 推送失败
|
|
||||||
|
|
||||||
原因:远程分支有更新,需要先拉取
|
|
||||||
|
|
||||||
建议操作:
|
|
||||||
1. git pull --rebase origin main
|
|
||||||
2. 解决冲突(如有)
|
|
||||||
3. 重新运行 /git-push
|
|
||||||
```
|
|
||||||
|
|
||||||
### If Remote Rejects Tag
|
|
||||||
|
|
||||||
If tag already exists on remote:
|
|
||||||
```
|
|
||||||
✗ 标签推送失败
|
|
||||||
|
|
||||||
原因:远程仓库已存在标签 1.2.0
|
|
||||||
|
|
||||||
建议操作:
|
|
||||||
1. 删除本地标签:git tag -d 1.2.0
|
|
||||||
2. 更新版本号后重新提交
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- **Main branch**: Default push target is `main` (not `master`)
|
|
||||||
- **Conventional Commits**: Auto-generated messages follow standard format
|
|
||||||
- **Semantic Versioning**: Automatic version bumping based on change type
|
|
||||||
- **Polyrepo/Monorepo**: Automatically detects and uses correct tag format
|
|
||||||
- **Platform-specific**: Commit messages in Chinese (macOS/Linux) or English (Windows)
|
|
||||||
|
|
||||||
## Related Commands
|
|
||||||
|
|
||||||
- `/git-status` - Check changes before committing
|
|
||||||
- `/git-commit` - Commit locally without pushing
|
|
||||||
- `/git-push-tags` - Push only tags (no commits)
|
|
||||||
|
|
||||||
## Reference
|
|
||||||
|
|
||||||
Complete git workflow guide: `skill/git/SKILL.md`
|
|
||||||
Quick command reference: `skill/git/quick-reference.md`
|
|
||||||
|
|||||||
@@ -2,53 +2,28 @@
|
|||||||
description: Check git working directory status and file changes
|
description: Check git working directory status and file changes
|
||||||
---
|
---
|
||||||
|
|
||||||
# git-status
|
Check the current git repository status and display file changes in a clear, organized format.
|
||||||
|
|
||||||
Check current git repository status and display file changes in a clear format.
|
Please perform the following tasks:
|
||||||
|
|
||||||
## What It Does
|
1. **Run `git status`** to show the current state of the working tree
|
||||||
|
2. **Display current branch** using `git branch --show-current`
|
||||||
|
3. **List unstaged changes** with `git diff --name-only`
|
||||||
|
4. **List staged changes** with `git diff --cached --name-only`
|
||||||
|
|
||||||
- Shows current branch
|
Present the information in Chinese with the following structure:
|
||||||
- Lists changed files (unstaged and staged)
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
Execute the following commands in parallel:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Current branch
|
|
||||||
git branch --show-current
|
|
||||||
|
|
||||||
# Repository status
|
|
||||||
git status
|
|
||||||
|
|
||||||
# List changed files only
|
|
||||||
echo "=== Unstaged Changes ==="
|
|
||||||
git diff --name-only
|
|
||||||
|
|
||||||
echo "=== Staged Changes ==="
|
|
||||||
git diff --cached --name-only
|
|
||||||
```
|
|
||||||
|
|
||||||
## Output Format
|
|
||||||
|
|
||||||
Present the information in Chinese with clear sections:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
当前分支:main
|
当前分支: [branch_name]
|
||||||
|
|
||||||
未暂存的文件 (3):
|
暂存区文件 ([count]):
|
||||||
- src/index.js
|
[列出已暂存的文件]
|
||||||
- src/utils.js
|
|
||||||
- README.md
|
|
||||||
|
|
||||||
已暂存的文件 (2):
|
未暂存的修改 ([count]):
|
||||||
- package.json
|
[列出未暂存的修改文件]
|
||||||
- src/config.js
|
|
||||||
|
未跟踪的文件 ([count]):
|
||||||
|
[列出未跟踪的文件]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Cases
|
Use clear formatting and emoji indicators (✓, ⚠️, etc.) to make the output easy to read.
|
||||||
|
|
||||||
- Quick status check before committing
|
|
||||||
- Review what files have changed
|
|
||||||
- Check if you're on the correct branch
|
|
||||||
|
|||||||
@@ -2,167 +2,71 @@
|
|||||||
description: View current Gitea configuration and runner status
|
description: View current Gitea configuration and runner status
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-config
|
Display the current Gitea configuration and runner status.
|
||||||
|
|
||||||
查看当前 Gitea 配置信息和 Runner 状态。
|
## 工作目录
|
||||||
|
|
||||||
## Features
|
**macOS / Linux:**
|
||||||
|
```
|
||||||
|
~/.config/gitea/
|
||||||
|
```
|
||||||
|
|
||||||
- 显示配置的 Gitea URL
|
**Windows:**
|
||||||
- 显示默认组织
|
```
|
||||||
- 验证 Token 状态和关联用户
|
%USERPROFILE%\.config\gitea\
|
||||||
- 显示已配置的 Runner 数量和列表
|
```
|
||||||
- 显示配置文件路径
|
|
||||||
|
|
||||||
## Steps
|
Please perform the following:
|
||||||
|
|
||||||
### 1. Check Configuration File
|
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
|
```bash
|
||||||
config_dir="$HOME/.config/gitea"
|
source ~/.config/gitea/config.env
|
||||||
config_file="$config_dir/config.env"
|
|
||||||
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
echo "❌ Gitea 未配置"
|
|
||||||
echo "请运行 /gitea-reset 进行配置"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Load and Display Configuration
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
```bash
|
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||||
source "$config_file"
|
if ($_ -match '^([^=]+)=(.*)$') {
|
||||||
|
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
}
|
||||||
echo "当前 Gitea 配置"
|
}
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " URL: $GITEA_URL"
|
|
||||||
echo " 默认组织: ${GITEA_DEFAULT_ORG:-<未设置>}"
|
|
||||||
echo " 配置文件: $config_file"
|
|
||||||
echo ""
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Validate Token and Display User Info
|
Show in Chinese:
|
||||||
|
- Gitea URL
|
||||||
|
- Default organization (if set)
|
||||||
|
- Config file path (根据平台显示正确路径)
|
||||||
|
|
||||||
```bash
|
3. **Validate token and display user info:**
|
||||||
response=$(curl -s -w "\n%{http_code}" \
|
- Call API: `GET ${GITEA_URL}/api/v1/user`
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
- Header: `Authorization: token ${GITEA_TOKEN}`
|
||||||
"${GITEA_URL}/api/v1/user")
|
- Show: Token status (✓ 有效 / ✗ 无效), username, email
|
||||||
|
|
||||||
http_code=$(echo "$response" | tail -n1)
|
4. **Display runner information:**
|
||||||
body=$(echo "$response" | sed '$d')
|
- 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)
|
||||||
|
|
||||||
if [ "$http_code" = "200" ]; then
|
5. **Show management commands:**
|
||||||
username=$(echo "$body" | jq -r '.login')
|
```
|
||||||
email=$(echo "$body" | jq -r '.email // "<未设置>"')
|
管理命令:
|
||||||
echo " Token 状态: ✓ 有效"
|
- 重置配置: /gitea-reset
|
||||||
echo " 登录用户: $username"
|
- 切换组织: /gitea-switch-org <org-name>
|
||||||
echo " 邮箱: $email"
|
- 列出 Runners: /gitea-list-runners
|
||||||
else
|
- 创建仓库: /create-gitea-repo <repo-name>
|
||||||
echo " Token 状态: ✗ 无效或已过期"
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Display Runner Information
|
Use `jq` to parse JSON responses and `pgrep` to check runner process status.
|
||||||
|
|
||||||
```bash
|
|
||||||
runners_dir="$config_dir/runners"
|
|
||||||
|
|
||||||
if [ -d "$runners_dir" ]; then
|
|
||||||
runner_count=$(ls -1 "$runners_dir" 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "Runner 信息"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 已配置 Runner 数量: $runner_count"
|
|
||||||
echo " Runner 目录: $runners_dir"
|
|
||||||
|
|
||||||
if [ "$runner_count" -gt 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo " 已配置的 Runners:"
|
|
||||||
ls -1 "$runners_dir" | while read runner; do
|
|
||||||
# Check if running
|
|
||||||
config_file="$runners_dir/$runner/config.yaml"
|
|
||||||
if [ -f "$config_file" ]; then
|
|
||||||
if pgrep -f "act_runner daemon --config $config_file" > /dev/null; then
|
|
||||||
status="🟢"
|
|
||||||
else
|
|
||||||
status="🔴"
|
|
||||||
fi
|
|
||||||
echo " $status $runner"
|
|
||||||
else
|
|
||||||
echo " ⚠️ $runner (配置文件缺失)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "Runner 信息"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 未配置任何 Runner"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Display Management Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "管理命令"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 重置配置: /gitea-reset"
|
|
||||||
echo " 切换组织: /gitea-switch-org <org-name>"
|
|
||||||
echo " 列出 Runners: /gitea-list-runners"
|
|
||||||
echo " 创建仓库: /create-gitea-repo <repo-name>"
|
|
||||||
echo ""
|
|
||||||
```
|
|
||||||
|
|
||||||
## Output Example
|
|
||||||
|
|
||||||
```
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
当前 Gitea 配置
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
URL: https://git.digitevents.com
|
|
||||||
默认组织: ai
|
|
||||||
配置文件: /Users/voson/.config/gitea/config.env
|
|
||||||
|
|
||||||
Token 状态: ✓ 有效
|
|
||||||
登录用户: your_username
|
|
||||||
邮箱: your_username@example.com
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
Runner 信息
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
已配置 Runner 数量: 2
|
|
||||||
Runner 目录: /Users/voson/.config/gitea/runners
|
|
||||||
|
|
||||||
已配置的 Runners:
|
|
||||||
🟢 runner-macbook-pro
|
|
||||||
🔴 runner-mac-mini
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
管理命令
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
重置配置: /gitea-reset
|
|
||||||
切换组织: /gitea-switch-org <org-name>
|
|
||||||
列出 Runners: /gitea-list-runners
|
|
||||||
创建仓库: /create-gitea-repo <repo-name>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- 使用 `jq` 解析 JSON 响应
|
|
||||||
- 检查 runner 进程使用 `pgrep`
|
|
||||||
- Token 验证通过调用 `/api/v1/user` endpoint
|
|
||||||
- Runner 状态:🟢 运行中、🔴 已停止、⚠️ 配置异常
|
|
||||||
|
|||||||
@@ -2,255 +2,103 @@
|
|||||||
description: Create a new Git repository on Gitea
|
description: Create a new Git repository on Gitea
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-create-repo
|
Create a new Git repository on Gitea via API.
|
||||||
|
|
||||||
Create a new Git repository on Gitea.
|
## 工作目录
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Create new repository under specified organization or user via Gitea API
|
|
||||||
- Support creating private or public repositories
|
|
||||||
- Automatically add remote repository address after successful creation
|
|
||||||
|
|
||||||
## User Input Format
|
|
||||||
|
|
||||||
User can specify parameters in the following format:
|
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```
|
```
|
||||||
[<owner>/]<repo> [private|public]
|
~/.config/gitea/
|
||||||
```
|
```
|
||||||
|
|
||||||
- `owner`: Organization name or username (optional, uses `GITEA_DEFAULT_ORG` if set, otherwise uses current user)
|
**Windows:**
|
||||||
- `repo`: Repository name (required)
|
```
|
||||||
- `private|public`: Visibility (optional, default `private`)
|
%USERPROFILE%\.config\gitea\
|
||||||
|
```
|
||||||
|
|
||||||
**Examples**:
|
配置文件从该目录加载。
|
||||||
- `my-project` - Create private repository under default organization (or current user if not set)
|
|
||||||
- `ai/my-project` - Create private repository my-project under ai organization
|
|
||||||
- `ai/my-project public` - Create public repository my-project under ai organization
|
|
||||||
- `username/test private` - Create private repository test under username user
|
|
||||||
|
|
||||||
## Configuration
|
**User input format:**
|
||||||
|
```
|
||||||
|
$ARGUMENTS = [<owner>/]<repo> [private|public]
|
||||||
|
```
|
||||||
|
|
||||||
Load configuration from `~/.config/gitea/config.env`:
|
**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
|
||||||
|
|
||||||
| Config Item | Source |
|
Please perform the following:
|
||||||
| --- | --- |
|
|
||||||
| Gitea Server URL | `GITEA_URL` from config.env |
|
|
||||||
| API Token | `GITEA_TOKEN` from config.env |
|
|
||||||
| Default Organization | `GITEA_DEFAULT_ORG` from config.env (optional) |
|
|
||||||
|
|
||||||
## Steps
|
1. **Load configuration:**
|
||||||
|
|
||||||
### 0. Load Configuration
|
|
||||||
|
|
||||||
Before executing, load Gitea configuration:
|
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```bash
|
```bash
|
||||||
config_file="$HOME/.config/gitea/config.env"
|
source ~/.config/gitea/config.env
|
||||||
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
echo "❌ Gitea 未配置,请运行 /gitea-reset 进行初始化"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
source "$config_file"
|
|
||||||
|
|
||||||
# Validate required variables
|
|
||||||
if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
|
|
||||||
echo "❌ 配置文件不完整,请运行 /gitea-reset 重新配置"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 1. Parse User Input
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
|
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||||
|
if ($_ -match '^([^=]+)=(.*)$') {
|
||||||
|
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Parse from user input:
|
- If not exists: prompt to run `/gitea-reset`
|
||||||
- `owner`: Organization name or username
|
|
||||||
- `repo`: Repository name
|
|
||||||
- `visibility`: `private` (default) or `public`
|
|
||||||
|
|
||||||
**Input parsing logic**:
|
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
|
```bash
|
||||||
input="$1"
|
POST ${GITEA_URL}/api/v1/orgs/${owner}/repos
|
||||||
visibility="${2:-private}"
|
Body: {
|
||||||
|
"name": "${repo}",
|
||||||
# Parse owner/repo
|
"private": true/false,
|
||||||
if [[ "$input" =~ / ]]; then
|
"auto_init": false,
|
||||||
owner=$(echo "$input" | cut -d'/' -f1)
|
"default_branch": "main"
|
||||||
repo=$(echo "$input" | cut -d'/' -f2)
|
}
|
||||||
else
|
|
||||||
# Use default organization if available, otherwise use current user
|
|
||||||
if [ -z "$GITEA_DEFAULT_ORG" ]; then
|
|
||||||
# Get current user from Gitea API
|
|
||||||
owner=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
|
||||||
"${GITEA_URL}/api/v1/user" | jq -r '.login')
|
|
||||||
|
|
||||||
if [ -z "$owner" ] || [ "$owner" = "null" ]; then
|
|
||||||
echo "❌ 无法获取当前用户信息,请使用 owner/repo 格式"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "使用当前用户: $owner"
|
|
||||||
else
|
|
||||||
owner="$GITEA_DEFAULT_ORG"
|
|
||||||
echo "使用默认组织: $owner"
|
|
||||||
fi
|
|
||||||
repo="$input"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Convert visibility to boolean
|
|
||||||
private_bool=$([ "$visibility" = "private" ] && echo "true" || echo "false")
|
|
||||||
```
|
```
|
||||||
|
- 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
|
||||||
|
|
||||||
**Input validation**:
|
4. **Extract repository info from response:**
|
||||||
- Repository name can only contain letters, numbers, underscores, hyphens and dots
|
- `html_url` - Web URL
|
||||||
|
- `clone_url` - HTTPS URL
|
||||||
|
- `ssh_url` - SSH URL
|
||||||
|
|
||||||
```bash
|
5. **Ask user if they want to add remote:**
|
||||||
if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
|
- Check if current directory is a git repo
|
||||||
echo "❌ 仓库名只能包含字母、数字、下划线、连字符和点"
|
- If not, ask to initialize: `git init`
|
||||||
exit 1
|
- Check if `origin` remote exists
|
||||||
fi
|
- Add or update remote: `git remote add/set-url origin <clone_url>`
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Call Gitea API to Create Repository
|
6. **Display result in Chinese:**
|
||||||
|
|
||||||
Use curl to call Gitea API with configuration:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "正在创建仓库: $owner/$repo ($visibility)"
|
|
||||||
|
|
||||||
# Try organization repository first
|
|
||||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"name\": \"${repo}\",
|
|
||||||
\"private\": ${private_bool},
|
|
||||||
\"auto_init\": false,
|
|
||||||
\"default_branch\": \"main\"
|
|
||||||
}" \
|
|
||||||
"${GITEA_URL}/api/v1/orgs/${owner}/repos")
|
|
||||||
|
|
||||||
http_code=$(echo "$response" | tail -n1)
|
|
||||||
body=$(echo "$response" | sed '$d')
|
|
||||||
|
|
||||||
# If 404, try user repository
|
|
||||||
if [ "$http_code" = "404" ]; then
|
|
||||||
echo "⚠️ 组织不存在,尝试创建用户仓库..."
|
|
||||||
|
|
||||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"name\": \"${repo}\",
|
|
||||||
\"private\": ${private_bool},
|
|
||||||
\"auto_init\": false,
|
|
||||||
\"default_branch\": \"main\"
|
|
||||||
}" \
|
|
||||||
"${GITEA_URL}/api/v1/user/repos")
|
|
||||||
|
|
||||||
http_code=$(echo "$response" | tail -n1)
|
|
||||||
body=$(echo "$response" | sed '$d')
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: First try organization API, if 404 then try user API.
|
|
||||||
|
|
||||||
### 3. Handle Response
|
|
||||||
|
|
||||||
```bash
|
|
||||||
case "$http_code" in
|
|
||||||
201)
|
|
||||||
echo "✓ 仓库创建成功"
|
|
||||||
;;
|
|
||||||
409)
|
|
||||||
echo "❌ 仓库已存在: $owner/$repo"
|
|
||||||
echo "查看仓库: ${GITEA_URL}/$owner/$repo"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
404)
|
|
||||||
echo "❌ Owner 不存在或无权限: $owner"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "❌ 创建失败 (HTTP $http_code)"
|
|
||||||
echo "$body" | jq -r '.message // empty'
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Extract repository info
|
|
||||||
html_url=$(echo "$body" | jq -r '.html_url')
|
|
||||||
clone_url=$(echo "$body" | jq -r '.clone_url')
|
|
||||||
ssh_url=$(echo "$body" | jq -r '.ssh_url')
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response Handling**:
|
|
||||||
- **HTTP 201**: Repository created successfully
|
|
||||||
- **HTTP 409**: Repository already exists
|
|
||||||
- **HTTP 404**: Owner does not exist or no permission
|
|
||||||
- **Other**: API error, display error message
|
|
||||||
|
|
||||||
### 4. Ask Whether to Add Remote Repository
|
|
||||||
|
|
||||||
Ask user whether to add the newly created repository as current project's remote repository.
|
|
||||||
|
|
||||||
**If user confirms**:
|
|
||||||
|
|
||||||
1. Check if current directory is a Git repository:
|
|
||||||
```bash
|
|
||||||
git rev-parse --is-inside-work-tree
|
|
||||||
```
|
|
||||||
|
|
||||||
2. If not a Git repository, ask whether to initialize:
|
|
||||||
```bash
|
|
||||||
git init
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Check if origin remote already exists:
|
|
||||||
```bash
|
|
||||||
git remote get-url origin
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Add or update remote repository:
|
|
||||||
- If no origin: `git remote add origin <clone_url>`
|
|
||||||
- If origin exists: Ask whether to overwrite, after confirmation execute `git remote set-url origin <clone_url>`
|
|
||||||
|
|
||||||
### 5. Output Result Summary
|
|
||||||
|
|
||||||
Output creation result summary:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "仓库创建成功"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 名称: $owner/$repo"
|
|
||||||
echo " 可见性: $visibility"
|
|
||||||
echo " Web URL: $html_url"
|
|
||||||
echo " HTTPS URL: $clone_url"
|
|
||||||
echo " SSH URL: $ssh_url"
|
|
||||||
echo ""
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example Output**:
|
|
||||||
```
|
```
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
仓库创建成功
|
仓库创建成功
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
名称: ai/my-project
|
名称: [owner]/[repo]
|
||||||
可见性: private
|
可见性: [private/public]
|
||||||
Web URL: https://git.digitevents.com/ai/my-project
|
Web URL: [html_url]
|
||||||
HTTPS URL: https://git.digitevents.com/ai/my-project.git
|
HTTPS URL: [clone_url]
|
||||||
SSH URL: git@git.digitevents.com:ai/my-project.git
|
SSH URL: [ssh_url]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
**Notes:**
|
||||||
|
- Requires repo creation permission in token
|
||||||
- **Permission check**: Ensure Token has permission to create repository
|
- Organization and user repositories use different API endpoints
|
||||||
- **Organization vs User**: Creating organization repository and user repository use different API endpoints
|
- Default branch is `main` (not `master`)
|
||||||
- **Repository naming**: Follow Gitea naming rules, avoid special characters
|
|
||||||
|
|||||||
@@ -1,52 +1,160 @@
|
|||||||
---
|
---
|
||||||
description: Create and start a Gitea Actions runner (default host mode)
|
description: Create and start a Gitea Actions runner (default host mode)
|
||||||
|
agent: general
|
||||||
|
subtask: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-create-runner
|
# 创建并启动 Gitea Actions Runner
|
||||||
|
|
||||||
创建并启动 Gitea Actions Runner(默认 host 模式)。
|
你的任务是创建并启动一个 Gitea Actions Runner(默认使用 host 模式)。
|
||||||
|
|
||||||
## 命令说明
|
## 工作目录
|
||||||
|
|
||||||
此命令用于快速创建和启动一个 Gitea Actions Runner。默认使用 host 模式,自动检测系统环境并配置。
|
**macOS / Linux:**
|
||||||
|
```
|
||||||
**重要**:这是一个可执行命令,AI 应该按照以下步骤执行操作。
|
~/.config/gitea/
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- 自动检查并安装 act_runner(如果未安装)
|
|
||||||
- 自动加载 Gitea 配置(如果不存在则提示初始化)
|
|
||||||
- 默认使用 host 模式(支持 Android SDK、iOS 构建等原生工具)
|
|
||||||
- 智能检测系统环境(OS、架构)并生成合适的 labels
|
|
||||||
- 自动注册并后台启动 runner
|
|
||||||
- 优先尝试创建全局 runner(需要管理员权限)
|
|
||||||
- 权限不足时自动降级到组织 runner
|
|
||||||
|
|
||||||
## User Input Format
|
|
||||||
|
|
||||||
无需参数,运行后自动创建。可选提供 runner 名称。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/gitea-create-runner
|
|
||||||
# 或
|
|
||||||
/gitea-create-runner my-runner-name
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## AI 执行指导
|
**Windows:**
|
||||||
|
```
|
||||||
|
%USERPROFILE%\.config\gitea\
|
||||||
|
```
|
||||||
|
|
||||||
当用户调用此命令时,AI 应该:
|
所有 Runner 配置、缓存、工作区都存储在该目录的 `runners/` 子目录下。
|
||||||
|
|
||||||
1. **检查 act_runner 安装**:如果未安装,自动安装
|
## 核心功能要求
|
||||||
2. **加载 Gitea 配置**:如果不存在,提示用户先初始化
|
|
||||||
3. **生成 runner 名称**:基于主机名或用户输入
|
|
||||||
4. **检测系统环境**:自动生成 labels
|
|
||||||
5. **创建 runner 目录**:在 `~/.config/gitea/runners/` 下创建
|
|
||||||
6. **生成配置文件**:默认 host 模式配置
|
|
||||||
7. **获取注册 token**:优先全局,失败则降级到组织
|
|
||||||
8. **注册 runner**:使用 act_runner register
|
|
||||||
9. **启动 runner**:后台启动并显示状态
|
|
||||||
|
|
||||||
## Implementation Steps
|
请按照以下步骤执行:
|
||||||
|
|
||||||
|
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
|
### 1. Check act_runner Installation
|
||||||
|
|
||||||
|
|||||||
@@ -1,422 +1,63 @@
|
|||||||
---
|
---
|
||||||
description: Delete a Gitea runner configuration (interactive)
|
description: Delete a Gitea runner configuration (interactive)
|
||||||
|
agent: general
|
||||||
|
subtask: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-delete-runner
|
Delete Gitea runner configuration with interactive selection. This command requires multiple user interactions.
|
||||||
|
|
||||||
删除 Gitea Runner 配置(交互式选择)。
|
**Important:** This is an interactive command. Wait for user input at each step before proceeding.
|
||||||
|
|
||||||
## 命令说明
|
## 工作目录
|
||||||
|
|
||||||
此命令用于从 Gitea 服务器删除 runner 配置。支持交互式选择单个或所有 runners。
|
**macOS / Linux:**
|
||||||
|
```
|
||||||
|
~/.config/gitea/
|
||||||
|
```
|
||||||
|
|
||||||
**重要**:这是一个可执行命令,AI 应该按照以下步骤执行操作,并与用户进行交互。
|
**Windows:**
|
||||||
|
```
|
||||||
|
%USERPROFILE%\.config\gitea\
|
||||||
|
```
|
||||||
|
|
||||||
## Features
|
所有 Runner 配置、进程管理都基于此目录。
|
||||||
|
|
||||||
- 显示 Gitea 服务器上的全局 runners
|
Please perform the following steps:
|
||||||
- 交互式选择要删除的 runner
|
|
||||||
- 支持删除单个或所有 runners
|
|
||||||
- 删除 runner 配置目录(包括 cache 和 workspace)
|
|
||||||
- 停止运行中的 runner 进程
|
|
||||||
- 自动从 Gitea 服务器注销 runner
|
|
||||||
- 安全确认机制(需要用户输入 'yes')
|
|
||||||
|
|
||||||
## User Input Format
|
## Step 1: Load Configuration and Fetch Runners
|
||||||
|
|
||||||
无需参数,运行后交互式选择。
|
1. **Load Gitea configuration:**
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```bash
|
```bash
|
||||||
/gitea-delete-runner
|
source ~/.config/gitea/config.env
|
||||||
```
|
```
|
||||||
|
|
||||||
## AI 执行指导
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
当用户调用此命令时,AI 应该:
|
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||||
|
if ($_ -match '^([^=]+)=(.*)$') {
|
||||||
1. **获取并展示 runner 列表**:调用 Gitea API 获取服务器上的全局 runners,并以清晰的格式展示给用户
|
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||||
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
|
- Validate `GITEA_URL` and `GITEA_TOKEN` exist
|
||||||
|
|
||||||
**AI 执行**:运行以下命令获取并显示 runners 列表,然后等待用户选择。
|
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
|
||||||
|
|
||||||
```bash
|
3. **Display runners list in Chinese:**
|
||||||
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 个)
|
Gitea 全局 Runners (共 N 个)
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
1. runner-mac-mini4 [ID: 42 ] 🟢 在线
|
1. [runner-name] [ID: XX] 🟢 在线/🔴 离线
|
||||||
系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30
|
2. [runner-name] [ID: XX] 🟢 在线/🔴 离线
|
||||||
|
...
|
||||||
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
|
||||||
@@ -425,11 +66,21 @@ Gitea 全局 Runners (共 3 个)
|
|||||||
输入序号: 删除单个 runner
|
输入序号: 删除单个 runner
|
||||||
输入 'all': 删除所有 runners
|
输入 'all': 删除所有 runners
|
||||||
输入 'q' 或 'quit': 取消
|
输入 'q' 或 'quit': 取消
|
||||||
|
```
|
||||||
|
|
||||||
请选择: 2
|
4. **Wait for user selection** → Do NOT proceed until user responds
|
||||||
|
|
||||||
已选择: runner-macbook-pro (ID: 43)
|
## 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
|
- 从 Gitea 服务器注销 runner
|
||||||
- 停止本地运行的 runner 进程
|
- 停止本地运行的 runner 进程
|
||||||
@@ -437,159 +88,87 @@ Gitea 全局 Runners (共 3 个)
|
|||||||
- 删除 cache 和 workspace 目录
|
- 删除 cache 和 workspace 目录
|
||||||
- 删除所有相关数据
|
- 删除所有相关数据
|
||||||
|
|
||||||
确认删除? 输入 'yes' 继续: yes
|
将删除以下 runners:
|
||||||
|
- [list of runners to be deleted]
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
确认删除? 输入 'yes' 继续:
|
||||||
删除: runner-macbook-pro (ID: 43)
|
```
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
[1/3] 从 Gitea 服务器注销...
|
**Wait for user confirmation** → Do NOT proceed until user types 'yes'
|
||||||
✓ 已从服务器注销
|
|
||||||
[2/3] 检查本地进程...
|
|
||||||
✓ 未运行
|
|
||||||
[3/3] 删除本地配置...
|
|
||||||
✓ 本地配置已删除
|
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
```
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
删除完成
|
删除完成
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
成功: 1 个
|
成功: N 个
|
||||||
|
失败: M 个 (if any)
|
||||||
|
|
||||||
管理命令:
|
管理命令:
|
||||||
查看剩余 runners: /gitea-list-runners
|
查看剩余 runners: /gitea-list-runners
|
||||||
创建新 runner: /gitea-create-runner
|
创建新 runner: /gitea-create-runner
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example 2: Delete All Runners
|
---
|
||||||
|
|
||||||
```
|
## Key Points
|
||||||
正在从 Gitea 服务器获取全局 runners...
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
**Interactive checkpoints (wait for user input):**
|
||||||
Gitea 全局 Runners (共 2 个)
|
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)
|
||||||
|
|
||||||
1. runner-mac-mini4 [ID: 42 ] 🟢 在线
|
**Safety features:**
|
||||||
系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30
|
- Double confirmation required
|
||||||
|
- Busy status detection
|
||||||
|
- Graceful stop before force kill
|
||||||
|
- Three-step deletion process
|
||||||
|
- Clear status reporting
|
||||||
|
|
||||||
2. runner-linux-server [ID: 44 ] 🟢 在线
|
**Technical notes:**
|
||||||
系统: linux 架构: amd64 最后在线: 2026-01-12 10:25
|
- Requires `jq` for JSON parsing
|
||||||
|
- Requires admin token for global runners
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
- Uses temporary file `/tmp/gitea_runners.txt` for data passing
|
||||||
选择要删除的 Runner
|
- Cleanup temp file after completion
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
输入序号: 删除单个 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,选择等待或强制停止
|
|
||||||
|
|
||||||
不要一次性执行所有步骤。
|
|
||||||
|
|||||||
@@ -1,184 +1,79 @@
|
|||||||
---
|
---
|
||||||
description: List all configured Gitea runners and their status
|
description: List all global runners on Gitea server
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-list-runners
|
List all global runners registered on the Gitea server.
|
||||||
|
|
||||||
列出所有已配置的 Gitea Runners 及其运行状态。
|
## 工作目录
|
||||||
|
|
||||||
## Features
|
**macOS / Linux:**
|
||||||
|
```
|
||||||
- 显示所有已配置的 runner
|
~/.config/gitea/
|
||||||
- 检查 runner 运行状态(运行中/已停止)
|
|
||||||
- 显示 runner 配置信息(labels、capacity 等)
|
|
||||||
- 显示 runner ID 和名称
|
|
||||||
- 提供启动命令
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1. Check Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
config_dir="$HOME/.config/gitea"
|
|
||||||
runners_dir="$config_dir/runners"
|
|
||||||
|
|
||||||
if [ ! -d "$runners_dir" ]; then
|
|
||||||
echo "❌ 未找到 runner 目录"
|
|
||||||
echo "请先创建 runner"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. List All Runners
|
**Windows:**
|
||||||
|
```
|
||||||
```bash
|
%USERPROFILE%\.config\gitea\
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "Gitea Runners"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
runners=$(ls -1 "$runners_dir" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$runners" ]; then
|
|
||||||
echo "未配置任何 runner"
|
|
||||||
echo ""
|
|
||||||
echo "创建 runner:"
|
|
||||||
echo " /gitea-create-runner"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
runner_count=$(echo "$runners" | wc -l | tr -d ' ')
|
|
||||||
echo "总计: $runner_count 个 runner"
|
|
||||||
echo ""
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Display Each Runner's Status
|
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
|
```bash
|
||||||
for runner in $runners; do
|
curl -s -H "Authorization: token <token>" \
|
||||||
runner_dir="$runners_dir/$runner"
|
"<server>/api/v1/admin/actions/runners"
|
||||||
config_file="$runner_dir/config.yaml"
|
|
||||||
|
|
||||||
echo "[$runner]"
|
|
||||||
|
|
||||||
# Check if config exists
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
echo " ⚠️ 配置文件缺失"
|
|
||||||
echo ""
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if runner process is running
|
|
||||||
if pgrep -f "act_runner daemon --config $config_file" > /dev/null; then
|
|
||||||
status="🟢 运行中"
|
|
||||||
pid=$(pgrep -f "act_runner daemon --config $config_file")
|
|
||||||
else
|
|
||||||
status="🔴 已停止"
|
|
||||||
pid="-"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " 状态: $status"
|
|
||||||
echo " PID: $pid"
|
|
||||||
|
|
||||||
# Display configuration info
|
|
||||||
if command -v yq &> /dev/null; then
|
|
||||||
# Use yq if available
|
|
||||||
capacity=$(yq eval '.runner.capacity' "$config_file" 2>/dev/null)
|
|
||||||
timeout=$(yq eval '.runner.timeout' "$config_file" 2>/dev/null)
|
|
||||||
else
|
|
||||||
# Fallback to grep
|
|
||||||
capacity=$(grep "capacity:" "$config_file" | awk '{print $2}')
|
|
||||||
timeout=$(grep "timeout:" "$config_file" | awk '{print $2}')
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " 容量: ${capacity:-N/A}"
|
|
||||||
echo " 超时: ${timeout:-N/A}"
|
|
||||||
|
|
||||||
# Display labels
|
|
||||||
labels=$(grep -A 10 "labels:" "$config_file" | grep "^ -" | sed 's/^ - "//' | sed 's/"$//' | tr '\n' ',' | sed 's/,$//')
|
|
||||||
if [ -n "$labels" ]; then
|
|
||||||
echo " Labels: $labels"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Display runner info from .runner file
|
|
||||||
if [ -f "$runner_dir/.runner" ]; then
|
|
||||||
if command -v jq &> /dev/null; then
|
|
||||||
runner_id=$(jq -r '.id // "N/A"' "$runner_dir/.runner" 2>/dev/null)
|
|
||||||
runner_name=$(jq -r '.name // "N/A"' "$runner_dir/.runner" 2>/dev/null)
|
|
||||||
|
|
||||||
echo " ID: $runner_id"
|
|
||||||
echo " 名称: $runner_name"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " 路径: $runner_dir"
|
|
||||||
|
|
||||||
# Display start command
|
|
||||||
echo ""
|
|
||||||
echo " 启动命令:"
|
|
||||||
echo " act_runner daemon --config $config_file"
|
|
||||||
|
|
||||||
# Display background start command
|
|
||||||
if [ "$status" = "🔴 已停止" ]; then
|
|
||||||
echo ""
|
|
||||||
echo " 后台启动:"
|
|
||||||
echo " nohup act_runner daemon --config $config_file > $runner_dir/runner.log 2>&1 &"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Display Summary Commands
|
3. **Parse JSON response and extract information:**
|
||||||
|
- Response structure:
|
||||||
```bash
|
```json
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
{
|
||||||
echo "管理命令"
|
"runners": [...],
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
"total_count": 1
|
||||||
echo ""
|
}
|
||||||
echo " 查看配置: /gitea-config"
|
|
||||||
echo " 创建 runner: /gitea-create-runner"
|
|
||||||
echo " 删除 runner: /gitea-delete-runner"
|
|
||||||
echo ""
|
|
||||||
```
|
```
|
||||||
|
- 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`
|
||||||
|
|
||||||
## Output Example
|
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
|
Gitea 全局 Runners
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
总计: 2 个 runner
|
服务器: [server_url]
|
||||||
|
总计: N 个全局 runner
|
||||||
|
|
||||||
[runner-macbook-pro]
|
[runner-name]
|
||||||
状态: 🟢 运行中
|
状态: 🟢/🔴 [在线/离线]
|
||||||
PID: 12345
|
ID: [id]
|
||||||
容量: 2
|
忙碌: 是/否
|
||||||
超时: 3h
|
临时: 是/否
|
||||||
Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
|
标签: [comma-separated labels]
|
||||||
ID: 42
|
|
||||||
名称: runner-macbook-pro
|
|
||||||
路径: /Users/voson/.config/gitea/runners/runner-macbook-pro
|
|
||||||
|
|
||||||
启动命令:
|
|
||||||
act_runner daemon --config /Users/voson/.config/gitea/runners/runner-macbook-pro/config.yaml
|
|
||||||
|
|
||||||
[runner-mac-mini]
|
|
||||||
状态: 🔴 已停止
|
|
||||||
PID: -
|
|
||||||
容量: 2
|
|
||||||
超时: 3h
|
|
||||||
Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
|
|
||||||
ID: 43
|
|
||||||
名称: runner-mac-mini
|
|
||||||
路径: /Users/voson/.config/gitea/runners/runner-mac-mini
|
|
||||||
|
|
||||||
启动命令:
|
|
||||||
act_runner daemon --config /Users/voson/.config/gitea/runners/runner-mac-mini/config.yaml
|
|
||||||
|
|
||||||
后台启动:
|
|
||||||
nohup act_runner daemon --config /Users/voson/.config/gitea/runners/runner-mac-mini/config.yaml > /Users/voson/.config/gitea/runners/runner-mac-mini/runner.log 2>&1 &
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
管理命令
|
管理命令
|
||||||
@@ -189,14 +84,11 @@ Gitea Runners
|
|||||||
删除 runner: /gitea-delete-runner
|
删除 runner: /gitea-delete-runner
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
**Notes:**
|
||||||
|
- Requires admin API token to list runners
|
||||||
- 使用 `pgrep` 检查进程状态
|
- **Correct API endpoint**: `/api/v1/admin/actions/runners` (not `/api/v1/admin/runners`)
|
||||||
- 优先使用 `yq` 解析 YAML,fallback 到 `grep`
|
- Only shows global runners (instance-level runners)
|
||||||
- 优先使用 `jq` 解析 JSON `.runner` 文件
|
- Uses `jq` for JSON parsing
|
||||||
- Runner 状态图标:
|
- 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
|
||||||
- ⚠️ 配置异常
|
|
||||||
- 显示启动命令方便用户复制执行
|
|
||||||
- 对已停止的 runner,额外显示后台启动命令
|
|
||||||
|
|||||||
@@ -1,70 +1,47 @@
|
|||||||
---
|
---
|
||||||
description: Reset Gitea configuration with interactive setup wizard
|
description: Reset Gitea configuration with interactive setup wizard
|
||||||
|
agent: general
|
||||||
|
subtask: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-reset
|
Launch an interactive configuration wizard to set up or reset Gitea configuration.
|
||||||
|
|
||||||
重置 Gitea 配置,启动交互式配置向导。
|
## 工作目录
|
||||||
|
|
||||||
## Features
|
**macOS / Linux:**
|
||||||
|
```
|
||||||
- 交互式引导配置
|
~/.config/gitea/
|
||||||
- 验证 URL 和 Token
|
|
||||||
- 检查 Token 权限
|
|
||||||
- 自动保存配置到 `~/.config/gitea/config.env`
|
|
||||||
- 创建必要的目录结构
|
|
||||||
|
|
||||||
## Steps
|
|
||||||
|
|
||||||
### 1. Create Configuration Directory
|
|
||||||
|
|
||||||
```bash
|
|
||||||
config_dir="$HOME/.config/gitea"
|
|
||||||
config_file="$config_dir/config.env"
|
|
||||||
|
|
||||||
# Create directories
|
|
||||||
mkdir -p "$config_dir/runners"
|
|
||||||
|
|
||||||
echo "开始 Gitea 配置向导..."
|
|
||||||
echo ""
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Input Gitea URL
|
**Windows:**
|
||||||
|
```
|
||||||
```bash
|
%USERPROFILE%\.config\gitea\
|
||||||
read -p "请输入 Gitea 实例地址 (例如: https://git.digitevents.com): " gitea_url
|
|
||||||
|
|
||||||
# Validate URL format
|
|
||||||
if ! [[ "$gitea_url" =~ ^https?:// ]]; then
|
|
||||||
echo "❌ URL 必须以 http:// 或 https:// 开头"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove trailing slash
|
|
||||||
gitea_url="${gitea_url%/}"
|
|
||||||
|
|
||||||
echo "✓ URL: $gitea_url"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Input Personal Access Token
|
配置文件和 Runner 目录都将存储在此位置。
|
||||||
|
|
||||||
|
Please perform the following:
|
||||||
|
|
||||||
|
1. **Create configuration directory:**
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```bash
|
```bash
|
||||||
echo ""
|
mkdir -p ~/.config/gitea/runners
|
||||||
read -sp "请输入 Personal Access Token: " gitea_token
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ -z "$gitea_token" ]; then
|
|
||||||
echo "❌ Token 不能为空"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✓ Token 已输入"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Token 获取提示**:
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
|
New-Item -Path "$env:USERPROFILE\.config\gitea\runners" -ItemType Directory -Force
|
||||||
|
```
|
||||||
|
|
||||||
在用户输入 Token 前,可以显示帮助信息:
|
2. **Interactive input - Gitea URL:**
|
||||||
|
- Prompt: "请输入 Gitea 实例地址 (例如: https://git.digitevents.com):"
|
||||||
|
- Validate: Must start with http:// or https://
|
||||||
|
- Remove trailing slash
|
||||||
|
|
||||||
|
3. **Interactive input - Personal Access Token:**
|
||||||
|
- Prompt: "请输入 Personal Access Token:"
|
||||||
|
- Before input, show help:
|
||||||
```
|
```
|
||||||
提示:获取 Personal Access Token 的步骤:
|
提示:获取 Personal Access Token 的步骤:
|
||||||
1. 登录 Gitea
|
1. 登录 Gitea
|
||||||
@@ -75,221 +52,58 @@ echo "✓ Token 已输入"
|
|||||||
6. 点击 "生成令牌"
|
6. 点击 "生成令牌"
|
||||||
7. 复制生成的 Token
|
7. 复制生成的 Token
|
||||||
```
|
```
|
||||||
|
- Validate: Not empty
|
||||||
|
- Use `read -sp` for secure input (password style)
|
||||||
|
|
||||||
### 4. Test Connection
|
4. **Test connection:**
|
||||||
|
- API: `GET ${GITEA_URL}/api/v1/user`
|
||||||
|
- If fails: Show error and possible reasons
|
||||||
|
- If success: Show username
|
||||||
|
|
||||||
|
5. **Validate token permissions:**
|
||||||
|
- Check `repo`: `GET /api/v1/user/repos` (required)
|
||||||
|
- Check `admin:org`: `GET /api/v1/user/orgs` (optional, for org runners)
|
||||||
|
- Check `write:runner`: Try to get registration token (optional, for runners)
|
||||||
|
- Warn if missing required permissions
|
||||||
|
|
||||||
|
6. **Input default organization (optional):**
|
||||||
|
- Prompt: "请输入默认组织名称 (回车跳过):"
|
||||||
|
- If provided, validate it exists: `GET /api/v1/orgs/${org_name}`
|
||||||
|
|
||||||
|
7. **Save configuration:**
|
||||||
|
|
||||||
|
**macOS / Linux** - Save to `~/.config/gitea/config.env`:
|
||||||
```bash
|
```bash
|
||||||
echo ""
|
GITEA_URL=...
|
||||||
echo "正在测试连接..."
|
GITEA_TOKEN=...
|
||||||
|
GITEA_DEFAULT_ORG=... (if set)
|
||||||
response=$(curl -s -w "\n%{http_code}" \
|
|
||||||
-H "Authorization: token $gitea_token" \
|
|
||||||
"${gitea_url}/api/v1/user")
|
|
||||||
|
|
||||||
http_code=$(echo "$response" | tail -n1)
|
|
||||||
body=$(echo "$response" | sed '$d')
|
|
||||||
|
|
||||||
if [ "$http_code" != "200" ]; then
|
|
||||||
echo "❌ 连接失败 (HTTP $http_code)"
|
|
||||||
echo "请检查:"
|
|
||||||
echo " - URL 是否正确"
|
|
||||||
echo " - Token 是否有效"
|
|
||||||
echo " - 网络连接是否正常"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
username=$(echo "$body" | jq -r '.login')
|
|
||||||
echo "✓ 连接成功!"
|
|
||||||
echo "✓ 登录用户: $username"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Validate Token Permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "正在检查 Token 权限..."
|
|
||||||
|
|
||||||
# Check repo permission
|
|
||||||
if curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
-H "Authorization: token $gitea_token" \
|
|
||||||
"${gitea_url}/api/v1/user/repos" | grep -q "200"; then
|
|
||||||
echo " ✓ repo (仓库管理)"
|
|
||||||
has_repo=true
|
|
||||||
else
|
|
||||||
echo " ✗ repo (仓库管理) - 缺少"
|
|
||||||
has_repo=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check org permission
|
|
||||||
if curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
-H "Authorization: token $gitea_token" \
|
|
||||||
"${gitea_url}/api/v1/user/orgs" | grep -q "200"; then
|
|
||||||
echo " ✓ admin:org (组织管理)"
|
|
||||||
has_org=true
|
|
||||||
else
|
|
||||||
echo " ⚠ admin:org (组织管理) - 缺少(创建组织 Runner 时需要)"
|
|
||||||
has_org=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check runner permission (try to get a registration token)
|
|
||||||
if curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
-H "Authorization: token $gitea_token" \
|
|
||||||
"${gitea_url}/api/v1/user/actions/runners/registration-token" 2>/dev/null | grep -q "200"; then
|
|
||||||
echo " ✓ write:runner (Runner 管理)"
|
|
||||||
has_runner=true
|
|
||||||
else
|
|
||||||
echo " ⚠ write:runner (Runner 管理) - 缺少(创建 Runner 时需要)"
|
|
||||||
has_runner=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Warning if missing critical permissions
|
|
||||||
if [ "$has_repo" = false ]; then
|
|
||||||
echo ""
|
|
||||||
echo "❌ 缺少必需的 repo 权限"
|
|
||||||
read -p "是否继续? [y/N] " continue_anyway
|
|
||||||
if [[ ! "$continue_anyway" =~ ^[Yy]$ ]]; then
|
|
||||||
echo "已取消,请重新创建具有足够权限的 Token"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Input Default Organization (Optional)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "设置默认组织(可选):"
|
|
||||||
echo " - 创建仓库时,如果不指定 owner,将使用默认组织"
|
|
||||||
echo " - 创建组织级 Runner 时使用"
|
|
||||||
echo ""
|
|
||||||
read -p "请输入默认组织名称 (回车跳过): " default_org
|
|
||||||
|
|
||||||
if [ -n "$default_org" ]; then
|
|
||||||
# Validate organization exists
|
|
||||||
echo "正在验证组织..."
|
|
||||||
org_response=$(curl -s -w "\n%{http_code}" \
|
|
||||||
-H "Authorization: token $gitea_token" \
|
|
||||||
"${gitea_url}/api/v1/orgs/${default_org}")
|
|
||||||
|
|
||||||
org_http_code=$(echo "$org_response" | tail -n1)
|
|
||||||
|
|
||||||
if [ "$org_http_code" = "200" ]; then
|
|
||||||
echo "✓ 组织验证成功: $default_org"
|
|
||||||
else
|
|
||||||
echo "⚠️ 组织 '$default_org' 不存在或无权限访问"
|
|
||||||
read -p "仍然设置为默认组织? [Y/n] " set_anyway
|
|
||||||
if [[ "$set_anyway" =~ ^[Nn]$ ]]; then
|
|
||||||
default_org=""
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Save Configuration
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "正在保存配置..."
|
|
||||||
|
|
||||||
cat > "$config_file" << EOF
|
|
||||||
# Gitea Configuration
|
|
||||||
# Generated at $(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
GITEA_URL=$gitea_url
|
|
||||||
GITEA_TOKEN=$gitea_token
|
|
||||||
${default_org:+GITEA_DEFAULT_ORG=$default_org}
|
|
||||||
|
|
||||||
# Runner Default Settings
|
|
||||||
GITEA_RUNNER_CAPACITY=2
|
GITEA_RUNNER_CAPACITY=2
|
||||||
GITEA_RUNNER_TIMEOUT=3h
|
GITEA_RUNNER_TIMEOUT=3h
|
||||||
|
|
||||||
# Optional: Override auto-detected labels
|
|
||||||
# GITEA_RUNNER_LABELS=custom-label-1:host,custom-label-2:host
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Set restrictive permissions
|
|
||||||
chmod 600 "$config_file"
|
|
||||||
|
|
||||||
# Create .gitignore
|
|
||||||
cat > "$config_dir/.gitignore" << EOF
|
|
||||||
config.env
|
|
||||||
runners/*/.runner
|
|
||||||
runners/*/.env
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "✓ 配置已保存"
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "配置完成"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 配置文件: $config_file"
|
|
||||||
echo " Runner 目录: $config_dir/runners"
|
|
||||||
echo ""
|
|
||||||
echo "下一步:"
|
|
||||||
echo " - 查看配置: /gitea-config"
|
|
||||||
echo " - 创建 Runner: 告诉 AI '创建一个 runner'"
|
|
||||||
echo " - 创建仓库: /create-gitea-repo <repo-name>"
|
|
||||||
echo ""
|
|
||||||
```
|
```
|
||||||
|
- Set permissions: `chmod 600 ~/.config/gitea/config.env`
|
||||||
|
- Create `.gitignore` to exclude sensitive files
|
||||||
|
|
||||||
## Configuration File Format
|
**Windows** - Save to `%USERPROFILE%\.config\gitea\config.env`:
|
||||||
|
|
||||||
生成的 `~/.config/gitea/config.env` 文件格式:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Gitea Configuration
|
GITEA_URL=...
|
||||||
# Generated at 2026-01-12 22:00:00
|
GITEA_TOKEN=...
|
||||||
|
GITEA_DEFAULT_ORG=... (if set)
|
||||||
GITEA_URL=https://git.digitevents.com
|
|
||||||
GITEA_TOKEN=git_xxxxxxxxxxxxxxxxxxxx
|
|
||||||
GITEA_DEFAULT_ORG=ai
|
|
||||||
|
|
||||||
# Runner Default Settings
|
|
||||||
GITEA_RUNNER_CAPACITY=2
|
GITEA_RUNNER_CAPACITY=2
|
||||||
GITEA_RUNNER_TIMEOUT=3h
|
GITEA_RUNNER_TIMEOUT=3h
|
||||||
|
|
||||||
# Optional: Override auto-detected labels
|
|
||||||
# GITEA_RUNNER_LABELS=custom-label-1:host,custom-label-2:host
|
|
||||||
```
|
```
|
||||||
|
- Set file permissions to restrict access (see setup-guide.md for PowerShell script)
|
||||||
|
- Create `.gitignore` to exclude sensitive files
|
||||||
|
|
||||||
## Output Example
|
8. **Display completion summary in Chinese:**
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```
|
```
|
||||||
开始 Gitea 配置向导...
|
|
||||||
|
|
||||||
请输入 Gitea 实例地址 (例如: https://git.digitevents.com): https://git.digitevents.com
|
|
||||||
✓ URL: https://git.digitevents.com
|
|
||||||
|
|
||||||
请输入 Personal Access Token: ****************
|
|
||||||
✓ Token 已输入
|
|
||||||
|
|
||||||
正在测试连接...
|
|
||||||
✓ 连接成功!
|
|
||||||
✓ 登录用户: your_username
|
|
||||||
|
|
||||||
正在检查 Token 权限...
|
|
||||||
✓ repo (仓库管理)
|
|
||||||
✓ admin:org (组织管理)
|
|
||||||
✓ write:runner (Runner 管理)
|
|
||||||
|
|
||||||
设置默认组织(可选):
|
|
||||||
- 创建仓库时,如果不指定 owner,将使用默认组织
|
|
||||||
- 创建组织级 Runner 时使用
|
|
||||||
|
|
||||||
请输入默认组织名称 (回车跳过): ai
|
|
||||||
正在验证组织...
|
|
||||||
✓ 组织验证成功: ai
|
|
||||||
|
|
||||||
正在保存配置...
|
|
||||||
✓ 配置已保存
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
配置完成
|
配置完成
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
配置文件: /Users/voson/.config/gitea/config.env
|
配置文件: ~/.config/gitea/config.env
|
||||||
Runner 目录: /Users/voson/.config/gitea/runners
|
Runner 目录: ~/.config/gitea/runners
|
||||||
|
|
||||||
下一步:
|
下一步:
|
||||||
- 查看配置: /gitea-config
|
- 查看配置: /gitea-config
|
||||||
@@ -297,18 +111,22 @@ GITEA_RUNNER_TIMEOUT=3h
|
|||||||
- 创建仓库: /create-gitea-repo <repo-name>
|
- 创建仓库: /create-gitea-repo <repo-name>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security Notes
|
**Windows:**
|
||||||
|
```
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
配置完成
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
- 配置文件权限设置为 `600`(仅所有者可读写)
|
配置文件: %USERPROFILE%\.config\gitea\config.env
|
||||||
- Token 不会在日志中显示
|
Runner 目录: %USERPROFILE%\.config\gitea\runners
|
||||||
- 创建 `.gitignore` 文件排除敏感信息
|
|
||||||
- 建议定期轮换 Token(每 3-6 个月)
|
|
||||||
|
|
||||||
## Notes
|
下一步:
|
||||||
|
- 查看配置: /gitea-config
|
||||||
|
- 创建 Runner: 告诉 AI '创建一个 runner'
|
||||||
|
- 创建仓库: /create-gitea-repo <repo-name>
|
||||||
|
```
|
||||||
|
|
||||||
- **必需权限**: `repo` - 创建和管理仓库
|
**Security notes:**
|
||||||
- **推荐权限**: `admin:org` - 创建组织级 Runner
|
- Config file permissions: 600 (owner read/write only)
|
||||||
- **推荐权限**: `write:runner` - 管理 Runner
|
- Token is never displayed after initial input
|
||||||
- **可选权限**: `admin:repo_hook` - 配置 Webhooks
|
- Sensitive files excluded in .gitignore
|
||||||
- Token 只显示一次,请妥善保管
|
|
||||||
- 重置配置不会影响已创建的 Runner,但 Runner 会继续使用旧的注册信息
|
|
||||||
|
|||||||
@@ -2,154 +2,81 @@
|
|||||||
description: Switch default Gitea organization
|
description: Switch default Gitea organization
|
||||||
---
|
---
|
||||||
|
|
||||||
# gitea-switch-org
|
Switch the default Gitea organization in configuration.
|
||||||
|
|
||||||
切换默认 Gitea 组织。
|
## 工作目录
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- 更新配置文件中的默认组织
|
|
||||||
- 验证组织是否存在
|
|
||||||
- 立即生效,无需重启
|
|
||||||
|
|
||||||
## User Input Format
|
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```
|
```
|
||||||
<organization_name>
|
~/.config/gitea/
|
||||||
```
|
```
|
||||||
|
|
||||||
**Examples**:
|
**Windows:**
|
||||||
- `ai` - Switch to 'ai' organization
|
```
|
||||||
- `my-team` - Switch to 'my-team' organization
|
%USERPROFILE%\.config\gitea\
|
||||||
|
```
|
||||||
|
|
||||||
## Steps
|
**User input format:** `$ARGUMENTS` = organization name
|
||||||
|
|
||||||
### 1. Check Configuration
|
**Example usage:**
|
||||||
|
```
|
||||||
|
/gitea-switch-org ai
|
||||||
|
/gitea-switch-org my-team
|
||||||
|
```
|
||||||
|
|
||||||
|
Please perform the following:
|
||||||
|
|
||||||
|
1. **Check 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 configuration:**
|
||||||
|
|
||||||
|
**macOS / Linux:**
|
||||||
```bash
|
```bash
|
||||||
config_file="$HOME/.config/gitea/config.env"
|
source ~/.config/gitea/config.env
|
||||||
|
|
||||||
if [ ! -f "$config_file" ]; then
|
|
||||||
echo "❌ Gitea 未配置"
|
|
||||||
echo "请先运行 /gitea-reset 进行配置"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
source "$config_file"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Parse User Input
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
```bash
|
Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object {
|
||||||
new_org="$1"
|
if ($_ -match '^([^=]+)=(.*)$') {
|
||||||
|
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
||||||
if [ -z "$new_org" ]; then
|
}
|
||||||
echo "用法: /gitea-switch-org <organization_name>"
|
}
|
||||||
echo ""
|
|
||||||
echo "示例:"
|
|
||||||
echo " /gitea-switch-org ai"
|
|
||||||
echo " /gitea-switch-org my-team"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Validate Organization Exists
|
3. **Parse user input:**
|
||||||
|
- Organization name from `$ARGUMENTS`
|
||||||
|
- If empty: show usage and examples
|
||||||
|
|
||||||
|
4. **Validate organization exists:**
|
||||||
|
- API: `GET ${GITEA_URL}/api/v1/orgs/${org_name}`
|
||||||
|
- Header: `Authorization: token ${GITEA_TOKEN}`
|
||||||
|
- If 404: Show error and list available organizations:
|
||||||
```bash
|
```bash
|
||||||
echo "正在验证组织 '$new_org'..."
|
|
||||||
|
|
||||||
response=$(curl -s -w "\n%{http_code}" \
|
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
|
||||||
"${GITEA_URL}/api/v1/orgs/${new_org}")
|
|
||||||
|
|
||||||
http_code=$(echo "$response" | tail -n1)
|
|
||||||
body=$(echo "$response" | sed '$d')
|
|
||||||
|
|
||||||
if [ "$http_code" != "200" ]; then
|
|
||||||
echo "❌ 组织 '$new_org' 不存在或无权限访问"
|
|
||||||
|
|
||||||
# Suggest available organizations
|
|
||||||
echo ""
|
|
||||||
echo "你可以访问的组织:"
|
|
||||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
"${GITEA_URL}/api/v1/user/orgs" | jq -r '.[].username' | sed 's/^/ - /'
|
"${GITEA_URL}/api/v1/user/orgs" | jq -r '.[].username'
|
||||||
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
org_name=$(echo "$body" | jq -r '.full_name // .username')
|
|
||||||
echo "✓ 组织验证成功: $org_name"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Update Configuration File
|
5. **Update configuration file:**
|
||||||
|
- If `GITEA_DEFAULT_ORG` exists: update the line
|
||||||
|
- If not exists: add after `GITEA_TOKEN`
|
||||||
|
- Handle macOS (sed -i '') and Linux (sed -i) differences
|
||||||
|
|
||||||
```bash
|
6. **Display result in Chinese:**
|
||||||
echo "正在更新配置..."
|
|
||||||
|
|
||||||
# Check if GITEA_DEFAULT_ORG already exists in config
|
|
||||||
if grep -q "^GITEA_DEFAULT_ORG=" "$config_file"; then
|
|
||||||
# Update existing line (macOS compatible)
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
sed -i '' "s/^GITEA_DEFAULT_ORG=.*/GITEA_DEFAULT_ORG=$new_org/" "$config_file"
|
|
||||||
else
|
|
||||||
sed -i "s/^GITEA_DEFAULT_ORG=.*/GITEA_DEFAULT_ORG=$new_org/" "$config_file"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Add new line after GITEA_TOKEN
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
sed -i '' "/^GITEA_TOKEN=/a\\
|
|
||||||
GITEA_DEFAULT_ORG=$new_org
|
|
||||||
" "$config_file"
|
|
||||||
else
|
|
||||||
sed -i "/^GITEA_TOKEN=/a GITEA_DEFAULT_ORG=$new_org" "$config_file"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✓ 默认组织已切换到: $new_org"
|
|
||||||
```
|
```
|
||||||
|
✓ 默认组织已切换到: [org_name]
|
||||||
### 5. Display Summary
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "切换完成"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo " 新的默认组织: $new_org"
|
|
||||||
echo ""
|
|
||||||
echo "现在可以:"
|
|
||||||
echo " - 创建仓库: /create-gitea-repo my-project"
|
|
||||||
echo " (将创建到 $new_org/my-project)"
|
|
||||||
echo " - 查看配置: /gitea-config"
|
|
||||||
echo ""
|
|
||||||
```
|
|
||||||
|
|
||||||
## Output Example
|
|
||||||
|
|
||||||
```
|
|
||||||
正在验证组织 'ai'...
|
|
||||||
✓ 组织验证成功: AI Team
|
|
||||||
|
|
||||||
正在更新配置...
|
|
||||||
✓ 默认组织已切换到: ai
|
|
||||||
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
切换完成
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
新的默认组织: ai
|
|
||||||
|
|
||||||
现在可以:
|
现在可以:
|
||||||
- 创建仓库: /create-gitea-repo my-project
|
- 创建仓库: /create-gitea-repo my-project
|
||||||
(将创建到 ai/my-project)
|
(将创建到 [org_name]/my-project)
|
||||||
- 查看配置: /gitea-config
|
- 查看配置: /gitea-config
|
||||||
```
|
```
|
||||||
|
|
||||||
## Notes
|
**Notes:**
|
||||||
|
- Switching organization doesn't affect existing repositories or runners
|
||||||
- 切换组织不会影响已创建的仓库和 Runner
|
- Only affects default owner for future repository creation
|
||||||
- 仅影响后续创建仓库时的默认 owner
|
- Can switch anytime
|
||||||
- 可以随时切换到其他组织
|
|
||||||
- 使用 `jq` 解析 JSON 响应
|
|
||||||
- macOS 和 Linux 的 `sed` 命令略有不同,需兼容处理
|
|
||||||
|
|||||||
@@ -3,14 +3,18 @@ description: Review code or documentation and provide suggestions
|
|||||||
agent: plan
|
agent: plan
|
||||||
---
|
---
|
||||||
|
|
||||||
# review
|
Review the code or documentation and provide detailed feedback.
|
||||||
|
|
||||||
## Actions to Execute
|
Please perform the following:
|
||||||
|
|
||||||
1. Review the code or documentation mentioned by user
|
1. **Review** the code or documentation mentioned by the user
|
||||||
2. Provide suggestions and content that needs modification
|
2. **Identify issues** and areas for improvement
|
||||||
3. Ask user if modifications are needed, if there's content that doesn't need modification; if user doesn't specify, modify all
|
3. **Provide suggestions** with clear explanations
|
||||||
|
4. **Ask for confirmation** before making modifications
|
||||||
|
|
||||||
## Notes
|
If the user hasn't specified what to review, ask them to provide the code or documentation they want reviewed.
|
||||||
|
|
||||||
- If user doesn't mention documentation or code, prompt user to provide documentation or code.
|
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
|
||||||
|
|||||||
@@ -23,18 +23,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"ref": {
|
|
||||||
"type": "remote",
|
|
||||||
"url": "https://api.ref.tools/mcp?apiKey={env:REF_API_KEY}",
|
|
||||||
"headers": {}
|
|
||||||
},
|
|
||||||
"figma": {
|
|
||||||
"type": "local",
|
|
||||||
"command": ["npx", "-y", "figma-developer-mcp", "--stdio"],
|
|
||||||
"environment": {
|
|
||||||
"FIGMA_API_KEY": "{env:FIGMA_API_KEY}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"permission": "allow"
|
"permission": "allow"
|
||||||
}
|
}
|
||||||
|
|||||||
72
plugin/notification.ts
Normal file
72
plugin/notification.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import type { Plugin } from "@opencode-ai/plugin"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知 Plugin
|
||||||
|
* 在会话完成或发生错误时发送系统通知
|
||||||
|
*/
|
||||||
|
export const NotificationPlugin: Plugin = async ({ project, client, $ }) => {
|
||||||
|
// 检测操作系统
|
||||||
|
const platform = process.platform
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送系统通知
|
||||||
|
* @param title 通知标题
|
||||||
|
* @param message 通知内容
|
||||||
|
* @param isError 是否为错误通知
|
||||||
|
*/
|
||||||
|
const sendNotification = async (title: string, message: string, isError: boolean = false) => {
|
||||||
|
try {
|
||||||
|
if (platform === "darwin") {
|
||||||
|
// macOS - 使用 osascript
|
||||||
|
const sound = isError ? ' sound name "Basso"' : ''
|
||||||
|
await $`osascript -e 'display notification "${message}" with title "${title}"${sound}'`
|
||||||
|
} else if (platform === "linux") {
|
||||||
|
// Linux - 使用 notify-send
|
||||||
|
const urgency = isError ? "-u critical" : ""
|
||||||
|
await $`notify-send "${title}" "${message}" ${urgency}`
|
||||||
|
} else if (platform === "win32") {
|
||||||
|
// Windows - 使用 PowerShell
|
||||||
|
const script = `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${message}', '${title}')`
|
||||||
|
await $`powershell -Command "& {${script}}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录日志
|
||||||
|
await client.app.log({
|
||||||
|
service: "notification",
|
||||||
|
level: "info",
|
||||||
|
message: `已发送通知: ${title} - ${message}`,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
// 如果通知发送失败,记录错误但不中断流程
|
||||||
|
await client.app.log({
|
||||||
|
service: "notification",
|
||||||
|
level: "error",
|
||||||
|
message: `发送通知失败: ${error}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
event: async ({ event }) => {
|
||||||
|
const projectName = project?.name || "OpenCode"
|
||||||
|
|
||||||
|
// 会话完成时发送通知
|
||||||
|
if (event.type === "session.idle") {
|
||||||
|
await sendNotification(
|
||||||
|
projectName,
|
||||||
|
"会话已完成!",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会话错误时发送通知
|
||||||
|
if (event.type === "session.error") {
|
||||||
|
await sendNotification(
|
||||||
|
projectName,
|
||||||
|
"会话发生错误!",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,51 @@ description: Comprehensive Gitea management tool for creating runners, workflows
|
|||||||
|
|
||||||
完整的 Gitea 管理工具,提供 Runner、Workflow、仓库的创建和管理功能。
|
完整的 Gitea 管理工具,提供 Runner、Workflow、仓库的创建和管理功能。
|
||||||
|
|
||||||
|
## 工作目录
|
||||||
|
|
||||||
|
**重要:该技能和所有相关命令的工作目录统一为:**
|
||||||
|
|
||||||
|
### macOS / Linux
|
||||||
|
```bash
|
||||||
|
~/.config/gitea/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
```powershell
|
||||||
|
# PowerShell
|
||||||
|
$env:USERPROFILE\.config\gitea\
|
||||||
|
|
||||||
|
# CMD
|
||||||
|
%USERPROFILE%\.config\gitea\
|
||||||
|
|
||||||
|
# 完整路径示例
|
||||||
|
C:\Users\YourUsername\.config\gitea\
|
||||||
|
```
|
||||||
|
|
||||||
|
所有配置文件、Runner 目录、日志文件都存储在此目录下。请确保该目录具有适当的读写权限。
|
||||||
|
|
||||||
|
**目录结构(所有平台通用):**
|
||||||
|
```
|
||||||
|
.config/gitea/
|
||||||
|
├── config.env # 主配置文件(Gitea URL、Token、默认组织等)
|
||||||
|
├── runners/ # Runner 配置目录
|
||||||
|
│ └── runner-*/ # 各个 runner 的独立目录
|
||||||
|
└── .gitignore # Git 忽略文件(保护敏感信息)
|
||||||
|
```
|
||||||
|
|
||||||
|
**平台兼容性:**
|
||||||
|
- **macOS**: `~/.config/gitea/`(完全支持)
|
||||||
|
- **Linux**: `~/.config/gitea/`(完全支持)
|
||||||
|
- **Windows**: `%USERPROFILE%\.config\gitea\`(Act Runner 支持,但该技能的命令和脚本需要适配)
|
||||||
|
|
||||||
|
**Windows 用户注意事项:**
|
||||||
|
- Gitea Act Runner 官方支持 Windows 平台(包括 Host 模式)
|
||||||
|
- 该技能文档中的命令和脚本主要基于 Bash,Windows 用户需要:
|
||||||
|
- 使用 PowerShell 或 Git Bash 执行命令
|
||||||
|
- 调整路径格式(如将 `~/.config/gitea` 改为 `%USERPROFILE%\.config\gitea`)
|
||||||
|
- 在 workflow 中指定 `shell: powershell`
|
||||||
|
- Windows 安装 act_runner:从 [官方 Releases](https://gitea.com/gitea/act_runner/releases) 下载 Windows 二进制文件
|
||||||
|
|
||||||
## 功能概览
|
## 功能概览
|
||||||
|
|
||||||
| 功能模块 | 文档 | 说明 |
|
| 功能模块 | 文档 | 说明 |
|
||||||
|
|||||||
@@ -20,17 +20,35 @@ Gitea Act Runner 是 Gitea Actions 的 CI/CD 执行器,兼容 GitHub Actions w
|
|||||||
|
|
||||||
### 执行模式
|
### 执行模式
|
||||||
|
|
||||||
| 模式 | 环境 | 适用场景 | Android SDK |
|
| 模式 | 环境 | 适用场景 | 平台支持 |
|
||||||
|------|------|---------|-------------|
|
|------|------|---------|---------|
|
||||||
| **Host Mode** | Native macOS/Linux | Android/iOS 构建、原生工具链 | macOS ARM64 支持 |
|
| **Host Mode** | Native OS(macOS/Linux/Windows) | Android/iOS 构建、原生工具链 | 全平台支持 |
|
||||||
| Docker Mode | Linux 容器 | 跨平台构建 | Linux ARM64 不支持 |
|
| Docker Mode | Linux 容器 | 跨平台构建 | Linux/macOS(不支持 ARM64 Android) |
|
||||||
|
|
||||||
**推荐**:macOS ARM64 使用 **Host Mode** 以支持 Android SDK。
|
**推荐**:
|
||||||
|
- **macOS ARM64**: 使用 **Host Mode** 以支持 Android SDK
|
||||||
|
- **Windows**: 使用 **Host Mode**(需在 workflow 中指定 `shell: powershell`)
|
||||||
|
- **Linux**: 两种模式均可,Docker Mode 隔离性更好
|
||||||
|
|
||||||
|
**Windows Host Mode 注意事项**:
|
||||||
|
- Bash 默认不可用,需在 workflow 中指定 shell:
|
||||||
|
```yaml
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: powershell
|
||||||
|
```
|
||||||
|
- 或者安装 Git Bash 并指定:
|
||||||
|
```yaml
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
```
|
||||||
|
|
||||||
## Runner 目录结构
|
## Runner 目录结构
|
||||||
|
|
||||||
所有 Runner 配置统一管理在:
|
所有 Runner 配置统一管理在:
|
||||||
|
|
||||||
|
### macOS / Linux
|
||||||
```
|
```
|
||||||
~/.config/gitea/runners/
|
~/.config/gitea/runners/
|
||||||
├── runner-macbook-pro/ # Runner 1
|
├── runner-macbook-pro/ # Runner 1
|
||||||
@@ -42,23 +60,123 @@ Gitea Act Runner 是 Gitea Actions 的 CI/CD 执行器,兼容 GitHub Actions w
|
|||||||
└── ...
|
└── ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
```
|
||||||
|
%USERPROFILE%\.config\gitea\runners\
|
||||||
|
├── runner-desktop-pc\ # Runner 1
|
||||||
|
│ ├── .runner # 注册信息(JSON)
|
||||||
|
│ ├── config.yaml # Runner 配置
|
||||||
|
│ ├── cache\ # Cache 目录
|
||||||
|
│ └── workspace\ # 工作目录
|
||||||
|
└── runner-laptop\ # Runner 2
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows 用户提示**:
|
||||||
|
- 完整路径示例:`C:\Users\YourUsername\.config\gitea\runners\`
|
||||||
|
- 配置文件使用反斜杠路径:`workdir_parent: "C:\\Users\\YourUsername\\.config\\gitea\\runners\\runner-name\\workspace"`
|
||||||
|
- 或在 YAML 中使用正斜杠(Windows 兼容):`workdir_parent: "C:/Users/YourUsername/.config/gitea/runners/runner-name/workspace"`
|
||||||
|
|
||||||
## 前置要求
|
## 前置要求
|
||||||
|
|
||||||
### 1. 安装 act_runner
|
### 1. 安装 act_runner
|
||||||
|
|
||||||
|
**macOS**:
|
||||||
```bash
|
```bash
|
||||||
# 使用 Homebrew(推荐)
|
# 使用 Homebrew(推荐)
|
||||||
brew install act_runner
|
brew install act_runner
|
||||||
|
|
||||||
# 或手动下载
|
# 或手动下载(ARM64)
|
||||||
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-arm64 \
|
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-arm64 \
|
||||||
-o /usr/local/bin/act_runner
|
-o /usr/local/bin/act_runner
|
||||||
chmod +x /usr/local/bin/act_runner
|
chmod +x /usr/local/bin/act_runner
|
||||||
|
|
||||||
|
# 或手动下载(x64)
|
||||||
|
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-amd64 \
|
||||||
|
-o /usr/local/bin/act_runner
|
||||||
|
chmod +x /usr/local/bin/act_runner
|
||||||
|
|
||||||
# 验证安装
|
# 验证安装
|
||||||
act_runner --version
|
act_runner --version
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Linux**:
|
||||||
|
```bash
|
||||||
|
# 手动下载(x64)
|
||||||
|
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-linux-amd64 \
|
||||||
|
-o /usr/local/bin/act_runner
|
||||||
|
chmod +x /usr/local/bin/act_runner
|
||||||
|
|
||||||
|
# 或(ARM64)
|
||||||
|
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-linux-arm64 \
|
||||||
|
-o /usr/local/bin/act_runner
|
||||||
|
chmod +x /usr/local/bin/act_runner
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
act_runner --version
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows**:
|
||||||
|
|
||||||
|
**方法 1: 使用 Scoop(推荐)**
|
||||||
|
```powershell
|
||||||
|
# 安装 Scoop(如果尚未安装)
|
||||||
|
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
|
||||||
|
|
||||||
|
# 添加 extras bucket
|
||||||
|
scoop bucket add extras
|
||||||
|
|
||||||
|
# 安装 act_runner(如果 Scoop 仓库中有)
|
||||||
|
# 注意:截至目前可能需要手动下载
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
act_runner --version
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 2: 手动下载(推荐)**
|
||||||
|
```powershell
|
||||||
|
# 下载最新版本(x64)
|
||||||
|
$version = "v0.2.13"
|
||||||
|
$arch = "amd64"
|
||||||
|
$url = "https://gitea.com/gitea/act_runner/releases/download/$version/act_runner-$version-windows-$arch.exe"
|
||||||
|
|
||||||
|
# 创建安装目录
|
||||||
|
New-Item -Path "$env:USERPROFILE\bin" -ItemType Directory -Force
|
||||||
|
|
||||||
|
# 下载
|
||||||
|
Invoke-WebRequest -Uri $url -OutFile "$env:USERPROFILE\bin\act_runner.exe"
|
||||||
|
|
||||||
|
# 添加到 PATH(永久)
|
||||||
|
[Environment]::SetEnvironmentVariable(
|
||||||
|
"Path",
|
||||||
|
[Environment]::GetEnvironmentVariable("Path", "User") + ";$env:USERPROFILE\bin",
|
||||||
|
"User"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 刷新当前会话的 PATH
|
||||||
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
act_runner --version
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 3: 使用 Chocolatey**
|
||||||
|
```powershell
|
||||||
|
# 安装 Chocolatey(如果尚未安装)
|
||||||
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||||
|
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
||||||
|
|
||||||
|
# 注意:act_runner 可能尚未在 Chocolatey 仓库中,需要手动下载
|
||||||
|
```
|
||||||
|
|
||||||
|
**通用验证**:
|
||||||
|
```bash
|
||||||
|
# 所有平台
|
||||||
|
act_runner --version
|
||||||
|
```
|
||||||
|
|
||||||
### 2. 安装开发工具(可选,根据需要)
|
### 2. 安装开发工具(可选,根据需要)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Gitea skill 需要配置连接信息才能与你的 Gitea 实例交互。配置
|
|||||||
|
|
||||||
## 配置目录结构
|
## 配置目录结构
|
||||||
|
|
||||||
|
### macOS / Linux
|
||||||
```
|
```
|
||||||
~/.config/gitea/
|
~/.config/gitea/
|
||||||
├── config.env # 主配置文件(包含 URL、Token、默认组织等)
|
├── config.env # 主配置文件(包含 URL、Token、默认组织等)
|
||||||
@@ -20,6 +21,20 @@ Gitea skill 需要配置连接信息才能与你的 Gitea 实例交互。配置
|
|||||||
└── .gitignore # Git 忽略文件(保护敏感信息)
|
└── .gitignore # Git 忽略文件(保护敏感信息)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
```
|
||||||
|
%USERPROFILE%\.config\gitea\
|
||||||
|
├── config.env # 主配置文件(包含 URL、Token、默认组织等)
|
||||||
|
├── runners\ # Runner 配置目录
|
||||||
|
│ └── runner-*\ # 各个 runner 的独立目录
|
||||||
|
└── .gitignore # Git 忽略文件(保护敏感信息)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows 用户提示**:
|
||||||
|
- 配置文件路径示例:`C:\Users\YourUsername\.config\gitea\config.env`
|
||||||
|
- 可以在 PowerShell 中使用 `$env:USERPROFILE` 变量
|
||||||
|
- 在 CMD 中使用 `%USERPROFILE%` 环境变量
|
||||||
|
|
||||||
## 快速配置
|
## 快速配置
|
||||||
|
|
||||||
### 方法 1: 使用交互式向导(推荐)
|
### 方法 1: 使用交互式向导(推荐)
|
||||||
@@ -48,6 +63,7 @@ AI 会自动启动配置向导。
|
|||||||
|
|
||||||
如果你熟悉配置格式,可以手动创建:
|
如果你熟悉配置格式,可以手动创建:
|
||||||
|
|
||||||
|
**macOS / Linux**:
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.config/gitea/runners
|
mkdir -p ~/.config/gitea/runners
|
||||||
cat > ~/.config/gitea/config.env << 'EOF'
|
cat > ~/.config/gitea/config.env << 'EOF'
|
||||||
@@ -62,6 +78,45 @@ EOF
|
|||||||
chmod 600 ~/.config/gitea/config.env
|
chmod 600 ~/.config/gitea/config.env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Windows PowerShell**:
|
||||||
|
```powershell
|
||||||
|
# 创建目录
|
||||||
|
New-Item -Path "$env:USERPROFILE\.config\gitea\runners" -ItemType Directory -Force
|
||||||
|
|
||||||
|
# 创建配置文件
|
||||||
|
@"
|
||||||
|
GITEA_URL=https://git.digitevents.com
|
||||||
|
GITEA_TOKEN=your_personal_access_token
|
||||||
|
GITEA_DEFAULT_ORG=your_org_name
|
||||||
|
|
||||||
|
GITEA_RUNNER_CAPACITY=2
|
||||||
|
GITEA_RUNNER_TIMEOUT=3h
|
||||||
|
"@ | Out-File -FilePath "$env:USERPROFILE\.config\gitea\config.env" -Encoding utf8
|
||||||
|
|
||||||
|
# 设置文件权限(仅所有者可读)
|
||||||
|
$acl = Get-Acl "$env:USERPROFILE\.config\gitea\config.env"
|
||||||
|
$acl.SetAccessRuleProtection($true, $false)
|
||||||
|
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($env:USERNAME, "Read,Write", "Allow")
|
||||||
|
$acl.SetAccessRule($rule)
|
||||||
|
Set-Acl "$env:USERPROFILE\.config\gitea\config.env" $acl
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows CMD**:
|
||||||
|
```cmd
|
||||||
|
:: 创建目录
|
||||||
|
mkdir "%USERPROFILE%\.config\gitea\runners"
|
||||||
|
|
||||||
|
:: 创建配置文件
|
||||||
|
(
|
||||||
|
echo GITEA_URL=https://git.digitevents.com
|
||||||
|
echo GITEA_TOKEN=your_personal_access_token
|
||||||
|
echo GITEA_DEFAULT_ORG=your_org_name
|
||||||
|
echo.
|
||||||
|
echo GITEA_RUNNER_CAPACITY=2
|
||||||
|
echo GITEA_RUNNER_TIMEOUT=3h
|
||||||
|
) > "%USERPROFILE%\.config\gitea\config.env"
|
||||||
|
```
|
||||||
|
|
||||||
## 交互式配置流程
|
## 交互式配置流程
|
||||||
|
|
||||||
### 步骤 1: 输入 Gitea 实例地址
|
### 步骤 1: 输入 Gitea 实例地址
|
||||||
|
|||||||
Reference in New Issue
Block a user