diff --git a/command/git-add.md b/command/git-add.md index 24da577..0b6694d 100644 --- a/command/git-add.md +++ b/command/git-add.md @@ -2,169 +2,64 @@ description: Stage changes with automatic filtering of sensitive files --- -# git-add - Intelligently stage changes while automatically filtering security-sensitive files. -## What It Does +Please perform the following: -- Detects 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 +1. **Detect all unstaged changes:** + - Modified files (M) + - Deleted files (D) + - Untracked files (??) - **重要:第一次就显示并提供选项** -## Quick Start +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 -Use this command when you want to safely stage changes without accidentally committing sensitive information. +3. **Categorize files:** + - **已跟踪的修改/删除** (tracked modified/deleted) + - **未跟踪的安全文件** (untracked safe files) + - **敏感文件** (sensitive files - filtered) -## 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 +4. **Display preview in Chinese:** ``` +=== 将要暂存的文件 (N) === +M [tracked modified files] +D [tracked deleted files] -Categories: -- Modified files (M) -- Deleted files (D) -- Untracked files (??) - **重要:第一次就显示并提供选项** +=== 未跟踪的文件 (N) === +?? [untracked safe files] -### 2. Filter Sensitive Files - -Build exclusion list: -- Read `.gitignore` for patterns -- Read `.secretsignore` if exists (project-specific rules) -- Apply built-in security patterns -- 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: - -``` -=== 将要暂存的文件 (3) === -M src/index.js -M src/utils.js -D old-file.js - -=== 未跟踪的文件 (2) === -?? new-feature.js -?? tests/new-test.js - -=== 敏感文件已过滤 (2) === -⚠ .env.local (Environment file) -⚠ config/secrets.json (Credential file) +=== 敏感文件已过滤 (N) === +⚠ [sensitive files with reasons] === 操作选项 === - 输入 "y" 或 "yes" 暂存已修改/已删除的文件(不包括未跟踪文件) -- 输入 "all" 暂存所有文件(包括未跟踪文件,但排除敏感文件) -- 输入 "with-untracked" 或 "u" 暂存所有文件(包括未跟踪文件) -- 输入 "force" 强制暂存所有文件(包括敏感文件,谨慎使用) +- 输入 "all" 或 "u" 暂存所有安全文件(包括未跟踪文件)✓ 推荐 +- 输入 "force" 强制暂存所有文件(包括敏感文件)⚠️ 谨慎使用 - 输入 "no" 或 "cancel" 取消操作 - 输入文件路径 暂存特定文件 ``` -### 4. User Confirmation +5. **Wait for user confirmation** -Prompt user: -``` -是否确认暂存上述文件? (y/all/u/no) -``` - -**Options:** -- `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 ... - -# Option 2: Stage all including untracked (all/u) -git add - -# 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: +6. **Execute staging based on user choice:** + - `y/yes`: Stage tracked modified/deleted only + - `all/u`: Stage all safe files (including untracked) + - `force`: Show warning, require "confirm" input, then stage everything + - `no/cancel`: Abort + - File path: Stage specific file(s) +7. **Display result in Chinese:** ``` ✓ 暂存成功 -已暂存 3 个文件: - M src/index.js - M src/utils.js - A command/git-add.md +已暂存 N 个文件: + [列出已暂存的文件] 敏感文件已过滤并排除,保护了你的凭证信息。 @@ -173,149 +68,4 @@ Show success message in Chinese: - 运行 /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 +**重要:第一次运行就显示所有选项,包括未跟踪文件的处理方式,不需要用户多次运行命令。** diff --git a/command/git-commit.md b/command/git-commit.md index 5d7aca6..b03e01b 100644 --- a/command/git-commit.md +++ b/command/git-commit.md @@ -2,188 +2,51 @@ 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 +2. **Collect information** - Run these commands in parallel: + - `git status` + - `git diff --cached` + - `git log --oneline -10` + - `git tag --list | sort -V | tail -5` + - Read `@AGENTS.md` if it exists (repository type, version rules, project structure) +3. **Detect repository type** - Polyrepo (tag: `1.2.0`) or Monorepo (tag: `subproject-1.2.0`) +4. **Detect project type and version** - Check for version files: + - iOS: `*.xcodeproj/project.pbxproj` → `MARKETING_VERSION` + - Node.js: `package.json` → `version` + - Android: `build.gradle(.kts)` → `versionName` + - Go: Git tag only +5. **Generate commit message** following Conventional Commits: + - Format: `(): ` + - 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"` -- Analyzes staged changes -- Auto-generates meaningful commit message following Conventional Commits -- Detects project type and updates version number if needed -- Creates appropriate git tag (polyrepo or monorepo format) -- Does NOT push to remote (local only) +**Options:** +- User can input "skip tag" or "skip" to skip tag creation -## Quick Start - -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 -``` - -## 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 `-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` -- Node.js: `package.json` → `version` -- Android: `build.gradle(.kts)` → `versionName` -- Go: Git tag only (no version file) -- etc. - -**Version increment rules:** -- `feat`: minor +1 → `1.2.0` → `1.3.0` -- `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:** -- ✓ feat, fix, perf, breaking changes -- ✗ docs, test, refactor, style, chore, ci, build - -### 5. Generate Commit Message - -Follow Conventional Commits specification: - -**Format:** -``` -(): - - -``` - -**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 ` -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: +**Display result in Chinese:** ``` ✓ 提交成功 -提交信息:feat(android): 添加用户认证 -版本标签:android-1.3.0 +提交信息:[commit message] +版本标签:[tag] (如果创建了) 要推送到远程仓库,请运行:/git-push ``` -## Use Cases - -- 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` +**Important:** This command does NOT push to remote. Use `/git-push` to push commits and tags. diff --git a/command/git-pull.md b/command/git-pull.md index 8d263e5..a383976 100644 --- a/command/git-pull.md +++ b/command/git-pull.md @@ -2,84 +2,22 @@ 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 ` + - Complete the merge with `git commit` +3. **Show the result** with branch status and changes summary -- Fetches latest changes from remote -- Merges remote changes into local branch -- Updates working directory +If there are any errors or conflicts, explain them clearly in Chinese and provide step-by-step guidance for resolution. -## Quick Start - -Use this command to synchronize your local branch with the latest remote changes. - -## Steps - -### 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 ` -- 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 -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 +Present the final result showing: +- Branch name +- Number of commits pulled +- Files changed +- Any conflicts that need attention diff --git a/command/git-push-tags.md b/command/git-push-tags.md index 750339a..c0e47bb 100644 --- a/command/git-push-tags.md +++ b/command/git-push-tags.md @@ -2,90 +2,54 @@ description: Push all local tags to remote repository --- -# git-push-tags - 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 +1. **List local tags:** + ```bash + git tag --list | sort -V + ``` -## Steps +2. **Check remote tags:** + ```bash + git ls-remote --tags origin + ``` -### 1. List Local Tags +3. **Identify unpushed tags** - Compare local and remote to find tags that need to be pushed -```bash -echo "=== Local Tags ===" -git tag --list | sort -V +4. **Display summary in Chinese:** ``` - -### 2. Check Remote Tags - -```bash -echo "=== Remote Tags ===" -git ls-remote --tags origin | awk '{print $2}' | sed 's|refs/tags/||' | sort -V -``` - -### 3. Identify Unpushed Tags - -Compare local and remote tags to identify which tags need to be pushed. - -### 4. Confirm Before Push - -Display summary in Chinese: -``` -本地标签总数:15 个 -远程标签总数:12 个 -待推送标签:3 个 -- 1.3.0 -- 1.3.1 -- ios-2.0.0 +本地标签总数:N 个 +远程标签总数:M 个 +待推送标签:K 个 +- [list of unpushed tags] 确认推送所有标签到 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 + git push --tags + ``` -```bash -git push --tags -# or -git push origin --tags -``` - -### 6. Verify Push - -```bash -echo "=== Push Result ===" -git ls-remote --tags origin | tail -5 -``` - -Display confirmation in Chinese: +7. **Verify and display result in Chinese:** ``` ✓ 已成功推送所有标签到 origin 最近 5 个远程标签: -- 1.3.0 -- 1.3.1 -- ios-2.0.0 -- android-1.5.0 -- electron-3.0.0 +- [list of recent tags] ``` -## Use Cases - +**Use cases:** - After creating multiple local tags - Sync tags with remote repository - Before triggering CI/CD release workflows - Share version tags with team -## Notes - -- **Safe operation**: Pushing tags does not affect commits -- **No force push**: Uses standard push, won't overwrite existing tags -- **All tags**: Pushes ALL local tags, not just one -- If you only want to push a specific tag, use: `git push origin ` +**Notes:** +- Pushes ALL local tags, not just one +- To push a specific tag: `git push origin ` +- Safe operation: won't overwrite existing tags (no force push) diff --git a/command/git-push.md b/command/git-push.md index 6952d0e..1a6f479 100644 --- a/command/git-push.md +++ b/command/git-push.md @@ -2,189 +2,54 @@ 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. ✓ 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 +1-7. **Follow the same steps as `/git-commit`:** + - Check staging area (must not be empty) + - Analyze changes and repository type + - Detect project type and version + - Generate commit message (Conventional Commits, Chinese) + - Update version number if needed + - Commit changes + - Create version tag -## Quick Start + Refer to `/git-commit` for detailed steps or `@skill/git/SKILL.md` for complete workflow. -Use this command when you want to commit AND push in one step. +8. **Push commit to remote:** + ```bash + git push origin $(git branch --show-current) + ``` -## Prerequisites +9. **Push tag to remote** (only if tag was created): + - Polyrepo: `git push origin ` + - Monorepo: `git push origin -` -**Staging area must have files:** -```bash -git add -``` - -## 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) -- Collect information (status, diff, logs, tags, AGENTS.md) -- Detect repository type (polyrepo/monorepo) -- Detect project type and version file -- Generate commit message (Conventional Commits, Chinese/English) -- Update version number if needed -- Commit changes -- Create tag if needed - -Refer to `/git-commit` for detailed steps or see `skill/git/SKILL.md`. - -### 9. Push Commit to Remote - -```bash -# Push current branch to origin -git push origin $(git branch --show-current) -``` - -### 10. Push Tag to Remote - -**Only if tag was created:** - -**Polyrepo:** -```bash -git push origin -# Example: git push origin 1.2.0 -``` - -**Monorepo:** -```bash -git push origin - -# Example: git push origin ios-1.2.0 -``` - -### 11. Display Result - -Show summary in Chinese: +10. **Display result in Chinese:** ``` ✓ 提交并推送成功 -分支:main -提交信息:feat(android): 添加用户认证 -版本标签:android-1.3.0 +分支:[branch] +提交信息:[commit message] +版本标签:[tag] (如果创建了) 已推送到远程仓库:origin -- 提交:a1b2c3d -- 标签:android-1.3.0 +- 提交:[commit hash] +- 标签:[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 | -|---------|--------|-----|-------------|----------| -| `/git-commit` | ✓ | ✓ | ✗ | ✗ | -| `/git-push` | ✓ | ✓ | ✓ | ✓ | -| `/git-push-tags` | ✗ | ✗ | ✗ | ✓ (all tags) | +**Options:** +- User can input "skip tag" or "skip" to skip tag creation -## Use Cases - -- **Quick workflow**: Commit and push in one command -- **Release preparation**: Create version tag and push for CI/CD -- **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` +**When to use:** +- `/git-commit`: Local only, review before pushing +- `/git-push`: Commit and push immediately +- `/git-push-tags`: Push tags only (no commits) diff --git a/command/git-status.md b/command/git-status.md index 681b518..44b968b 100644 --- a/command/git-status.md +++ b/command/git-status.md @@ -2,53 +2,28 @@ 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 -- 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: +Present the information in Chinese with the following structure: ``` -当前分支:main +当前分支: [branch_name] -未暂存的文件 (3): -- src/index.js -- src/utils.js -- README.md +暂存区文件 ([count]): +[列出已暂存的文件] -已暂存的文件 (2): -- package.json -- src/config.js +未暂存的修改 ([count]): +[列出未暂存的修改文件] + +未跟踪的文件 ([count]): +[列出未跟踪的文件] ``` -## Use Cases - -- Quick status check before committing -- Review what files have changed -- Check if you're on the correct branch +Use clear formatting and emoji indicators (✓, ⚠️, etc.) to make the output easy to read. diff --git a/command/gitea-config.md b/command/gitea-config.md index 4081d31..c585bfe 100644 --- a/command/gitea-config.md +++ b/command/gitea-config.md @@ -2,167 +2,71 @@ 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 -- 显示默认组织 -- 验证 Token 状态和关联用户 -- 显示已配置的 Runner 数量和列表 -- 显示配置文件路径 +**Windows:** +``` +%USERPROFILE%\.config\gitea\ +``` -## 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 -config_dir="$HOME/.config/gitea" -config_file="$config_dir/config.env" - -if [ ! -f "$config_file" ]; then - echo "❌ Gitea 未配置" - echo "请运行 /gitea-reset 进行配置" - exit 1 -fi +source ~/.config/gitea/config.env ``` -### 2. Load and Display Configuration - -```bash -source "$config_file" - -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "当前 Gitea 配置" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" -echo " URL: $GITEA_URL" -echo " 默认组织: ${GITEA_DEFAULT_ORG:-<未设置>}" -echo " 配置文件: $config_file" -echo "" +**Windows PowerShell:** +```powershell +Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + [Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process') + } +} ``` -### 3. Validate Token and Display User Info +Show in Chinese: +- Gitea URL +- Default organization (if set) +- Config file path (根据平台显示正确路径) -```bash -response=$(curl -s -w "\n%{http_code}" \ - -H "Authorization: token $GITEA_TOKEN" \ - "${GITEA_URL}/api/v1/user") +3. **Validate token and display user info:** + - Call API: `GET ${GITEA_URL}/api/v1/user` + - Header: `Authorization: token ${GITEA_TOKEN}` + - Show: Token status (✓ 有效 / ✗ 无效), username, email -http_code=$(echo "$response" | tail -n1) -body=$(echo "$response" | sed '$d') +4. **Display runner information:** + - Runners directory: + - macOS/Linux: `~/.config/gitea/runners` + - Windows: `%USERPROFILE%\.config\gitea\runners` + - Count configured runners + - List each runner with status: + - 🟢 运行中 (process running) + - 🔴 已停止 (process not running) + - ⚠️ 配置异常 (config file missing) -if [ "$http_code" = "200" ]; then - username=$(echo "$body" | jq -r '.login') - email=$(echo "$body" | jq -r '.email // "<未设置>"') - echo " Token 状态: ✓ 有效" - echo " 登录用户: $username" - echo " 邮箱: $email" -else - echo " Token 状态: ✗ 无效或已过期" -fi +5. **Show management commands:** +``` +管理命令: +- 重置配置: /gitea-reset +- 切换组织: /gitea-switch-org +- 列出 Runners: /gitea-list-runners +- 创建仓库: /create-gitea-repo ``` -### 4. Display Runner Information - -```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 " -echo " 列出 Runners: /gitea-list-runners" -echo " 创建仓库: /create-gitea-repo " -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 - 列出 Runners: /gitea-list-runners - 创建仓库: /create-gitea-repo -``` - -## Notes - -- 使用 `jq` 解析 JSON 响应 -- 检查 runner 进程使用 `pgrep` -- Token 验证通过调用 `/api/v1/user` endpoint -- Runner 状态:🟢 运行中、🔴 已停止、⚠️ 配置异常 +Use `jq` to parse JSON responses and `pgrep` to check runner process status. diff --git a/command/gitea-create-repo.md b/command/gitea-create-repo.md index d138909..d0215e7 100644 --- a/command/gitea-create-repo.md +++ b/command/gitea-create-repo.md @@ -2,255 +2,103 @@ 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:** ``` -[/] [private|public] +~/.config/gitea/ ``` -- `owner`: Organization name or username (optional, uses `GITEA_DEFAULT_ORG` if set, otherwise uses current user) -- `repo`: Repository name (required) -- `private|public`: Visibility (optional, default `private`) +**Windows:** +``` +%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 = [/] [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 | -| --- | --- | -| Gitea Server URL | `GITEA_URL` from config.env | -| API Token | `GITEA_TOKEN` from config.env | -| Default Organization | `GITEA_DEFAULT_ORG` from config.env (optional) | +Please perform the following: -## Steps - -### 0. Load Configuration - -Before executing, load Gitea configuration: +1. **Load configuration:** +**macOS / Linux:** ```bash -config_file="$HOME/.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 +source ~/.config/gitea/config.env ``` -### 1. Parse User Input - -Parse from user input: -- `owner`: Organization name or username -- `repo`: Repository name -- `visibility`: `private` (default) or `public` - -**Input parsing logic**: - -```bash -input="$1" -visibility="${2:-private}" - -# Parse owner/repo -if [[ "$input" =~ / ]]; then - owner=$(echo "$input" | cut -d'/' -f1) - 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") +**Windows PowerShell:** +```powershell +Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + [Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process') + } +} ``` -**Input validation**: -- Repository name can only contain letters, numbers, underscores, hyphens and dots + - If not exists: prompt to run `/gitea-reset` -```bash -if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then - echo "❌ 仓库名只能包含字母、数字、下划线、连字符和点" - exit 1 -fi -``` +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 -### 2. Call Gitea API to Create Repository +3. **Create repository via API:** + - Try organization API first: + ```bash + POST ${GITEA_URL}/api/v1/orgs/${owner}/repos + Body: { + "name": "${repo}", + "private": true/false, + "auto_init": false, + "default_branch": "main" + } + ``` + - If 404, try user API: `POST /api/v1/user/repos` + - Handle response codes: + - 201: Success + - 409: Repository already exists + - 404: Owner not found or no permission + - Other: API error -Use curl to call Gitea API with configuration: +4. **Extract repository info from response:** + - `html_url` - Web URL + - `clone_url` - HTTPS URL + - `ssh_url` - SSH URL -```bash -echo "正在创建仓库: $owner/$repo ($visibility)" +5. **Ask user if they want to add remote:** + - Check if current directory is a git repo + - If not, ask to initialize: `git init` + - Check if `origin` remote exists + - Add or update remote: `git remote add/set-url origin ` -# 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 ` - - If origin exists: Ask whether to overwrite, after confirmation execute `git remote set-url origin ` - -### 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**: +6. **Display result in Chinese:** ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 仓库创建成功 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - 名称: ai/my-project - 可见性: private - Web URL: https://git.digitevents.com/ai/my-project - HTTPS URL: https://git.digitevents.com/ai/my-project.git - SSH URL: git@git.digitevents.com:ai/my-project.git + 名称: [owner]/[repo] + 可见性: [private/public] + Web URL: [html_url] + HTTPS URL: [clone_url] + SSH URL: [ssh_url] ``` -## Notes - -- **Permission check**: Ensure Token has permission to create repository -- **Organization vs User**: Creating organization repository and user repository use different API endpoints -- **Repository naming**: Follow Gitea naming rules, avoid special characters +**Notes:** +- Requires repo creation permission in token +- Organization and user repositories use different API endpoints +- Default branch is `main` (not `master`) diff --git a/command/gitea-create-runner.md b/command/gitea-create-runner.md index ecb34e7..a71a72f 100644 --- a/command/gitea-create-runner.md +++ b/command/gitea-create-runner.md @@ -1,52 +1,160 @@ --- 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 模式,自动检测系统环境并配置。 - -**重要**:这是一个可执行命令,AI 应该按照以下步骤执行操作。 - -## 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 +**macOS / Linux:** +``` +~/.config/gitea/ ``` -## 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 diff --git a/command/gitea-delete-runner.md b/command/gitea-delete-runner.md index d3d5772..ff4ff11 100644 --- a/command/gitea-delete-runner.md +++ b/command/gitea-delete-runner.md @@ -1,422 +1,63 @@ --- 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 -- 交互式选择要删除的 runner -- 支持删除单个或所有 runners -- 删除 runner 配置目录(包括 cache 和 workspace) -- 停止运行中的 runner 进程 -- 自动从 Gitea 服务器注销 runner -- 安全确认机制(需要用户输入 'yes') +Please perform the following steps: -## User Input Format +## Step 1: Load Configuration and Fetch Runners -无需参数,运行后交互式选择。 +1. **Load Gitea configuration:** +**macOS / Linux:** ```bash -/gitea-delete-runner +source ~/.config/gitea/config.env ``` -## AI 执行指导 - -当用户调用此命令时,AI 应该: - -1. **获取并展示 runner 列表**:调用 Gitea API 获取服务器上的全局 runners,并以清晰的格式展示给用户 -2. **等待用户选择**:让用户选择要删除的 runner(序号、'all' 或 'q') -3. **确认操作**:在删除前要求用户输入 'yes' 确认 -4. **执行删除**:按照三步流程删除选中的 runners -5. **显示结果**:展示删除操作的详细结果 - -**注意**:此命令需要与用户进行多次交互,不要一次性执行所有步骤。 - -## Implementation Steps - -### 1. Load Configuration - -```bash -config_file_main="$HOME/.config/gitea/config.env" - -if [ ! -f "$config_file_main" ]; then - echo "❌ 未找到 Gitea 配置文件" - echo " 路径: $config_file_main" - exit 1 -fi - -source "$config_file_main" - -if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then - echo "❌ Gitea 配置不完整" - echo " 需要 GITEA_URL 和 GITEA_TOKEN" - exit 1 -fi +**Windows PowerShell:** +```powershell +Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + [Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process') + } +} ``` -### 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 -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 +3. **Display runners list in Chinese:** ``` - -**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 ] 🟢 在线 - 系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30 - - 2. runner-macbook-pro [ID: 43 ] 🔴 离线 - 系统: darwin 架构: arm64 最后在线: 2026-01-10 18:45 - - 3. runner-linux-server [ID: 44 ] 🟢 在线 - 系统: linux 架构: amd64 最后在线: 2026-01-12 10:25 + 1. [runner-name] [ID: XX] 🟢 在线/🔴 离线 + 2. [runner-name] [ID: XX] 🟢 在线/🔴 离线 +... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 选择要删除的 Runner @@ -425,11 +66,21 @@ Gitea 全局 Runners (共 3 个) 输入序号: 删除单个 runner 输入 'all': 删除所有 runners 输入 '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 - 停止本地运行的 runner 进程 @@ -437,159 +88,87 @@ Gitea 全局 Runners (共 3 个) - 删除 cache 和 workspace 目录 - 删除所有相关数据 -确认删除? 输入 'yes' 继续: yes +将删除以下 runners: + - [list of runners to be deleted] -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -删除: runner-macbook-pro (ID: 43) -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +确认删除? 输入 'yes' 继续: +``` -[1/3] 从 Gitea 服务器注销... - ✓ 已从服务器注销 -[2/3] 检查本地进程... - ✓ 未运行 -[3/3] 删除本地配置... - ✓ 本地配置已删除 +**Wait for user confirmation** → Do NOT proceed until user types 'yes' +## Step 4: Execute Deletion + +If user confirmed with 'yes', for each selected runner: + +### 4.1 Unregister from Gitea Server +```bash +DELETE ${GITEA_URL}/api/v1/admin/actions/runners/${runner_id} +``` +- Expected: HTTP 204 +- Show: "✓ 已从服务器注销" or "⚠️ 注销失败" + +### 4.2 Stop Local Process +1. Find local runner directory by matching ID in `.runner` file +2. Check if process is running: `pgrep -f "act_runner daemon --config ..."` +3. If running: + - Check if runner is busy (executing jobs) via API + - **If busy, wait for user choice:** + ``` + ⚠️ 警告: Runner 正在执行 job! + 选项: + 1. 等待 job 完成后再停止(推荐) + 2. 强制立即停止 + ``` + - **Wait for user input** → Proceed based on choice + - If waiting: Poll status every 10 seconds, max 5 minutes + - Stop process: `kill $pid` (graceful), then `kill -9 $pid` if needed (force) + +### 4.3 Delete Local Directory + +**macOS / Linux:** +```bash +rm -rf ~/.config/gitea/runners/[runner_name] +``` + +**Windows PowerShell:** +```powershell +Remove-Item -Path "$env:USERPROFILE\.config\gitea\runners\[runner_name]" -Recurse -Force +``` + +## Step 5: Display Result + +Show completion summary in Chinese: +``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 删除完成 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -成功: 1 个 +成功: N 个 +失败: M 个 (if any) 管理命令: 查看剩余 runners: /gitea-list-runners 创建新 runner: /gitea-create-runner ``` -### Example 2: Delete All Runners +--- -``` -正在从 Gitea 服务器获取全局 runners... +## Key Points -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Gitea 全局 Runners (共 2 个) -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +**Interactive checkpoints (wait for user input):** +1. Step 1: After displaying runners list → Wait for selection +2. Step 3: After displaying warning → Wait for confirmation ('yes') +3. Step 4.2: If runner is busy → Wait for stop choice (1 or 2) - 1. runner-mac-mini4 [ID: 42 ] 🟢 在线 - 系统: darwin 架构: arm64 最后在线: 2026-01-12 10:30 +**Safety features:** +- Double confirmation required +- Busy status detection +- Graceful stop before force kill +- Three-step deletion process +- Clear status reporting - 2. runner-linux-server [ID: 44 ] 🟢 在线 - 系统: linux 架构: amd64 最后在线: 2026-01-12 10:25 - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -选择要删除的 Runner -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - 输入序号: 删除单个 runner - 输入 'all': 删除所有 runners - 输入 'q' 或 'quit': 取消 - -请选择: all - -⚠️ 将删除所有 2 个 runners - -⚠️ 警告: 此操作将执行以下操作: - - 从 Gitea 服务器注销 runner - - 停止本地运行的 runner 进程 - - 删除 runner 配置文件 - - 删除 cache 和 workspace 目录 - - 删除所有相关数据 - -将删除 2 个 runners: - - runner-mac-mini4 (ID: 42) - - runner-linux-server (ID: 44) - -确认删除? 输入 'yes' 继续: yes - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -删除: runner-mac-mini4 (ID: 42) -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -[1/3] 从 Gitea 服务器注销... - ✓ 已从服务器注销 -[2/3] 检查本地进程... - 正在停止进程 (PID: 12345)... - ✓ 进程已停止 -[3/3] 删除本地配置... - ✓ 本地配置已删除 - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -删除: runner-linux-server (ID: 44) -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -[1/3] 从 Gitea 服务器注销... - ✓ 已从服务器注销 -[2/3] 检查本地进程... - ⓘ 未找到本地配置 -[3/3] 删除本地配置... - ⓘ 无本地配置需要删除 - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -删除完成 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -成功: 2 个 - -管理命令: - 查看剩余 runners: /gitea-list-runners - 创建新 runner: /gitea-create-runner -``` - -## Safety Features - -- **服务器数据优先**:直接从 Gitea 服务器获取 runner 列表,确保准确性 -- **交互式选择**:支持选择单个或所有 runners,避免误删 -- **双重确认**:需要输入 'yes' 进行最终确认(防止误删) -- **Busy 状态检测**:检查 runner 是否正在执行 job - - 如果 runner 正在执行 job,给用户选择: - - 等待 job 完成后停止(推荐) - - 强制立即停止(有风险) -- **优雅停止**:先尝试 SIGTERM,2 秒后才使用 SIGKILL -- **服务器注销**:自动从 Gitea 服务器注销 runner -- **三步删除流程**: - 1. 从服务器注销 - 2. 停止本地进程(检测 busy 状态) - 3. 删除本地配置 -- **清晰提示**:显示每个步骤的执行状态和警告信息 -- **批量删除支持**:可一次性删除所有 runners -- **错误处理**:各步骤独立执行,部分失败不影响其他操作 -- **超时保护**:等待 job 完成最多 5 分钟,超时后强制停止 - -## Technical Notes - -- **必需工具**:需要安装 `jq` 工具(`brew install jq`) -- **权限要求**:需要 Gitea admin 权限(全局 runner 管理) -- **配置文件**:读取 `~/.config/gitea/config.env` 获取 API 配置 -- **本地匹配**:通过 runner ID 匹配本地配置目录 -- **服务器同步**:从服务器注销后再删除本地配置 -- **无本地配置**:如果只存在服务器记录,仅注销服务器端 -- **取消操作**:输入 'q' 或 'quit' 可随时取消 -- **临时文件**:使用 `/tmp/gitea_runners.txt` 存储临时数据,操作完成后自动清理 -- **API 格式**:Gitea API 返回格式为 `{"runners": [...], "total_count": N}`,不是直接的数组 -- **Busy 检测**:通过 API 的 `busy` 字段判断 runner 是否正在执行 job -- **停止信号**: - - `kill $pid` (SIGTERM): 优雅停止,给进程清理资源的机会 - - `kill -9 $pid` (SIGKILL): 强制终止,无法被捕获或忽略 -- **等待策略**:如果 runner busy,最多等待 5 分钟(300 秒),每 10 秒检查一次状态 - -## AI 执行流程总结 - -当用户调用 `/gitea-delete-runner` 时,AI 应该按以下流程执行: - -1. **步骤 1**:加载并验证 Gitea 配置 -2. **步骤 2**:获取并展示 runners 列表 → **等待用户选择** -3. **步骤 3**:处理用户选择,验证输入 -4. **步骤 4**:显示删除警告和列表 → **等待用户确认** -5. **步骤 5**:执行删除操作 - - 5.1: 从服务器注销 - - 5.2: 检查并停止本地进程 - - **如果 runner 正在执行 job(busy)** → **等待用户选择**(等待完成 or 强制停止) - - 5.3: 删除本地配置 -6. **步骤 6**:显示操作结果摘要 - -**重要**:这是一个交互式命令,可能需要在以下位置等待用户输入: -- 步骤 2: 选择要删除的 runner -- 步骤 4: 确认删除操作 -- 步骤 5.2: 如果 runner 正在执行 job,选择等待或强制停止 - -不要一次性执行所有步骤。 +**Technical notes:** +- Requires `jq` for JSON parsing +- Requires admin token for global runners +- Uses temporary file `/tmp/gitea_runners.txt` for data passing +- Cleanup temp file after completion diff --git a/command/gitea-list-runners.md b/command/gitea-list-runners.md index 3ad56e7..8c2269a 100644 --- a/command/gitea-list-runners.md +++ b/command/gitea-list-runners.md @@ -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 - -- 显示所有已配置的 runner -- 检查 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 +**macOS / Linux:** +``` +~/.config/gitea/ ``` -### 2. List All Runners - -```bash -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 "" +**Windows:** +``` +%USERPROFILE%\.config\gitea\ ``` -### 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 -for runner in $runners; do - runner_dir="$runners_dir/$runner" - 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 +curl -s -H "Authorization: token " \ + "/api/v1/admin/actions/runners" ``` -### 4. Display Summary Commands +3. **Parse JSON response and extract information:** + - Response structure: + ```json + { + "runners": [...], + "total_count": 1 + } + ``` + - Use `jq` to parse JSON + - For each runner in `runners` array: + - `id`: Runner ID + - `name`: Runner name + - `status`: Runner status ("online"/"offline") + - `busy`: Whether runner is currently busy (true/false) + - `ephemeral`: Whether runner is ephemeral (true/false) + - `labels`: Array of label objects with `name` and `type` -```bash -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "管理命令" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" -echo " 查看配置: /gitea-config" -echo " 创建 runner: /gitea-create-runner" -echo " 删除 runner: /gitea-delete-runner" -echo "" -``` +4. **Determine runner status:** + - 🟢 在线 - `status: "online"` + - 🔴 离线 - `status: "offline"` + - ⚠️ 未知 - Unable to determine -## Output Example +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] - 状态: 🟢 运行中 - PID: 12345 - 容量: 2 - 超时: 3h - Labels: self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host - 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 & +[runner-name] + 状态: 🟢/🔴 [在线/离线] + ID: [id] + 忙碌: 是/否 + 临时: 是/否 + 标签: [comma-separated labels] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 管理命令 @@ -189,14 +84,11 @@ Gitea Runners 删除 runner: /gitea-delete-runner ``` -## Notes - -- 使用 `pgrep` 检查进程状态 -- 优先使用 `yq` 解析 YAML,fallback 到 `grep` -- 优先使用 `jq` 解析 JSON `.runner` 文件 -- Runner 状态图标: - - 🟢 运行中 - - 🔴 已停止 - - ⚠️ 配置异常 -- 显示启动命令方便用户复制执行 -- 对已停止的 runner,额外显示后台启动命令 +**Notes:** +- Requires admin API token to list runners +- **Correct API endpoint**: `/api/v1/admin/actions/runners` (not `/api/v1/admin/runners`) +- Only shows global runners (instance-level runners) +- Uses `jq` for JSON parsing +- Response includes: `id`, `name`, `status`, `busy`, `ephemeral`, `labels` +- If API call fails, show error message and suggest checking token permissions +- Tested with Gitea version 1.25.3 diff --git a/command/gitea-reset.md b/command/gitea-reset.md index 825e8b6..de6eb7b 100644 --- a/command/gitea-reset.md +++ b/command/gitea-reset.md @@ -1,70 +1,47 @@ --- 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 - -- 交互式引导配置 -- 验证 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 "" +**macOS / Linux:** +``` +~/.config/gitea/ ``` -### 2. Input Gitea URL - -```bash -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" +**Windows:** +``` +%USERPROFILE%\.config\gitea\ ``` -### 3. Input Personal Access Token +配置文件和 Runner 目录都将存储在此位置。 +Please perform the following: + +1. **Create configuration directory:** + +**macOS / Linux:** ```bash -echo "" -read -sp "请输入 Personal Access Token: " gitea_token -echo "" - -if [ -z "$gitea_token" ]; then - echo "❌ Token 不能为空" - exit 1 -fi - -echo "✓ Token 已输入" +mkdir -p ~/.config/gitea/runners ``` -**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 的步骤: 1. 登录 Gitea @@ -75,221 +52,58 @@ echo "✓ Token 已输入" 6. 点击 "生成令牌" 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 -echo "" -echo "正在测试连接..." - -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_URL=... +GITEA_TOKEN=... +GITEA_DEFAULT_ORG=... (if set) GITEA_RUNNER_CAPACITY=2 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 " -echo "" ``` + - Set permissions: `chmod 600 ~/.config/gitea/config.env` + - Create `.gitignore` to exclude sensitive files -## Configuration File Format - -生成的 `~/.config/gitea/config.env` 文件格式: - +**Windows** - Save to `%USERPROFILE%\.config\gitea\config.env`: ```bash -# Gitea Configuration -# Generated at 2026-01-12 22:00:00 - -GITEA_URL=https://git.digitevents.com -GITEA_TOKEN=git_xxxxxxxxxxxxxxxxxxxx -GITEA_DEFAULT_ORG=ai - -# Runner Default Settings +GITEA_URL=... +GITEA_TOKEN=... +GITEA_DEFAULT_ORG=... (if set) GITEA_RUNNER_CAPACITY=2 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 - Runner 目录: /Users/voson/.config/gitea/runners + 配置文件: ~/.config/gitea/config.env + Runner 目录: ~/.config/gitea/runners 下一步: - 查看配置: /gitea-config @@ -297,18 +111,22 @@ GITEA_RUNNER_TIMEOUT=3h - 创建仓库: /create-gitea-repo ``` -## Security Notes +**Windows:** +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +配置完成 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -- 配置文件权限设置为 `600`(仅所有者可读写) -- Token 不会在日志中显示 -- 创建 `.gitignore` 文件排除敏感信息 -- 建议定期轮换 Token(每 3-6 个月) + 配置文件: %USERPROFILE%\.config\gitea\config.env + Runner 目录: %USERPROFILE%\.config\gitea\runners -## Notes +下一步: + - 查看配置: /gitea-config + - 创建 Runner: 告诉 AI '创建一个 runner' + - 创建仓库: /create-gitea-repo +``` -- **必需权限**: `repo` - 创建和管理仓库 -- **推荐权限**: `admin:org` - 创建组织级 Runner -- **推荐权限**: `write:runner` - 管理 Runner -- **可选权限**: `admin:repo_hook` - 配置 Webhooks -- Token 只显示一次,请妥善保管 -- 重置配置不会影响已创建的 Runner,但 Runner 会继续使用旧的注册信息 +**Security notes:** +- Config file permissions: 600 (owner read/write only) +- Token is never displayed after initial input +- Sensitive files excluded in .gitignore diff --git a/command/gitea-switch-org.md b/command/gitea-switch-org.md index e6d0283..04ed834 100644 --- a/command/gitea-switch-org.md +++ b/command/gitea-switch-org.md @@ -2,154 +2,81 @@ description: Switch default Gitea organization --- -# gitea-switch-org +Switch the default Gitea organization in configuration. -切换默认 Gitea 组织。 - -## Features - -- 更新配置文件中的默认组织 -- 验证组织是否存在 -- 立即生效,无需重启 - -## User Input Format +## 工作目录 +**macOS / Linux:** ``` - +~/.config/gitea/ ``` -**Examples**: -- `ai` - Switch to 'ai' organization -- `my-team` - Switch to 'my-team' organization +**Windows:** +``` +%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 -config_file="$HOME/.config/gitea/config.env" - -if [ ! -f "$config_file" ]; then - echo "❌ Gitea 未配置" - echo "请先运行 /gitea-reset 进行配置" - exit 1 -fi - -source "$config_file" +source ~/.config/gitea/config.env ``` -### 2. Parse User Input - -```bash -new_org="$1" - -if [ -z "$new_org" ]; then - echo "用法: /gitea-switch-org " - echo "" - echo "示例:" - echo " /gitea-switch-org ai" - echo " /gitea-switch-org my-team" - exit 1 -fi +**Windows PowerShell:** +```powershell +Get-Content "$env:USERPROFILE\.config\gitea\config.env" | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + [Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process') + } +} ``` -### 3. Validate Organization Exists +3. **Parse user input:** + - Organization name from `$ARGUMENTS` + - If empty: show usage and examples -```bash -echo "正在验证组织 '$new_org'..." +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 + curl -s -H "Authorization: token $GITEA_TOKEN" \ + "${GITEA_URL}/api/v1/user/orgs" | jq -r '.[].username' + ``` -response=$(curl -s -w "\n%{http_code}" \ - -H "Authorization: token $GITEA_TOKEN" \ - "${GITEA_URL}/api/v1/orgs/${new_org}") +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 -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" \ - "${GITEA_URL}/api/v1/user/orgs" | jq -r '.[].username' | sed 's/^/ - /' - - exit 1 -fi - -org_name=$(echo "$body" | jq -r '.full_name // .username') -echo "✓ 组织验证成功: $org_name" +6. **Display result in Chinese:** ``` - -### 4. Update Configuration File - -```bash -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" -``` - -### 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 +✓ 默认组织已切换到: [org_name] 现在可以: - 创建仓库: /create-gitea-repo my-project - (将创建到 ai/my-project) + (将创建到 [org_name]/my-project) - 查看配置: /gitea-config ``` -## Notes - -- 切换组织不会影响已创建的仓库和 Runner -- 仅影响后续创建仓库时的默认 owner -- 可以随时切换到其他组织 -- 使用 `jq` 解析 JSON 响应 -- macOS 和 Linux 的 `sed` 命令略有不同,需兼容处理 +**Notes:** +- Switching organization doesn't affect existing repositories or runners +- Only affects default owner for future repository creation +- Can switch anytime diff --git a/command/review.md b/command/review.md index f57c527..3fa584b 100644 --- a/command/review.md +++ b/command/review.md @@ -3,14 +3,18 @@ description: Review code or documentation and provide suggestions 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 -2. Provide suggestions and content that needs modification -3. Ask user if modifications are needed, if there's content that doesn't need modification; if user doesn't specify, modify all +1. **Review** the code or documentation mentioned by the user +2. **Identify issues** and areas for improvement +3. **Provide suggestions** with clear explanations +4. **Ask for confirmation** before making modifications -## 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 diff --git a/opencode.json b/opencode.json index 1efa3fd..496b3d7 100644 --- a/opencode.json +++ b/opencode.json @@ -23,18 +23,6 @@ } }, "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" } diff --git a/plugin/notification.ts b/plugin/notification.ts new file mode 100644 index 0000000..4e1c2c5 --- /dev/null +++ b/plugin/notification.ts @@ -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 + ) + } + }, + } +} diff --git a/skill/gitea/SKILL.md b/skill/gitea/SKILL.md index f06f84f..f441f0a 100644 --- a/skill/gitea/SKILL.md +++ b/skill/gitea/SKILL.md @@ -7,6 +7,51 @@ description: Comprehensive Gitea management tool for creating runners, workflows 完整的 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 二进制文件 + ## 功能概览 | 功能模块 | 文档 | 说明 | diff --git a/skill/gitea/runner-management.md b/skill/gitea/runner-management.md index 6715aa3..a297e21 100644 --- a/skill/gitea/runner-management.md +++ b/skill/gitea/runner-management.md @@ -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 支持 | -| Docker Mode | Linux 容器 | 跨平台构建 | Linux ARM64 不支持 | +| 模式 | 环境 | 适用场景 | 平台支持 | +|------|------|---------|---------| +| **Host Mode** | Native OS(macOS/Linux/Windows) | Android/iOS 构建、原生工具链 | 全平台支持 | +| 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 配置统一管理在: +### macOS / Linux ``` ~/.config/gitea/runners/ ├── 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 +**macOS**: ```bash # 使用 Homebrew(推荐) 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 \ -o /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 ``` +**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. 安装开发工具(可选,根据需要) ```bash diff --git a/skill/gitea/setup-guide.md b/skill/gitea/setup-guide.md index 6c282e2..f26a6b8 100644 --- a/skill/gitea/setup-guide.md +++ b/skill/gitea/setup-guide.md @@ -12,6 +12,7 @@ Gitea skill 需要配置连接信息才能与你的 Gitea 实例交互。配置 ## 配置目录结构 +### macOS / Linux ``` ~/.config/gitea/ ├── config.env # 主配置文件(包含 URL、Token、默认组织等) @@ -20,6 +21,20 @@ Gitea skill 需要配置连接信息才能与你的 Gitea 实例交互。配置 └── .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: 使用交互式向导(推荐) @@ -48,6 +63,7 @@ AI 会自动启动配置向导。 如果你熟悉配置格式,可以手动创建: +**macOS / Linux**: ```bash mkdir -p ~/.config/gitea/runners cat > ~/.config/gitea/config.env << 'EOF' @@ -62,6 +78,45 @@ EOF 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 实例地址