chore: 重构 OpenCode 命令和技能文档体系

- 新增:统一的 git 命令文档(add/commit/push/pull 等)
- 新增:整合的 Gitea 技能文档(API、运行器、工作流等)
- 新增:工作流模板(Android、Go、Node.js 等)
- 移除:已弃用的旧命令脚本和发布脚本
- 改进:.gitignore 添加敏感文件保护规则
- 改进:AGENTS.md 完善了开发规范和示例

此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
This commit is contained in:
Voson
2026-01-13 00:27:14 +08:00
parent 84a3b48d43
commit 5a05d5ab53
35 changed files with 9658 additions and 1609 deletions

565
skill/git/SKILL.md Normal file
View File

@@ -0,0 +1,565 @@
---
name: git
description: Git workflow best practices with commit conventions, tagging, and common operations for both polyrepo and monorepo
---
# Git Workflow Best Practices
You are an expert in Git version control and repository management.
## Core Principles
1. **Default Main Branch**: Use `main` as the primary branch (not `master`)
2. **Conventional Commits**: Follow [Conventional Commits](https://www.conventionalcommits.org/) specification
3. **Semantic Versioning**: Use `major.minor.patch` format (e.g., `0.1.0`, `1.2.3`)
4. **Repository Types**: Support both polyrepo and monorepo workflows
5. **Clean History**: Maintain meaningful commit history and proper tagging
## Repository Types
### Polyrepo (Single Repository)
- Each project has its own repository
- Tag format: `<version>` (e.g., `1.2.0`)
- Version files at project root
- Simpler workflow for independent projects
### Monorepo (Multiple Subprojects)
- Multiple projects in a single repository
- Detect from `AGENTS.md` file or directory structure (e.g., `packages/`, `apps/`)
- Tag format: `<subproject>-<version>` (e.g., `ios-1.2.0`, `android-0.3.1`)
- Commit scope includes subproject name when changes affect single project
- Each subproject maintains independent versioning
**Monorepo Detection Rules:**
- Check if `AGENTS.md` explicitly indicates monorepo
- Look for common monorepo directory structures:
- `packages/`, `apps/`, `services/`, `modules/`, `projects/`
- If uncertain, default to polyrepo
## Commit Message Convention
### Format
```
<type>(<scope>): <subject>
<body>
<footer>
```
### Commit Types
| Type | Description | Version Impact | Examples |
|------|-------------|----------------|----------|
| `feat` | New feature | minor +1 | Add user authentication |
| `fix` | Bug fix | patch +1 | Fix memory leak in cache |
| `perf` | Performance improvement | patch +1 | Optimize database queries |
| `BREAKING CHANGE` or `!` | Breaking change | major +1 | Remove deprecated API |
| `docs` | Documentation only | None | Update README |
| `style` | Code style/formatting | None | Fix indentation |
| `refactor` | Code refactoring | None | Reorganize file structure |
| `test` | Add/modify tests | None | Add unit tests for auth |
| `chore` | Maintenance tasks | None | Update dependencies |
| `ci` | CI/CD changes | None | Update workflow config |
| `build` | Build system changes | None | Update webpack config |
### Commit Message Language
- **Default (macOS/Linux)**: Use Chinese (中文)
- **Windows**: Use English (due to Cursor Shell tool encoding issues)
- **Content**: Focus on "why" rather than "what"
- **Length**: Subject line ≤ 50 characters, body line ≤ 72 characters
### Scope (for Monorepo)
When changes affect a single subproject, include scope:
- Format: `<type>(<scope>): <subject>`
- Example: `feat(ios): add OGG Opus upload support`
- Example: `fix(electron): resolve clipboard injection issue`
When changes affect multiple subprojects or the entire repository, omit scope:
- Example: `chore: update shared dependencies`
### Examples
**Polyrepo commits:**
```bash
feat: add user authentication with OAuth2
fix: resolve bluetooth connection timeout
docs: update API documentation
chore: update project dependencies
```
**Monorepo commits:**
```bash
feat(ios): add OGG Opus upload support
fix(android): resolve memory leak in cache manager
refactor(electron): reorganize main process code
chore: update shared ESLint configuration
```
## Version Management
### Semantic Versioning
Format: `major.minor.patch` (e.g., `0.1.0`, `1.2.3`, `2.0.0`)
- **Default starting version**: `0.1.0`
- **Major** (X.0.0): Breaking changes, API incompatibility
- **Minor** (0.X.0): New features, backward compatible
- **Patch** (0.0.X): Bug fixes, backward compatible
### Version Increment Rules
| Change Type | Version Change | Example |
|-------------|----------------|---------|
| Breaking change | major +1, reset minor/patch | `1.2.3``2.0.0` |
| New feature (`feat`) | minor +1, reset patch | `1.2.3``1.3.0` |
| Bug fix (`fix`) | patch +1 | `1.2.3``1.2.4` |
| Performance (`perf`) | patch +1 | `1.2.3``1.2.4` |
### When to Update Version
**Update version** (user-perceivable changes):
- New features (`feat`)
- Bug fixes that affect users (`fix`)
- Performance improvements users can notice (`perf`)
- Breaking changes (major version bump)
**Don't update version** (internal changes):
- Documentation (`docs`)
- Tests (`test`)
- Refactoring without behavior change (`refactor`)
- Code style (`style`)
- Build configuration (`build`)
- CI/CD changes (`ci`)
- Maintenance tasks (`chore`)
**Decision criteria:**
1. Will this be packaged into the final product?
2. Will users notice this change?
3. Does it affect the product that users download/use?
If answer is "yes" → update version. Otherwise → skip version update.
## Project Type Detection
### Common Project Types
| Project Type | Version File | Version Field |
|--------------|--------------|---------------|
| iOS | `*.xcodeproj/project.pbxproj` | `MARKETING_VERSION` |
| npm/Node.js | `package.json` | `version` |
| Android (Groovy) | `app/build.gradle` | `versionName` |
| Android (Kotlin DSL) | `app/build.gradle.kts` | `versionName` |
| Python (pyproject) | `pyproject.toml` | `[project] version` or `[tool.poetry] version` |
| Python (setup) | `setup.py` | `version` |
| Rust | `Cargo.toml` | `[package] version` |
| Go | Git tag only | - |
| Flutter | `pubspec.yaml` | `version` |
| .NET | `*.csproj` | `<Version>` or `<PackageVersion>` |
### Detection Strategy
1. **Check AGENTS.md first**: If version rules are defined, use them
2. **Auto-detect**: Scan for version files based on project structure
3. **Fallback**: If no version file found, only create Git tag (like Go projects)
## Tag Management
### Tag Format
**Polyrepo:**
```bash
<version>
Examples: 1.2.0, 0.3.1, 2.0.0
```
**Monorepo:**
```bash
<subproject>-<version>
Examples: ios-1.2.0, android-0.3.1, electron-2.0.0
```
### Tag Annotation
- **Use same content as commit message** for tag annotation
- Tag annotations are used as Release notes by CI/CD
- Multi-line commits should have multi-line annotations
**Single-line example:**
```bash
git tag -a "1.2.0" -m "feat: add user authentication"
```
**Multi-line example (recommended):**
```bash
git tag -a "1.2.1" \
-m "fix: resolve bluetooth connection timeout" \
-m "" \
-m "- Increase connection timeout to 30s" \
-m "- Add retry mechanism for failed connections" \
-m "- Improve error messages"
```
**Monorepo example:**
```bash
git tag -a "android-1.2.1" \
-m "fix(android): resolve bluetooth connection timeout" \
-m "" \
-m "- Increase connection timeout to 30s" \
-m "- Add retry mechanism for failed connections"
```
### Tag Operations
**Create annotated tag:**
```bash
git tag -a "<tag-name>" -m "<message>"
```
**Push single tag:**
```bash
git push origin <tag-name>
```
**Push all tags:**
```bash
git push --tags
# or
git push origin --tags
```
**List recent tags:**
```bash
git tag --list | sort -V | tail -5
```
**Delete local tag:**
```bash
git tag -d <tag-name>
```
**Delete remote tag:**
```bash
git push origin --delete <tag-name>
# or
git push origin :refs/tags/<tag-name>
```
## Common Git Operations
### Check File Changes
**View changed files (working directory):**
```bash
git status
```
**View unstaged changes:**
```bash
git diff
```
**View staged changes:**
```bash
git diff --cached
# or
git diff --staged
```
**List changed files only:**
```bash
git diff --name-only
git diff --cached --name-only
```
**View specific file changes:**
```bash
git diff <file-path>
git diff --cached <file-path>
```
### Staging and Committing
**Add files to staging area:**
```bash
git add <file>
git add .
git add -A
```
**Check what's staged:**
```bash
git diff --cached --name-only
```
**Commit with message:**
```bash
# Single line
git commit -m "feat: add new feature"
# Multi-line (macOS/Linux)
git commit -m "$(cat <<'EOF'
feat: add new feature
- Detail 1
- Detail 2
EOF
)"
# Multi-line (Windows - use multiple -m flags)
git commit -m "feat: add new feature" -m "- Detail 1" -m "- Detail 2"
```
**Commit and tag in workflow:**
```bash
# 1. Check staging area
git diff --cached --name-only
# 2. Commit changes
git commit -m "feat: add user authentication"
# 3. Create tag
git tag -a "1.2.0" -m "feat: add user authentication"
# 4. Push both commit and tag
git push origin main
git push origin 1.2.0
```
### Pushing Changes
**Push current branch:**
```bash
git push origin $(git branch --show-current)
# or
git push origin main
```
**Push with upstream tracking:**
```bash
git push -u origin <branch-name>
```
**Push all tags:**
```bash
git push --tags
# or
git push origin --tags
```
**Push specific tag:**
```bash
git push origin <tag-name>
```
**Push commit and tag together:**
```bash
git push origin main && git push origin <tag-name>
```
### Branch Operations
**View current branch:**
```bash
git branch --show-current
```
**List all branches:**
```bash
git branch -a
```
**Create new branch:**
```bash
git branch <branch-name>
git checkout -b <branch-name>
# or (modern)
git switch -c <branch-name>
```
**Switch branch:**
```bash
git checkout <branch-name>
# or (modern)
git switch <branch-name>
```
**Delete branch:**
```bash
git branch -d <branch-name>
git branch -D <branch-name> # force delete
```
### History and Logs
**View commit history:**
```bash
git log --oneline -10
git log --graph --oneline --all
```
**View recent tags:**
```bash
git tag --list | sort -V | tail -5
```
**View commit details:**
```bash
git show <commit-hash>
git show <tag-name>
```
**Search commit history:**
```bash
git log --grep="<pattern>"
git log --author="<name>"
```
## Workflow Best Practices
### Standard Commit Workflow
1. **Check staging area:**
```bash
git diff --cached --name-only
```
- If empty, add files first: `git add .`
2. **Collect information (in parallel):**
```bash
git status
git diff --cached
git log --oneline -10
git tag --list | sort -V | tail -5
```
3. **Determine repository type:**
- Check `AGENTS.md` for monorepo indicator
- Analyze changed file paths for subproject scope
4. **Auto-detect project type:**
- Read `AGENTS.md` for version rules
- Scan for version files (package.json, build.gradle, etc.)
- Determine if version update is needed
5. **Generate commit message:**
- Analyze changes
- Follow Conventional Commits format
- Include scope for monorepo single-project changes
6. **Update version number (if needed):**
- Calculate new version based on change type
- Update version file
- Add version file to staging: `git add <version-file>`
- Verify: `git diff --cached --name-only`
7. **Commit changes:**
```bash
git commit -m "<message>"
```
8. **Create tag (if version updated):**
```bash
# Polyrepo
git tag -a "<version>" -m "<message>"
# Monorepo
git tag -a "<subproject>-<version>" -m "<message>"
```
9. **Push to remote:**
```bash
git push origin main
git push origin <tag-name> # if tag created
```
### Sync Configuration Workflow
**Pull latest config changes:**
```bash
cd ~/.config/opencode
git status # check for local changes
git pull origin main
git log --oneline -5 # view updates
```
**Push config changes:**
```bash
cd ~/.config/opencode
git status # check changes
git add command/ skill/ opencode.json
git commit -m "feat: add new git skill"
git push origin main
```
## Platform-Specific Considerations
### macOS/Linux
- **Commit language**: Use Chinese (中文)
- **Multi-line commits**: Use heredoc with `cat <<'EOF'`
- **Encoding**: UTF-8 without BOM (default)
### Windows
- **Commit language**: Use English only (Cursor Shell encoding issue)
- **Multi-line commits**: Use multiple `-m` flags
- **Prohibited methods**:
- No Chinese commit messages
- No `Out-File -Encoding utf8` (adds BOM)
- No PowerShell here-strings `@"..."@`
- No Write tool for temp files (encoding issues)
## Error Prevention
1. **Always check staging area first**: Don't commit empty staging area
2. **Verify version file is staged**: After updating version, confirm with `git diff --cached --name-only`
3. **No --amend after push**: Never amend commits that are already pushed
4. **Tag naming conflicts**: Check existing tags before creating new ones
5. **Branch protection**: Never force push to main/master without explicit user request
6. **Sensitive data**: Never commit secrets, API keys, or credentials
## Integration with CI/CD
- **Tag annotations**: Used as Release notes
- **Version consistency**: Git tag must match version file
- **Automated releases**: Tags trigger CI/CD pipelines
- **Semantic versioning**: CI/CD determines release type from version bump
## Quick Reference
**Check status:**
```bash
git status
git diff --cached --name-only
```
**Commit with tag:**
```bash
git commit -m "feat: add feature"
git tag -a "1.2.0" -m "feat: add feature"
git push origin main && git push origin 1.2.0
```
**Push all tags:**
```bash
git push --tags
```
**View recent history:**
```bash
git log --oneline -10
git tag --list | sort -V | tail -5
```
**View changes:**
```bash
git diff # unstaged changes
git diff --cached # staged changes
git diff main..feature # compare branches
```

View File

@@ -0,0 +1,663 @@
# Git Quick Reference
Quick reference guide for common Git operations.
## File Changes and Status
### View Changed Files
```bash
# Show working directory status
git status
# Show short status
git status -s
# List changed files only (unstaged)
git diff --name-only
# List changed files only (staged)
git diff --cached --name-only
# or
git diff --staged --name-only
# Show file change statistics
git diff --stat
git diff --cached --stat
```
### View Detailed Changes
```bash
# View unstaged changes
git diff
# View staged changes
git diff --cached
# or
git diff --staged
# View specific file changes
git diff <file-path>
git diff --cached <file-path>
# View changes between commits
git diff <commit1>..<commit2>
git diff HEAD~1..HEAD
# View changes between branches
git diff main..feature-branch
```
## Staging and Committing
### Add Files to Staging
```bash
# Add specific file
git add <file-path>
# Add all files in directory
git add .
# Add all files in repository
git add -A
# Add files interactively
git add -p
# Add only modified files (not new files)
git add -u
```
### Check Staging Area
```bash
# List files in staging area
git diff --cached --name-only
# Show detailed staged changes
git diff --cached
```
### Commit Changes
```bash
# Simple commit
git commit -m "feat: add user authentication"
# Multi-line commit (macOS/Linux)
git commit -m "$(cat <<'EOF'
feat: add user authentication
- Add OAuth2 support
- Implement JWT tokens
- Add login/logout endpoints
EOF
)"
# Multi-line commit (Windows)
git commit -m "feat: add user authentication" \
-m "" \
-m "- Add OAuth2 support" \
-m "- Implement JWT tokens" \
-m "- Add login/logout endpoints"
# Commit with automatic staging
git commit -am "fix: resolve issue"
# Amend last commit (before push only!)
git commit --amend -m "new message"
```
## Tag Management
### Create Tags
```bash
# Create annotated tag
git tag -a "1.2.0" -m "feat: add new feature"
# Create lightweight tag
git tag "1.2.0"
# Create tag with multi-line message
git tag -a "1.2.1" \
-m "fix: resolve connection issue" \
-m "" \
-m "- Increase timeout to 30s" \
-m "- Add retry mechanism"
# Create tag for specific commit
git tag -a "1.2.0" <commit-hash> -m "message"
# Monorepo tag
git tag -a "ios-1.2.0" -m "feat(ios): add feature"
```
### List Tags
```bash
# List all tags
git tag
# List tags with pattern
git tag -l "v1.*"
# List recent tags (sorted)
git tag --list | sort -V | tail -5
# Show tag details
git show <tag-name>
```
### Push Tags
```bash
# Push single tag
git push origin <tag-name>
# Push all tags
git push --tags
# or
git push origin --tags
# Push commit and tag together
git push origin main && git push origin 1.2.0
```
### Delete Tags
```bash
# Delete local tag
git tag -d <tag-name>
# Delete remote tag
git push origin --delete <tag-name>
# or
git push origin :refs/tags/<tag-name>
# Delete multiple tags
git tag -d tag1 tag2 tag3
```
## Branch Operations
### View Branches
```bash
# Show current branch
git branch --show-current
# List local branches
git branch
# List all branches (local + remote)
git branch -a
# List remote branches only
git branch -r
# Show branch with last commit
git branch -v
```
### Create and Switch Branches
```bash
# Create new branch
git branch <branch-name>
# Create and switch to new branch (old way)
git checkout -b <branch-name>
# Create and switch to new branch (modern)
git switch -c <branch-name>
# Switch to existing branch (old way)
git checkout <branch-name>
# Switch to existing branch (modern)
git switch <branch-name>
# Switch to previous branch
git switch -
```
### Delete Branches
```bash
# Delete local branch (safe)
git branch -d <branch-name>
# Delete local branch (force)
git branch -D <branch-name>
# Delete remote branch
git push origin --delete <branch-name>
# or
git push origin :<branch-name>
```
## Pushing and Pulling
### Push Changes
```bash
# Push current branch
git push
# Push to specific remote and branch
git push origin main
# Push current branch to remote
git push origin $(git branch --show-current)
# Push with upstream tracking
git push -u origin <branch-name>
# Push all branches
git push --all
# Push all tags
git push --tags
# Force push (dangerous!)
git push --force
# Better: force push with lease
git push --force-with-lease
```
### Pull Changes
```bash
# Pull from tracked remote
git pull
# Pull from specific remote and branch
git pull origin main
# Pull with rebase
git pull --rebase
# Pull and prune deleted remote branches
git pull --prune
```
### Fetch Changes
```bash
# Fetch from all remotes
git fetch
# Fetch from specific remote
git fetch origin
# Fetch and prune deleted remote branches
git fetch --prune
# Fetch all branches and tags
git fetch --all --tags
```
## History and Logs
### View Commit History
```bash
# View recent commits
git log
# View compact history
git log --oneline
# View recent 10 commits
git log --oneline -10
# View history with graph
git log --graph --oneline --all
# View history with stats
git log --stat
# View history with patches
git log -p
```
### Search History
```bash
# Search commits by message
git log --grep="feature"
# Search by author
git log --author="John"
# Search by date
git log --since="2024-01-01"
git log --after="2 weeks ago"
git log --before="yesterday"
# Search by file
git log -- <file-path>
# Search code changes
git log -S "function_name"
```
### View Commit Details
```bash
# Show specific commit
git show <commit-hash>
# Show specific tag
git show <tag-name>
# Show HEAD commit
git show HEAD
# Show previous commit
git show HEAD~1
git show HEAD^
```
## Undoing Changes
### Discard Changes
```bash
# Discard unstaged changes in file
git checkout -- <file-path>
# or (modern)
git restore <file-path>
# Discard all unstaged changes
git checkout -- .
# or (modern)
git restore .
# Unstage file (keep changes)
git reset HEAD <file-path>
# or (modern)
git restore --staged <file-path>
# Unstage all files
git reset HEAD
# or (modern)
git restore --staged .
```
### Reset Commits
```bash
# Undo last commit, keep changes staged
git reset --soft HEAD~1
# Undo last commit, keep changes unstaged
git reset HEAD~1
# or
git reset --mixed HEAD~1
# Undo last commit, discard changes (dangerous!)
git reset --hard HEAD~1
# Reset to specific commit
git reset --hard <commit-hash>
```
### Revert Commits
```bash
# Create new commit that undoes a commit
git revert <commit-hash>
# Revert without committing
git revert -n <commit-hash>
# Revert multiple commits
git revert <commit1>..<commit2>
```
## Stash Operations
### Save Changes
```bash
# Stash current changes
git stash
# Stash with message
git stash save "work in progress"
# Stash including untracked files
git stash -u
# Stash including untracked and ignored files
git stash -a
```
### Apply Stash
```bash
# Apply most recent stash
git stash apply
# Apply and remove from stash list
git stash pop
# Apply specific stash
git stash apply stash@{2}
```
### Manage Stash
```bash
# List all stashes
git stash list
# Show stash changes
git stash show
git stash show -p
# Drop specific stash
git stash drop stash@{1}
# Clear all stashes
git stash clear
```
## Remote Operations
### View Remotes
```bash
# List remotes
git remote
# List remotes with URLs
git remote -v
# Show remote details
git remote show origin
```
### Manage Remotes
```bash
# Add remote
git remote add <name> <url>
# Remove remote
git remote remove <name>
# Rename remote
git remote rename <old-name> <new-name>
# Change remote URL
git remote set-url <name> <new-url>
```
## Configuration
### View Configuration
```bash
# View all config
git config --list
# View global config
git config --global --list
# View local config
git config --local --list
# View specific config
git config user.name
git config user.email
```
### Set Configuration
```bash
# Set user name
git config --global user.name "Your Name"
# Set user email
git config --global user.email "your.email@example.com"
# Set default branch name
git config --global init.defaultBranch main
# Set default editor
git config --global core.editor "code --wait"
# Set credential helper
git config --global credential.helper store
```
## Workflow Examples
### Standard Commit and Tag Workflow
```bash
# 1. Check status
git status
git diff --cached --name-only
# 2. Stage changes
git add .
# 3. Commit
git commit -m "feat: add user authentication"
# 4. Create tag
git tag -a "1.2.0" -m "feat: add user authentication"
# 5. Push commit and tag
git push origin main
git push origin 1.2.0
```
### Complete Staging to Push Workflow
```bash
# Check what files changed
git status
# View changes
git diff
# Stage specific files
git add src/auth.js src/api.js
# Verify staging
git diff --cached --name-only
# Commit with message
git commit -m "feat: implement OAuth2 authentication"
# Push to remote
git push origin main
```
### Push All Tags Workflow
```bash
# List local tags
git tag
# View recent tags
git tag --list | sort -V | tail -5
# Push all tags to remote
git push --tags
# Verify tags on remote
git ls-remote --tags origin
```
### Quick Status Check
```bash
# Full status
git status
# Changed files only
git diff --name-only
git diff --cached --name-only
# Recent commits and tags
git log --oneline -5
git tag --list | sort -V | tail -5
# Current branch
git branch --show-current
```
## Tips and Tricks
### Aliases
Add to `~/.gitconfig`:
```ini
[alias]
st = status
co = checkout
br = branch
ci = commit
unstage = restore --staged
last = log -1 HEAD
lg = log --graph --oneline --all
tags = tag -l --sort=-v:refname
```
Usage:
```bash
git st
git co main
git lg
```
### Useful One-Liners
```bash
# Delete all merged branches
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
# View file in specific commit
git show <commit>:<file-path>
# Count commits by author
git shortlog -sn
# Find when a line was changed
git blame <file-path>
# Show what changed in each commit for a file
git log -p <file-path>
# List files in a commit
git diff-tree --no-commit-id --name-only -r <commit>
```

View File

@@ -1,417 +0,0 @@
---
name: gitea-runner
description: Gitea Act Runner configuration guide for macOS ARM64 with host mode, cache optimization, and multi-runner setup
---
# Gitea Act Runner Configuration Skill
Complete guide for configuring and deploying Gitea Act Runner, optimized for macOS ARM64 (Apple Silicon) host mode.
## Overview
Gitea Act Runner is the CI/CD executor for Gitea Actions, compatible with GitHub Actions workflow syntax.
### Execution Modes
| Mode | Environment | Use Case | Android SDK |
|------|-------------|----------|-------------|
| **Host Mode** | Native macOS/Linux | Android/iOS builds, native toolchains | macOS ARM64 supported |
| Docker Mode | Linux containers | Cross-platform builds | Linux ARM64 NOT supported |
**Recommendation**: Use **host mode** for macOS ARM64 runners to leverage native Android SDK support.
## Prerequisites
### 1. Install act_runner
```bash
# Using Homebrew (recommended)
brew install act_runner
# Or manual download
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
```
### 2. Install Development Tools
```bash
# Go (for Go backend builds)
brew install go
# Node.js (for frontend/miniprogram builds)
brew install node@22
# pnpm (package manager)
npm install -g pnpm
# JDK 17 (for Android builds)
brew install openjdk@17
# Docker (for container builds)
# Install Docker Desktop from https://docker.com
```
### 3. Install Android SDK (for Android builds)
```bash
# Using Homebrew
brew install --cask android-commandlinetools
# Or manual installation
mkdir -p ~/android-sdk/cmdline-tools
cd ~/android-sdk/cmdline-tools
curl -sL https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip -o cmdline-tools.zip
unzip cmdline-tools.zip
mv cmdline-tools latest
rm cmdline-tools.zip
# Accept licenses and install components
yes | sdkmanager --licenses
sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.0.0"
```
### 4. Configure Environment Variables
Add to `~/.zshrc` or `~/.bashrc`:
```bash
# Go
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# Java
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
export PATH=$PATH:$JAVA_HOME/bin
# Android SDK
export ANDROID_HOME=~/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
```
### 5. Verify Environment
```bash
# Verify all tools
go version # Go 1.23+
node --version # v22.x
pnpm --version # Latest
java -version # 17+
echo $ANDROID_HOME # SDK path
docker --version # Latest
act_runner --version
```
## Runner Configuration
### Host Mode Configuration Template
Create `act_runner_host.yaml`:
```yaml
log:
level: info
runner:
file: /path/to/work/dir/.runner
capacity: 2 # Concurrent jobs
timeout: 3h # Job timeout
shutdown_timeout: 30s
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
# Labels reflect actual system info for precise workflow matching
labels:
- "self-hosted:host" # Self-hosted runner
- "macOS:host" # Operating system
- "ARM64:host" # Architecture
- "darwin-arm64:host" # Combined label (recommended for matching)
cache:
enabled: true
dir: "/path/to/work/dir/cache"
host: "127.0.0.1" # Local only (use 0.0.0.0 for multi-runner)
port: 9000
host:
workdir_parent: "/path/to/work/dir/workspace"
```
### Label Design Guidelines
| Label | Meaning | Usage |
|-------|---------|-------|
| `self-hosted` | Self-hosted runner | Distinguish from Gitea-hosted runners |
| `macOS` | Operating system | Friendly name for Darwin |
| `ARM64` | CPU architecture | Apple Silicon (M1/M2/M3/M4) |
| `darwin-arm64` | Combined label | Most precise matching |
### Workflow Matching Examples
```yaml
jobs:
build:
# Method 1: Combined label (recommended, most precise)
runs-on: darwin-arm64
# Method 2: Label array (matches multiple conditions)
# runs-on: [self-hosted, macOS, ARM64]
# Method 3: OS only
# runs-on: macOS
```
## Registration & Startup
### 1. Get Registration Token
```bash
# Organization level (global runner, recommended)
curl -H "Authorization: token YOUR_GITEA_TOKEN" \
"https://your-gitea.com/api/v1/orgs/ORG_NAME/actions/runners/registration-token"
# Or repository level
curl -H "Authorization: token YOUR_GITEA_TOKEN" \
"https://your-gitea.com/api/v1/repos/OWNER/REPO/actions/runners/registration-token"
```
### 2. Register Runner
```bash
act_runner register \
--config act_runner_host.yaml \
--instance https://your-gitea.com/ \
--token YOUR_REGISTRATION_TOKEN \
--name "your-runner-name" \
--labels "self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host" \
--no-interactive
```
### 3. Start Runner
```bash
# Foreground (for debugging)
act_runner daemon --config act_runner_host.yaml
# Background
nohup act_runner daemon --config act_runner_host.yaml > runner.log 2>&1 &
# Using brew services (recommended for persistence)
brew services start act_runner
```
## Multi-Runner Cache Sharing
### Option A: Master-Slave Mode (Recommended for 2-3 runners)
**Primary Runner (cache server)**:
```yaml
cache:
enabled: true
dir: "/Users/voson/work/gitea/cache"
host: "0.0.0.0" # Listen on all interfaces
port: 9000
```
**Secondary Runner (cache client)**:
```yaml
cache:
enabled: true
server: "http://192.168.0.103:9000" # Primary runner IP
dir: "/Users/user/work/gitea/cache" # Local fallback
host: "192.168.0.104" # This runner's IP
port: 9000
```
### Option B: NFS Shared Storage (Enterprise)
**1. Setup NFS server on primary runner:**
```bash
# /etc/exports
/Users/voson/work/gitea/cache -alldirs -mapall=$(id -u):$(id -g) 192.168.0.0/24
sudo nfsd restart
```
**2. Mount on secondary runner:**
```bash
sudo mkdir -p /mnt/runner-cache
sudo mount -t nfs 192.168.0.103:/Users/voson/work/gitea/cache /mnt/runner-cache
```
### Option C: Independent Cache (Default)
Each runner maintains its own cache. First build downloads dependencies, subsequent builds use local cache.
## Cache Management
### Host Mode Cache Locations
| Cache Type | Location | Behavior |
|------------|----------|----------|
| Runner cache service | `config.cache.dir` | Managed by act_runner |
| Gradle | `~/.gradle/` | Persistent across builds |
| npm/pnpm | `~/.npm/`, `~/.pnpm-store/` | Persistent across builds |
| Go modules | `~/go/pkg/mod/` | Persistent across builds |
### Cache Cleanup Script
Create `cleanup-cache.sh`:
```bash
#!/bin/bash
set -e
echo "Cleaning up caches..."
# 1. Runner cache (older than 7 days)
find /path/to/cache/cache -type f -mtime +7 -delete 2>/dev/null || true
# 2. Gradle cache (older than 30 days)
find ~/.gradle/caches -type f -mtime +30 -delete 2>/dev/null || true
find ~/.gradle/caches -type d -empty -delete 2>/dev/null || true
# 3. npm cache verification
npm cache verify
# 4. Workspace cleanup
find /path/to/workspace -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true
echo "Cleanup complete!"
echo "Runner cache: $(du -sh /path/to/cache/ | awk '{print $1}')"
echo "Gradle cache: $(du -sh ~/.gradle/ | awk '{print $1}')"
```
### Schedule Cleanup
```bash
# Add to crontab for weekly cleanup
crontab -e
# Add: 0 3 * * 0 /path/to/cleanup-cache.sh >> /path/to/cleanup.log 2>&1
```
## Management Commands
```bash
# Check runner status
ps aux | grep act_runner
# View logs
tail -f /path/to/runner.log
# Stop runner
pkill -f "act_runner daemon"
# Re-register (stop first, delete .runner file)
rm /path/to/.runner
act_runner register --config act_runner_host.yaml ...
# Check Gitea connection
curl -s https://your-gitea.com/api/v1/version
```
## Troubleshooting
### 1. Android SDK Not Found
```bash
# Verify ANDROID_HOME
echo $ANDROID_HOME
ls $ANDROID_HOME
# Check if runner can access SDK
# Ensure runner runs as the same user who installed SDK
```
### 2. JDK Version Error
Android Gradle Plugin 8.x requires JDK 17+:
```bash
java -version
# Should show: openjdk version "17.x.x"
# If wrong version, update JAVA_HOME
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
```
### 3. Permission Issues
```bash
# Ensure runner user owns work directories
chown -R $(whoami) /path/to/work/dir
chmod -R 755 /path/to/work/dir
```
### 4. Label Mismatch
```bash
# Check registered labels
cat /path/to/.runner | jq '.labels'
# Ensure workflow runs-on matches
# Workflow: runs-on: darwin-arm64
# Runner: "darwin-arm64:host" label
```
### 5. Cache Service Port Conflict
```bash
# Check if port 9000 is in use
lsof -i :9000
# Use different port if needed
# In config: port: 9001
```
## Docker Mode Configuration (Alternative)
For container-based builds:
```yaml
log:
level: info
runner:
file: /path/to/.runner
capacity: 2
timeout: 3h
labels:
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
- "ubuntu-22.04:docker://catthehacker/ubuntu:act-latest"
cache:
enabled: true
dir: "/path/to/cache"
host: "192.168.0.103" # Host IP (not 127.0.0.1 for containers)
port: 9000
container:
options: "--platform=linux/amd64" # For ARM64 host running x86 images
network: "host"
```
## Quick Reference
| Task | Command |
|------|---------|
| Install runner | `brew install act_runner` |
| Register | `act_runner register --config ... --instance ... --token ...` |
| Start | `act_runner daemon --config act_runner_host.yaml` |
| Stop | `pkill -f "act_runner daemon"` |
| Check status | `ps aux \| grep act_runner` |
| View logs | `tail -f runner.log` |
| Re-register | `rm .runner && act_runner register ...` |
## Related Resources
- [Gitea Act Runner Documentation](https://docs.gitea.com/usage/actions/act-runner)
- [Android SDK Command Line Tools](https://developer.android.com/studio/command-line)
- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
## Version
- **Skill Version**: 1.0
- **Last Updated**: 2026-01-12
- **Compatibility**: act_runner 0.2.13+, macOS ARM64

View File

@@ -1,383 +0,0 @@
---
name: gitea-workflow
description: Gitea Actions Workflow foundation and templates for various project types with CI/CD best practices
---
# Gitea Actions Workflow Skill
Gitea Actions workflow 基础知识和项目模板指南,兼容 GitHub Actions 语法。
## 概述
Gitea Actions workflows 定义在 `.gitea/workflows/*.yml` 文件中。本 skill 提供:
- Workflow 基础结构和通用组件
- 各项目类型的骨架模板(用户按需填充具体构建逻辑)
## 项目类型模板
| 类型 | 文档 | 适用场景 |
|------|------|---------|
| Go 后端 | [go-backend.md](./go-backend.md) | API 服务、微服务、CLI 工具 |
| Node.js 前端 | [nodejs-frontend.md](./nodejs-frontend.md) | React/Vue/Vite/Next.js |
| Android 应用 | [android-app.md](./android-app.md) | Kotlin/Java/Jetpack Compose |
| 微信小程序 | [wechat-miniprogram.md](./wechat-miniprogram.md) | 微信小程序 CI/CD |
---
## Workflow 基础结构
### 文件位置
```
project/
├── .gitea/
│ └── workflows/
│ ├── backend.yml
│ ├── frontend.yml
│ └── ...
└── ...
```
### 骨架模板
```yaml
name: Service Name - Build & Publish
on:
push:
paths:
- 'service-dir/**' # 仅相关目录变更时触发
- '.gitea/workflows/this-workflow.yml'
tags:
- 'service-prefix-*' # Tag 触发 Release
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 取消同分支旧的运行
env:
SERVICE_PREFIX: service-name # 服务标识
jobs:
build:
name: Build
runs-on: darwin-arm64 # Runner 标签
permissions:
contents: read
packages: write
outputs:
version: ${{ steps.vars.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # 完整历史(用于 git describe
# ... 构建步骤
release:
name: Create Release
runs-on: darwin-arm64
needs: build
if: startsWith(github.ref, 'refs/tags/service-prefix-')
steps:
# ... Release 步骤
```
---
## 触发条件
### 常用触发模式
```yaml
on:
# 分支推送
push:
branches: [main, develop]
# 路径过滤(推荐:仅相关文件变更时触发)
push:
paths:
- 'src/**'
- '*.yml'
# Tag 推送(用于 Release
push:
tags:
- 'v*'
- 'service-*'
# Pull Request
pull_request:
branches: [main]
# 手动触发
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'staging'
# 定时触发
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点
```
### 并发控制
```yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
```
---
## 通用组件
### Checkout
```yaml
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # 完整历史,用于 git describe 获取版本
# fetch-depth: 1 # 仅最新提交,加快速度
```
### 变量设置
```yaml
- name: Set variables
id: vars
run: |
git_tag=$(git describe --tags --abbrev=0 --always)
registry=$(echo ${{ github.server_url }} | cut -d '/' -f 3)
# 写入环境变量(当前 job 可用)
{
echo "git_tag=${git_tag}"
echo "registry=${registry}"
} >> $GITHUB_ENV
# 写入输出(其他 job 可用)
echo "version=${git_tag}" >> $GITHUB_OUTPUT
```
### Cache Action
```yaml
- name: Cache dependencies
uses: https://github.com/actions/cache@v3
with:
path: |
~/.cache/directory
./node_modules
key: cache-name-${{ hashFiles('**/lockfile') }}
restore-keys: cache-name-
```
**各语言缓存路径**
| 语言 | 缓存路径 | Key 文件 |
|------|---------|----------|
| Go | `~/go/pkg/mod`, `~/.cache/go-build` | `go.mod`, `go.sum` |
| Node.js (pnpm) | `~/.pnpm-store`, `node_modules` | `pnpm-lock.yaml` |
| Node.js (npm) | `~/.npm`, `node_modules` | `package-lock.json` |
| Gradle | `~/.gradle/caches`, `~/.gradle/wrapper` | `*.gradle*`, `gradle-wrapper.properties` |
### Artifact 上传/下载
```yaml
# 上传
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: build-artifact
path: dist/
# 下载(另一个 job
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: build-artifact
path: dist/
```
### Docker 构建推送
```yaml
- name: Docker - Login
uses: docker/login-action@v3
with:
registry: ${{ env.registry }}
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Docker - Setup Buildx
uses: docker/setup-buildx-action@v3
- name: Docker - Build & Push
uses: docker/build-push-action@v6
with:
context: ./service-dir
file: ./service-dir/Dockerfile
push: true
platforms: linux/amd64
tags: |
${{ env.registry }}/${{ github.repository_owner }}/image:latest
${{ env.registry }}/${{ github.repository_owner }}/image:${{ env.git_tag }}
cache-from: type=registry,ref=image:buildcache
cache-to: type=registry,ref=image:buildcache,mode=max
```
### 通知 Webhook
```yaml
- name: Notify
if: always()
continue-on-error: true
env:
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
run: |
status="${{ job.status }}"
[ "$status" = "success" ] && text="Build Success" || text="Build Failed"
curl -s -H "Content-Type: application/json" -X POST \
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"${{ env.SERVICE_PREFIX }} ${text}\"}}" \
"$WEBHOOK_URL"
```
### Release 创建Gitea API
```yaml
- name: Create Release
env:
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
git_tag=$(git describe --tags --abbrev=0)
api_url="${{ github.server_url }}/api/v1"
repo="${{ github.repository }}"
# 创建 Release
release_id=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
"${api_url}/repos/${repo}/releases" | jq -r '.id')
# 上传附件
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-F "attachment=@dist/artifact.zip" \
"${api_url}/repos/${repo}/releases/${release_id}/assets"
```
---
## Secrets 配置
### 通用 Secrets
| Secret | 用途 | 适用项目 |
|--------|------|---------|
| `REGISTRY_PASSWORD` | Docker Registry 密码 | 需要 Docker 发布的项目 |
| `RELEASE_TOKEN` | Gitea API 令牌 | 需要创建 Release 的项目 |
### 项目特定 Secrets
参考各项目类型子文档。
### 安全最佳实践
1. **不要在日志中打印 secrets**
2. **使用 `vars.` 存储非敏感变量**如用户名、URL
3. **secrets 仅用于敏感信息**(如密码、密钥)
4. **定期轮换密钥**
---
## 最佳实践
### 1. 路径过滤
仅相关文件变更时触发,避免无关构建:
```yaml
on:
push:
paths:
- 'backend/**'
- '.gitea/workflows/backend.yml'
```
### 2. Tag 命名规范
使用前缀区分不同服务:
```bash
git tag server-1.0.0 && git push origin server-1.0.0
git tag web-1.0.0 && git push origin web-1.0.0
git tag android-1.0.0 && git push origin android-1.0.0
```
### 3. Job 输出传递
```yaml
jobs:
build:
outputs:
version: ${{ steps.vars.outputs.version }}
deploy:
needs: build
env:
VERSION: ${{ needs.build.outputs.version }}
```
### 4. 条件执行
```yaml
# 仅 Tag 推送时执行
if: startsWith(github.ref, 'refs/tags/')
# 仅主分支执行
if: github.ref == 'refs/heads/main'
# 始终执行(用于通知)
if: always()
```
---
## 快速参考
| 任务 | 命令/语法 |
|------|----------|
| 获取 git tag | `git describe --tags --abbrev=0 --always` |
| 提取 registry | `echo ${{ github.server_url }} \| cut -d '/' -f 3` |
| 设置环境变量 | `echo "KEY=value" >> $GITHUB_ENV` |
| 设置输出 | `echo "key=value" >> $GITHUB_OUTPUT` |
| 计算哈希 | `sha256sum file1 file2 \| sha256sum \| head -c 16` |
---
## 使用方式
1. **选择项目类型**:参考上方索引表,选择对应的子文档
2. **复制骨架模板**:将模板复制到 `.gitea/workflows/`
3. **填充构建逻辑**:根据项目需求填充 `# 用户自定义` 部分
4. **配置 Secrets**:在 Gitea 中配置所需的 Secrets
5. **推送触发**:推送代码或 Tag 触发 workflow
---
## 版本
- **Skill Version**: 2.0
- **Last Updated**: 2026-01-12
- **Structure**: 主文档 + 4 个项目类型子文档

343
skill/gitea/SKILL.md Normal file
View File

@@ -0,0 +1,343 @@
---
name: gitea
description: Comprehensive Gitea management tool for creating runners, workflows, and repositories with interactive setup
---
# Gitea Management Skill
完整的 Gitea 管理工具,提供 Runner、Workflow、仓库的创建和管理功能。
## 功能概览
| 功能模块 | 文档 | 说明 |
|---------|------|------|
| 环境配置 | [setup-guide.md](./setup-guide.md) | 首次使用引导,配置 Gitea URL 和 Token |
| Runner 管理 | [runner-management.md](./runner-management.md) | 创建、注册、管理 Gitea Act Runner |
| Workflow 生成 | [workflow-generator.md](./workflow-generator.md) | 根据项目类型生成 CI/CD workflow |
| 仓库操作 | [repository-operations.md](./repository-operations.md) | 创建和配置 Gitea 仓库 |
| API 参考 | [api-reference.md](./api-reference.md) | Gitea API 常用接口 |
| 故障排查 | [troubleshooting.md](./troubleshooting.md) | 常见问题解决方案 |
## 触发条件
当用户提到以下关键词时自动加载此 skill
- "gitea"、"runner"、"workflow"
- "创建 runner"、"配置 runner"、"注册 runner"
- "生成 workflow"、"CI/CD"
- "创建仓库"、"gitea 仓库"
- "gitea 配置"、"gitea token"
## 首次使用
**重要:** 首次使用前需要配置 Gitea 连接信息。
- 配置文件:`~/.config/gitea/config.env`
- 如果文件不存在,自动启动交互式配置向导
- 使用 `/gitea-config` 命令查看当前配置
- 使用 `/gitea-reset` 命令重置配置
**新增Actions Variables 自动注册**
- 初始化时会自动将配置注册为用户级 variables
- `GITEA_USERNAME``USERNAME` variable
- `GITEA_WEBHOOK_URL``WEBHOOK_URL` variable
- 可在所有个人仓库的 Actions workflow 中使用
- 使用方式:`${{ vars.USERNAME }}``${{ vars.WEBHOOK_URL }}`
**重要**Gitea 不允许 variable 名称以 `GITEA_``GITHUB_` 开头
详见:[环境配置指南](./setup-guide.md)
## 快速命令
| 命令 | 说明 |
|------|------|
| `/gitea-config` | 查看当前 Gitea 配置和 Runner 状态 |
| `/gitea-reset` | 重置 Gitea 配置(交互式向导) |
| `/gitea-switch-org` | 切换默认组织 |
| `/gitea-create-runner` | 创建并启动新 Runner默认 host 模式) |
| `/gitea-list-runners` | 列出所有 Runner 及其状态 |
| `/gitea-delete-runner` | 删除指定 Runner |
| `/gitea-list-variables` | 列出用户级 Variables |
| `/gitea-sync-variables` | 同步本地配置到 Gitea Variables |
| `/gitea-create-repo` | 创建新仓库 |
## 快速开始
### 1. 配置 Gitea 连接
首次使用时,系统会自动引导你完成配置:
```
请输入 Gitea 实例地址: https://git.digitevents.com
请输入 Personal Access Token: ****************
请输入默认组织名称(可选): ai
请输入 Gitea 用户名(用于 Actions: your_username
请输入 Gitea 密码: ********
请输入 Actions 通知 Webhook URL可选: https://...
✓ 配置已保存到: ~/.config/gitea/config.env
正在注册用户级 Variables...
✓ USERNAME 已创建 (来自 GITEA_USERNAME)
✓ WEBHOOK_URL 已创建
```
或使用命令:
```bash
/gitea-reset
```
### 2. 创建 Runner
```bash
/gitea-create-runner
```
输出示例:
```
检查 act_runner 安装状态...
✓ act_runner 已安装: act_runner version 0.2.13
✓ 已加载 Gitea 配置
URL: https://git.digitevents.com
生成 Runner 名称: runner-macbook-pro
检测系统环境...
✓ 系统信息
操作系统: Darwin (macOS)
架构: arm64 (ARM64)
✓ Runner Labels (Host Mode)
self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
[自动创建目录、生成配置、注册并启动]
✅ Runner 创建完成!
名称: runner-macbook-pro
级别: global
状态: 🟢 运行中
PID: 12345
```
**说明**
- 默认使用 Host Mode支持 Android SDK、iOS 构建等)
- 自动检查并安装 act_runner如未安装
- 自动检测系统环境并生成合适的 labels
- 优先创建全局 Runner需要管理员 Token
- 权限不足时自动降级到组织 Runner
- 自动后台启动
### 3. 生成 Workflow
```
用户: 为我的 Go 项目生成 workflow
AI: 检测到 Go 项目,服务目录: ./backend
是否需要构建 Docker 镜像?[Y/n]
[自动生成 .gitea/workflows/backend.yml]
```
### 4. 创建仓库
```
用户: /gitea-create-repo my-project
AI: [使用配置的 Gitea URL 和默认组织创建仓库]
✓ 仓库创建成功: ai/my-project
```
## 配置管理
### 查看配置
```bash
/gitea-config
```
输出示例:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
当前 Gitea 配置
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL: https://git.digitevents.com
默认组织: ai
Token 状态: ✓ 有效 (用户: your_username)
配置文件: ~/.config/gitea/config.env
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Runner 信息
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
已配置 Runner 数量: 2
Runner 目录: ~/.config/gitea/runners
```
### 列出 Runners
```bash
/gitea-list-runners
```
### 切换组织
```bash
/gitea-switch-org my-org
```
### 重置配置
```bash
/gitea-reset
```
## 配置文件结构
```
~/.config/gitea/
├── config.env # 主配置文件(含认证信息和 Webhook
├── runners/ # Runner 配置目录
│ ├── runner-macbook-pro/
│ │ ├── .runner # Runner 注册信息
│ │ ├── config.yaml # Runner 配置
│ │ ├── cache/ # Cache 目录
│ │ └── workspace/ # 工作目录
│ └── runner-mac-mini/
│ └── ...
└── .gitignore # 忽略敏感文件
```
**config.env 包含的配置项**
- `GITEA_URL`: Gitea 实例地址
- `GITEA_TOKEN`: Personal Access Token
- `GITEA_DEFAULT_ORG`: 默认组织
- `GITEA_USERNAME`: Gitea 用户名(自动注册为 `USERNAME` variable
- `GITEA_PASSWORD`: Gitea 密码(仅本地使用)
- `GITEA_WEBHOOK_URL`: Actions 通知 Webhook自动注册为 `WEBHOOK_URL` variable
## 使用流程
### 典型的 Gitea 项目设置流程
1. **初始化配置**(仅首次)
```bash
/gitea-reset
```
2. **创建仓库**
```bash
/gitea-create-repo myorg/myproject
```
3. **创建 Runner**(如果需要自托管 CI/CD
```bash
/gitea-create-runner
```
4. **生成 Workflow**
```
用户: 为这个项目生成 workflow
```
5. **推送代码并触发 CI/CD**
```bash
git push origin main
```
## Runner 管理
### 创建 Runner
使用命令快速创建:
```bash
/gitea-create-runner
```
特性:
- 自动检查并安装 act_runner
- 自动检测系统环境OS、架构
- 默认使用 Host Mode支持原生工具
- 自动生成配置并启动
- 优先创建全局 Runner
详见:[Runner 管理](./runner-management.md)
### 查看 Runner 状态
```bash
/gitea-list-runners
```
显示:
- 运行状态(运行中/已停止)
- PID
- 配置信息容量、超时、labels
- 启动命令
### 删除 Runner
```bash
/gitea-delete-runner runner-macbook-pro
```
会自动:
- 停止运行中的进程
- 可选从 Gitea 服务器注销
- 删除所有相关文件配置、cache、workspace
## Workflow 模板
支持以下项目类型的 workflow 模板:
| 类型 | 模板文档 | 适用场景 |
|------|---------|---------|
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
| 微信小程序 | [wechat-miniprogram.md](./workflow-templates/wechat-miniprogram.md) | 微信小程序 CI/CD |
AI 会自动:
- 检测项目类型
- 选择合适的模板
- 填充项目特定的变量(路径、服务名等)
- 生成完整的 workflow 文件
详见:[Workflow 生成器](./workflow-generator.md)
## API 调用
所有与 Gitea 服务器的交互都通过 API 完成,使用配置文件中的:
- `GITEA_URL`: Gitea 实例地址
- `GITEA_TOKEN`: Personal Access Token
详见:[API 参考](./api-reference.md)
## 安全性
- 配置文件权限:`600`(仅所有者可读写)
- Token 不会在日志中显示
- `.gitignore` 自动排除敏感文件
- 删除 runner 时可选择从服务器注销
## 故障排查
常见问题:
- 连接失败:检查 URL 和网络
- Token 无效:检查 Token 权限和有效期
- Runner 无法启动:检查端口占用和权限
- Workflow 无法触发:检查 labels 匹配
详见:[故障排查](./troubleshooting.md)
## 版本
- **Skill Version**: 1.0
- **Last Updated**: 2026-01-12
- **整合内容**: gitea-runner + gitea-workflow
- **新增功能**: 统一配置管理、Runner CRUD、智能 labels 检测
## 相关资源
- [Gitea 官方文档](https://docs.gitea.com/)
- [Gitea Actions 文档](https://docs.gitea.com/usage/actions/overview)
- [Gitea API 文档](https://docs.gitea.com/api/1.20/)
- [Act Runner 文档](https://docs.gitea.com/usage/actions/act-runner)

1083
skill/gitea/api-reference.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,693 @@
# Gitea 仓库操作
创建和管理 Gitea 仓库的完整指南。
## 概述
本文档介绍如何通过 Gitea API 创建和管理仓库,包括:
- 创建组织/用户仓库
- 初始化仓库结构
- 配置 Actions 设置
- 管理 Secrets 和 Variables
- 设置 Webhooks
## 创建仓库
### 使用命令创建
**快速创建**(使用默认组织):
```bash
/gitea-create-repo my-project
```
**指定 owner**
```bash
/create-gitea-repo ai/my-project
/create-gitea-repo username/my-project
```
**指定可见性**
```bash
/create-gitea-repo ai/my-project public
/create-gitea-repo ai/my-project private
```
### 使用自然语言
```
用户: 创建一个新的 gitea 仓库,名为 my-project
用户: 在 ai 组织下创建仓库 test-repo
用户: 创建公开仓库 open-source-project
```
AI 会自动:
1. 加载 Gitea 配置
2. 解析仓库名称和 owner
3. 调用 API 创建仓库
4. 提示是否添加为 Git remote
5. 显示仓库信息URLs 等)
### 创建流程详解
#### 步骤 1: 加载配置
```bash
config_file="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file" ]; then
echo "❌ Gitea 未配置,请运行 /gitea-reset"
exit 1
fi
source "$config_file"
```
#### 步骤 2: 解析输入
```bash
input="$1"
# 解析 owner/repo
if [[ "$input" =~ / ]]; then
owner=$(echo "$input" | cut -d'/' -f1)
repo=$(echo "$input" | cut -d'/' -f2)
else
# 使用默认组织或当前用户
if [ -z "$GITEA_DEFAULT_ORG" ]; then
# 获取当前用户
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
# 解析可见性
visibility="${2:-private}"
private_bool=$([ "$visibility" = "private" ] && echo "true" || echo "false")
```
#### 步骤 3: 验证仓库名
```bash
# 仓库名只能包含字母、数字、下划线、连字符和点
if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
echo "❌ 仓库名只能包含字母、数字、下划线、连字符和点"
exit 1
fi
```
#### 步骤 4: 调用 API 创建
```bash
echo "正在创建仓库: $owner/$repo ($visibility)"
# 尝试组织仓库
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')
# 如果 404可能是用户而非组织
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}
}" \
"${GITEA_URL}/api/v1/user/repos")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
fi
# 处理响应
case "$http_code" in
201)
echo "✓ 仓库创建成功"
;;
409)
echo "❌ 仓库已存在"
exit 1
;;
*)
echo "❌ 创建失败 (HTTP $http_code)"
echo "$body" | jq -r '.message // empty'
exit 1
;;
esac
```
#### 步骤 5: 提取仓库信息
```bash
html_url=$(echo "$body" | jq -r '.html_url')
clone_url=$(echo "$body" | jq -r '.clone_url')
ssh_url=$(echo "$body" | jq -r '.ssh_url')
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 ""
```
#### 步骤 6: 添加 Git Remote
```bash
read -p "是否将此仓库添加为 Git remote? [Y/n] " add_remote
if [[ ! "$add_remote" =~ ^[Nn]$ ]]; then
# 检查是否是 Git 仓库
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "当前目录不是 Git 仓库"
read -p "是否初始化 Git 仓库? [Y/n] " init_git
if [[ ! "$init_git" =~ ^[Nn]$ ]]; then
git init
echo "✓ Git 仓库已初始化"
else
exit 0
fi
fi
# 检查 origin 是否已存在
if git remote get-url origin >/dev/null 2>&1; then
existing_url=$(git remote get-url origin)
echo "⚠️ origin remote 已存在: $existing_url"
read -p "是否覆盖? [y/N] " overwrite
if [[ "$overwrite" =~ ^[Yy]$ ]]; then
git remote set-url origin "$clone_url"
echo "✓ origin remote 已更新"
fi
else
git remote add origin "$clone_url"
echo "✓ origin remote 已添加"
fi
# 显示 remote 信息
echo ""
echo "当前 remote:"
git remote -v
fi
```
## 仓库初始化
### 初始化基本结构
创建常见的仓库文件:
```bash
# README.md
cat > README.md << 'EOF'
# Project Name
项目描述
## 功能特性
- 特性 1
- 特性 2
## 快速开始
```bash
# 安装依赖
make install
# 运行项目
make run
```
## 许可证
MIT License
EOF
# .gitignore
cat > .gitignore << 'EOF'
# OS
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
*.swp
*.swo
# Dependencies
node_modules/
vendor/
# Build
dist/
build/
*.exe
*.dll
*.so
*.dylib
# Logs
*.log
logs/
# Environment
.env
.env.local
EOF
# LICENSE
cat > LICENSE << 'EOF'
MIT License
Copyright (c) 2026
Permission is hereby granted...
EOF
git add README.md .gitignore LICENSE
git commit -m "Initial commit: Add basic project files"
```
### 创建分支保护规则
```bash
# 通过 API 设置分支保护(需要管理员权限)
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enable_push": false,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["admin"],
"require_signed_commits": false,
"enable_status_check": true,
"status_check_contexts": ["continuous-integration/gitea"]
}' \
"$GITEA_URL/api/v1/repos/$owner/$repo/branch_protections"
```
## Actions 配置
### 启用 Actions
Actions 在 Gitea 1.19+ 中默认启用,无需额外配置。
### 配置 Secrets
**方法 1: 通过 UI**
1. 打开仓库 → Settings → Secrets → Actions
2. 点击 "New Secret"
3. 输入 Name 和 Value
4. 保存
**方法 2: 通过 API**
```bash
source ~/.config/gitea/config.env
owner="ai"
repo="my-project"
secret_name="DEPLOY_KEY"
secret_value="super-secret-key"
# Base64 编码
encoded=$(echo -n "$secret_value" | base64)
# 创建 Secret
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":\"${encoded}\"}" \
"$GITEA_URL/api/v1/repos/$owner/$repo/actions/secrets/$secret_name"
echo "✓ Secret $secret_name 已创建"
```
### 配置 Variables
Variables 用于非敏感配置:
```bash
owner="ai"
repo="my-project"
var_name="ENVIRONMENT"
var_value="production"
# 创建 Variable
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"value\":\"${var_value}\"}" \
"$GITEA_URL/api/v1/repos/$owner/$repo/actions/variables/$var_name"
echo "✓ Variable $var_name 已创建"
```
### 批量配置 Secrets
```bash
#!/bin/bash
source ~/.config/gitea/config.env
owner="ai"
repo="my-project"
# Secret 列表
declare -A secrets=(
["REGISTRY_PASSWORD"]="docker-password"
["API_TOKEN"]="api-token-value"
["DEPLOY_KEY"]="ssh-private-key"
)
for name in "${!secrets[@]}"; do
value="${secrets[$name]}"
encoded=$(echo -n "$value" | base64)
curl -s -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":\"${encoded}\"}" \
"$GITEA_URL/api/v1/repos/$owner/$repo/actions/secrets/$name"
echo "$name"
done
```
## Webhook 配置
### 创建 Webhook
```bash
source ~/.config/gitea/config.env
owner="ai"
repo="my-project"
webhook_url="https://example.com/webhook"
webhook_secret="webhook-secret-key"
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"type\": \"gitea\",
\"config\": {
\"url\": \"${webhook_url}\",
\"content_type\": \"json\",
\"secret\": \"${webhook_secret}\"
},
\"events\": [\"push\", \"pull_request\", \"release\"],
\"active\": true
}" \
"$GITEA_URL/api/v1/repos/$owner/$repo/hooks"
echo "✓ Webhook 已创建"
```
### 常用事件类型
| 事件 | 说明 |
|------|------|
| `push` | 代码推送 |
| `pull_request` | PR 创建/更新 |
| `issues` | Issue 创建/更新 |
| `release` | Release 发布 |
| `create` | 分支/标签创建 |
| `delete` | 分支/标签删除 |
### 列出 Webhooks
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/hooks" | jq .
```
### 删除 Webhook
```bash
hook_id=1
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/hooks/$hook_id"
```
## 仓库设置
### 更新仓库信息
```bash
curl -X PATCH \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "新的仓库描述",
"website": "https://example.com",
"private": false,
"has_issues": true,
"has_wiki": false,
"default_branch": "main"
}' \
"$GITEA_URL/api/v1/repos/$owner/$repo"
```
### 启用/禁用功能
```bash
# 禁用 Wiki
curl -X PATCH \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"has_wiki": false}' \
"$GITEA_URL/api/v1/repos/$owner/$repo"
# 启用 Issues
curl -X PATCH \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"has_issues": true}' \
"$GITEA_URL/api/v1/repos/$owner/$repo"
```
## 协作者管理
### 添加协作者
```bash
username="collaborator"
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"permission": "write"}' \
"$GITEA_URL/api/v1/repos/$owner/$repo/collaborators/$username"
echo "✓ 已添加协作者: $username"
```
**权限级别**
- `read`: 只读
- `write`: 读写
- `admin`: 管理员
### 列出协作者
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/collaborators" | jq .
```
### 移除协作者
```bash
username="collaborator"
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/collaborators/$username"
```
## 常见操作
### 检查仓库是否存在
```bash
repo_exists() {
local owner="$1"
local repo="$2"
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo")
http_code=$(echo "$response" | tail -n1)
[ "$http_code" = "200" ]
}
if repo_exists "ai" "my-project"; then
echo "仓库存在"
else
echo "仓库不存在"
fi
```
### 归档仓库
```bash
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/archive"
echo "✓ 仓库已归档"
```
### 删除仓库
```bash
echo "⚠️ 警告: 此操作无法撤销!"
read -p "确认删除仓库 $owner/$repo? 输入 'yes' 确认: " confirm
if [ "$confirm" = "yes" ]; then
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo"
echo "✓ 仓库已删除"
else
echo "已取消"
fi
```
## 批量操作
### 批量创建仓库
```bash
#!/bin/bash
source ~/.config/gitea/config.env
org="ai"
repos=("project-a" "project-b" "project-c")
for repo in "${repos[@]}"; do
echo "创建仓库: $repo"
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${repo}\",
\"private\": true,
\"auto_init\": true
}" \
"$GITEA_URL/api/v1/orgs/$org/repos" | jq -r '.html_url'
sleep 1 # 避免请求过快
done
```
### 批量配置 Secrets
```bash
#!/bin/bash
source ~/.config/gitea/config.env
org="ai"
repos=("repo1" "repo2" "repo3")
secret_name="DEPLOY_KEY"
secret_value="shared-secret"
encoded=$(echo -n "$secret_value" | base64)
for repo in "${repos[@]}"; do
echo "配置 $repo..."
curl -s -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":\"${encoded}\"}" \
"$GITEA_URL/api/v1/repos/$org/$repo/actions/secrets/$secret_name"
echo "$repo"
done
```
## 故障排查
### 仓库创建失败
**症状**: HTTP 409 - 仓库已存在
**解决**:
```bash
# 列出所有仓库
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/$org/repos" | jq -r '.[].name'
```
### Secret 配置失败
**症状**: HTTP 404 - 仓库不存在
**解决**:
```bash
# 检查仓库是否存在
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo"
```
### 权限不足
**症状**: HTTP 403 - Forbidden
**解决**:
- 检查 Token 是否有 `repo` 权限
- 检查是否是仓库/组织的成员
- 使用管理员账户
## 相关资源
- [Gitea API 文档](https://docs.gitea.com/api/1.20/)
- [API 参考](./api-reference.md)
- [环境配置](./setup-guide.md)
- [Workflow 生成器](./workflow-generator.md)
## 版本
- **文档版本**: 1.0
- **最后更新**: 2026-01-12

View File

@@ -0,0 +1,808 @@
# Gitea Runner 管理
完整的 Gitea Act Runner 创建、注册、配置和管理指南。
## 概述
Gitea Act Runner 是 Gitea Actions 的 CI/CD 执行器,兼容 GitHub Actions workflow 语法。
### Runner 级别
| 级别 | 作用域 | 权限要求 | 适用场景 |
|------|--------|---------|---------|
| **全局 Runner** | 所有组织和仓库 | 管理员 Token | 共享资源、统一管理 |
| **组织 Runner** | 特定组织 | 组织管理权限 | 组织内项目共享 |
| **仓库 Runner** | 特定仓库 | 仓库管理权限 | 独立项目使用 |
**推荐**
- 小团队或个人使用:**全局 Runner**(统一管理,配置简单)
- 企业多组织:**组织 Runner**(隔离资源,权限分离)
### 执行模式
| 模式 | 环境 | 适用场景 | Android SDK |
|------|------|---------|-------------|
| **Host Mode** | Native macOS/Linux | Android/iOS 构建、原生工具链 | macOS ARM64 支持 |
| Docker Mode | Linux 容器 | 跨平台构建 | Linux ARM64 不支持 |
**推荐**macOS ARM64 使用 **Host Mode** 以支持 Android SDK。
## Runner 目录结构
所有 Runner 配置统一管理在:
```
~/.config/gitea/runners/
├── runner-macbook-pro/ # Runner 1
│ ├── .runner # 注册信息JSON
│ ├── config.yaml # Runner 配置
│ ├── cache/ # Cache 目录
│ └── workspace/ # 工作目录
└── runner-mac-mini/ # Runner 2
└── ...
```
## 前置要求
### 1. 安装 act_runner
```bash
# 使用 Homebrew推荐
brew install act_runner
# 或手动下载
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
# 验证安装
act_runner --version
```
### 2. 安装开发工具(可选,根据需要)
```bash
# GoGo 项目构建)
brew install go
# Node.js前端项目构建
brew install node@22
npm install -g pnpm
# JDK 17Android 项目构建)
brew install openjdk@17
# Docker容器构建
# 从 https://docker.com 安装 Docker Desktop
```
### 3. 安装 Android SDKAndroid 项目构建)
```bash
# 使用 Homebrew
brew install --cask android-commandlinetools
# 或手动安装
mkdir -p ~/android-sdk/cmdline-tools
cd ~/android-sdk/cmdline-tools
curl -sL https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip -o cmdline-tools.zip
unzip cmdline-tools.zip
mv cmdline-tools latest
rm cmdline-tools.zip
# 接受许可并安装组件
yes | sdkmanager --licenses
sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.0.0"
```
### 4. 配置环境变量
添加到 `~/.zshrc``~/.bashrc`
```bash
# Go
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# Java
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
export PATH=$PATH:$JAVA_HOME/bin
# Android SDK
export ANDROID_HOME=~/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
```
重新加载配置:
```bash
source ~/.zshrc # 或 source ~/.bashrc
```
### 5. 验证环境
```bash
go version # Go 1.23+
node --version # v22.x
pnpm --version # Latest
java -version # 17+
echo $ANDROID_HOME # SDK 路径
docker --version # Latest
act_runner --version
```
## 创建 Runner
### 使用命令快速创建
```bash
/gitea-create-runner
```
此命令会自动:
1. 检查并安装 act_runner如未安装
2. 加载 Gitea 配置(如不存在则提示初始化)
3. 生成 runner 名称(基于主机名)
4. 检测系统环境并生成 labels
5. 创建 runner 目录结构
6. 生成 host 模式配置文件
7. 获取注册 token优先全局
8. 注册并启动 runner
### 详细创建流程
当运行 `/gitea-create-runner` 命令时,会执行以下步骤:
#### 步骤 1: 检查 act_runner 安装
```bash
if command -v act_runner &> /dev/null; then
echo "✓ act_runner 已安装"
else
echo "⚠️ act_runner 未安装,正在安装..."
brew install act_runner
fi
```
#### 步骤 2: 加载 Gitea 配置
```bash
config_file="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file" ]; then
echo "❌ Gitea 配置不存在,请先初始化: /gitea-reset"
exit 1
fi
source "$config_file"
```
#### 步骤 3: 生成 Runner 名称
```bash
# 基于主机名自动生成
hostname=$(hostname -s)
runner_name="runner-$hostname"
# 或使用命令参数
# /gitea-create-runner my-custom-name
```
#### 步骤 4: 智能检测系统环境和 Labels
```bash
# 检测操作系统
OS=$(uname -s)
case "$OS" in
Darwin) os_label="macOS" ;;
Linux) os_label="ubuntu" ;;
*) os_label="unknown" ;;
esac
# 检测架构
ARCH=$(uname -m)
case "$ARCH" in
arm64|aarch64) arch_label="ARM64" ;;
x86_64) arch_label="x64" ;;
*) arch_label="unknown" ;;
esac
# 生成组合 label
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
# 生成建议的 labels
suggested_labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
echo ""
echo "检测到系统环境:"
echo " 操作系统: $OS ($os_label)"
echo " 架构: $ARCH ($arch_label)"
echo ""
echo "建议的 Runner Labels:"
echo " $suggested_labels"
echo ""
```
**输出示例**
```
检测到系统环境:
操作系统: Darwin (macOS)
架构: arm64 (ARM64)
建议的 Runner Labels:
self-hosted:host,macOS:host,ARM64:host,darwin-arm64:host
```
#### 步骤 5: 创建 Runner 目录
```bash
runners_dir="$HOME/.config/gitea/runners"
runner_dir="$runners_dir/$runner_name"
# 检查是否已存在
if [ -d "$runner_dir" ]; then
echo "❌ Runner '$runner_name' 已存在"
echo "请使用其他名称或先删除现有 runner: /gitea-delete-runner $runner_name"
exit 1
fi
# 创建目录结构
mkdir -p "$runner_dir"/{cache,workspace}
echo "✓ 创建目录: $runner_dir"
```
#### 步骤 6: 生成配置文件
**默认生成 Host Mode 配置**
```yaml
log:
level: info
runner:
file: $HOME/.config/gitea/runners/$runner_name/.runner
capacity: ${GITEA_RUNNER_CAPACITY:-2}
timeout: ${GITEA_RUNNER_TIMEOUT:-3h}
shutdown_timeout: 30s
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels:
- "self-hosted:host"
- "macOS:host"
- "ARM64:host"
- "darwin-arm64:host"
cache:
enabled: true
dir: "$HOME/.config/gitea/runners/$runner_name/cache"
host: "127.0.0.1"
port: 9000
host:
workdir_parent: "$HOME/.config/gitea/runners/$runner_name/workspace"
```
**说明**
- 默认使用 Host Mode支持 Android SDK、iOS 等原生工具)
- 自动填充系统检测的 labels
- 容量和超时可通过环境变量配置
#### 步骤 7: 获取注册 Token
```bash
echo ""
echo "正在获取 Runner 注册 Token..."
# 默认尝试全局 Runner管理员权限
echo "尝试创建全局 Runner可用于所有组织和仓库..."
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/admin/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
# 如果全局 Runner 失败(权限不足),降级到组织 Runner
if [ "$http_code" != "200" ]; then
echo "⚠️ 全局 Runner 权限不足 (HTTP $http_code)"
echo " 全局 Runner 需要管理员 Token"
echo ""
echo "降级到组织 Runner..."
runner_level="organization"
if [ -n "$GITEA_DEFAULT_ORG" ]; then
org_name="$GITEA_DEFAULT_ORG"
else
read -p "请输入组织名称: " org_input
if [ -z "$org_input" ]; then
echo "❌ 必须指定组织名称"
exit 1
fi
org_name="$org_input"
fi
echo "使用组织: $org_name"
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/orgs/$org_name/actions/runners/registration-token")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
else
echo "✓ 使用全局 Runner"
runner_level="global"
fi
if [ "$http_code" != "200" ]; then
echo "❌ 获取注册 Token 失败 (HTTP $http_code)"
echo "$body"
exit 1
fi
registration_token=$(echo "$body" | jq -r '.token')
echo "✓ 注册 Token 已获取"
```
#### 步骤 8: 注册 Runner
```bash
echo ""
echo "正在注册 Runner..."
act_runner register \
--config "$runner_dir/config.yaml" \
--instance "$GITEA_URL" \
--token "$registration_token" \
--name "$runner_name" \
--labels "$labels" \
--no-interactive
if [ $? -eq 0 ]; then
echo "✓ Runner 注册成功"
else
echo "❌ Runner 注册失败"
exit 1
fi
```
#### 步骤 9: 自动启动 Runner
```bash
echo ""
echo "正在启动 Runner..."
# 后台启动 Runner
nohup act_runner daemon --config "$runner_dir/config.yaml" \
> "$runner_dir/runner.log" 2>&1 &
runner_pid=$!
# 等待 2 秒让 runner 启动
sleep 2
# 检查进程是否存在
if ps -p $runner_pid > /dev/null 2>&1; then
echo "✓ Runner 已启动 (PID: $runner_pid)"
else
echo "⚠️ Runner 启动失败,请查看日志:"
echo " tail -f $runner_dir/runner.log"
exit 1
fi
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Runner 创建完成!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Runner 名称: $runner_name"
echo "Runner 级别: ${runner_level}"
if [ "$runner_level" = "organization" ]; then
echo "所属组织: ${org_name}"
fi
echo "PID: $runner_pid"
echo "配置文件: $runner_dir/config.yaml"
echo "工作目录: $runner_dir/workspace"
echo "Cache 目录: $runner_dir/cache"
echo "日志文件: $runner_dir/runner.log"
echo ""
echo "管理命令:"
echo " 查看日志: tail -f $runner_dir/runner.log"
echo " 停止 Runner: pkill -f 'act_runner daemon --config.*$runner_name'"
echo " 查看所有: /gitea-list-runners"
echo " 删除 Runner: /gitea-delete-runner $runner_name"
echo ""
```
## Label 设计指南
### Label 格式
```
label-name:mode
```
**Mode 类型**
- `host`: Host Mode原生执行
- `docker://image`: Docker Mode容器执行
### 推荐 Labels
#### macOS ARM64
```yaml
labels:
- "self-hosted:host"
- "macOS:host"
- "ARM64:host"
- "darwin-arm64:host"
```
#### Linux x64
```yaml
labels:
- "self-hosted:host"
- "ubuntu:host"
- "x64:host"
- "linux-x64:host"
```
#### Docker Mode
```yaml
labels:
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
- "ubuntu-22.04:docker://catthehacker/ubuntu:act-latest"
```
### Workflow 匹配
**方法 1: 组合 label推荐最精确**
```yaml
jobs:
build:
runs-on: darwin-arm64
```
**方法 2: Label 数组(匹配多个条件)**
```yaml
jobs:
build:
runs-on: [self-hosted, macOS, ARM64]
```
**方法 3: 仅操作系统**
```yaml
jobs:
build:
runs-on: macOS
```
## Runner 配置详解
### Host Mode 配置
```yaml
log:
level: info # 日志级别debug/info/warn/error
runner:
file: /path/to/.runner # 注册信息文件
capacity: 2 # 并发任务数
timeout: 3h # 任务超时时间
shutdown_timeout: 30s # 关闭超时时间
insecure: false # 是否允许不安全连接
fetch_timeout: 5s # 获取任务超时
fetch_interval: 2s # 获取任务间隔
labels:
- "label-name:host" # Runner labels
cache:
enabled: true # 启用缓存
dir: "/path/to/cache" # 缓存目录
host: "127.0.0.1" # 监听地址(仅本地)
port: 9000 # 缓存服务端口
host:
workdir_parent: "/path/to/workspace" # 工作目录父路径
```
### Docker Mode 配置
```yaml
log:
level: info
runner:
file: /path/to/.runner
capacity: 2
timeout: 3h
labels:
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
cache:
enabled: true
dir: "/path/to/cache"
host: "192.168.0.103" # 主机 IP非 127.0.0.1
port: 9000
container:
options: "--platform=linux/amd64" # 容器选项
network: "host" # 网络模式
```
## 多 Runner 缓存共享
### 方案 A: Master-Slave 模式(推荐 2-3 个 runner
**主 Runnercache server**
```yaml
cache:
enabled: true
dir: "$HOME/.config/gitea/runners/runner-primary/cache"
host: "0.0.0.0" # 监听所有接口
port: 9000
```
**从 Runnercache client**
```yaml
cache:
enabled: true
server: "http://192.168.0.103:9000" # 主 runner IP
dir: "$HOME/.config/gitea/runners/runner-secondary/cache" # 本地备份
host: "192.168.0.104" # 本 runner IP
port: 9000
```
### 方案 B: NFS 共享存储(企业级)
**1. 在主 Runner 上设置 NFS server**
```bash
# /etc/exports
/Users/voson/.config/gitea/cache -alldirs -mapall=$(id -u):$(id -g) 192.168.0.0/24
sudo nfsd restart
```
**2. 在从 Runner 上挂载**
```bash
sudo mkdir -p /mnt/runner-cache
sudo mount -t nfs 192.168.0.103:/Users/voson/.config/gitea/cache /mnt/runner-cache
```
### 方案 C: 独立缓存(默认)
每个 runner 维护自己的缓存。首次构建下载依赖,后续构建使用本地缓存。
## 缓存管理
### Host Mode 缓存位置
| 缓存类型 | 位置 | 行为 |
|---------|------|------|
| Runner cache service | `config.cache.dir` | act_runner 管理 |
| Gradle | `~/.gradle/` | 跨构建持久化 |
| npm/pnpm | `~/.npm/`, `~/.pnpm-store/` | 跨构建持久化 |
| Go modules | `~/go/pkg/mod/` | 跨构建持久化 |
### 缓存清理脚本
创建 `~/.config/gitea/cleanup-cache.sh`
```bash
#!/bin/bash
set -e
echo "清理 Gitea Runner 缓存..."
runners_dir="$HOME/.config/gitea/runners"
# 1. Runner cache超过 7 天)
find "$runners_dir"/*/cache -type f -mtime +7 -delete 2>/dev/null || true
echo "✓ Runner cache 已清理"
# 2. Gradle cache超过 30 天)
find ~/.gradle/caches -type f -mtime +30 -delete 2>/dev/null || true
find ~/.gradle/caches -type d -empty -delete 2>/dev/null || true
echo "✓ Gradle cache 已清理"
# 3. npm cache 验证
npm cache verify
echo "✓ npm cache 已验证"
# 4. Workspace 清理(超过 7 天)
find "$runners_dir"/*/workspace -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true
echo "✓ Workspace 已清理"
# 显示缓存大小
echo ""
echo "当前缓存大小:"
for runner in "$runners_dir"/*; do
if [ -d "$runner" ]; then
name=$(basename "$runner")
size=$(du -sh "$runner/cache" 2>/dev/null | awk '{print $1}')
echo " $name: ${size:-0B}"
fi
done
echo ""
echo "✓ 清理完成"
```
### 定时清理
```bash
# 添加到 crontab
chmod +x ~/.config/gitea/cleanup-cache.sh
crontab -e
# 每周日凌晨 3 点清理
0 3 * * 0 ~/.config/gitea/cleanup-cache.sh >> ~/.config/gitea/cleanup.log 2>&1
```
## Runner 管理命令
### 列出所有 Runners
```bash
/gitea-list-runners
```
### 启动 Runner
```bash
# 前台运行(调试用)
act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml
# 后台运行
nohup act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml \
> ~/.config/gitea/runners/runner-macbook-pro/runner.log 2>&1 &
```
### 停止 Runner
```bash
# 查找进程
ps aux | grep "act_runner daemon"
# 停止特定 runner
pkill -f "act_runner daemon --config.*runner-macbook-pro"
# 停止所有 runners
pkill -f "act_runner daemon"
```
### 查看 Runner 日志
```bash
# 实时查看
tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log
# 查看最近 100 行
tail -n 100 ~/.config/gitea/runners/runner-macbook-pro/runner.log
```
### 删除 Runner
```bash
/gitea-delete-runner runner-macbook-pro
```
## 故障排查
### 1. Android SDK 未找到
```bash
# 验证 ANDROID_HOME
echo $ANDROID_HOME
ls $ANDROID_HOME
# 确保 runner 以安装 SDK 的用户身份运行
whoami
```
### 2. JDK 版本错误
Android Gradle Plugin 8.x 需要 JDK 17+
```bash
java -version
# 应显示: openjdk version "17.x.x"
# 如果版本错误,更新 JAVA_HOME
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
```
### 3. 权限问题
```bash
# 确保 runner 用户拥有工作目录
chown -R $(whoami) ~/.config/gitea/runners
chmod -R 755 ~/.config/gitea/runners
```
### 4. Label 不匹配
```bash
# 检查注册的 labels
cat ~/.config/gitea/runners/runner-macbook-pro/.runner | jq '.labels'
# 确保 workflow runs-on 匹配
# Workflow: runs-on: darwin-arm64
# Runner: "darwin-arm64:host" label
```
### 5. 缓存服务端口冲突
```bash
# 检查端口占用
lsof -i :9000
# 如果冲突,修改配置使用其他端口
vim ~/.config/gitea/runners/runner-macbook-pro/config.yaml
# 修改: port: 9001
```
### 6. Runner 无法连接 Gitea
```bash
# 测试 Gitea 连接
source ~/.config/gitea/config.env
curl -s "$GITEA_URL/api/v1/version" | jq .
# 检查防火墙设置
# 检查网络连接
```
### 7. Runner 已注册但不在线
```bash
# 检查 runner 进程
ps aux | grep "act_runner daemon"
# 如果未运行,后台启动 runner创建时会自动启动
nohup act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/config.yaml \
> ~/.config/gitea/runners/runner-macbook-pro/runner.log 2>&1 &
# 查看日志诊断问题
tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log
```
## Quick Reference
| 任务 | 命令 |
|------|------|
| 安装 runner | `brew install act_runner` |
| 创建 runner | `/gitea-create-runner`(自动安装、配置、启动)|
| 列出 runners | `/gitea-list-runners` |
| 删除 runner | `/gitea-delete-runner` |
| 手动启动 | `nohup act_runner daemon --config <config.yaml> > <log> 2>&1 &` |
| 停止 runner | `pkill -f "act_runner daemon --config.*<name>"` |
| 查看状态 | `ps aux \| grep act_runner` |
| 查看日志 | `tail -f <runner-dir>/runner.log` |
| 清理缓存 | `~/.config/gitea/cleanup-cache.sh` |
## 相关资源
- [Gitea Actions 文档](https://docs.gitea.com/usage/actions/overview)
- [Act Runner 文档](https://docs.gitea.com/usage/actions/act-runner)
- [Android SDK 命令行工具](https://developer.android.com/studio/command-line)
- [GitHub Actions Workflow 语法](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
## 版本
- **文档版本**: 1.0
- **最后更新**: 2026-01-12
- **兼容性**: act_runner 0.2.13+, macOS ARM64, Linux

603
skill/gitea/setup-guide.md Normal file
View File

@@ -0,0 +1,603 @@
# Gitea 环境配置指南
首次使用 Gitea skill 前的完整配置指南。
## 概述
Gitea skill 需要配置连接信息才能与你的 Gitea 实例交互。配置信息存储在:
```
~/.config/gitea/config.env
```
## 配置目录结构
```
~/.config/gitea/
├── config.env # 主配置文件(包含 URL、Token、默认组织等
├── runners/ # Runner 配置目录
│ └── runner-*/ # 各个 runner 的独立目录
└── .gitignore # Git 忽略文件(保护敏感信息)
```
## 快速配置
### 方法 1: 使用交互式向导(推荐)
运行配置命令:
```bash
/gitea-reset
```
按照提示输入信息即可。
### 方法 2: 自然语言请求
直接告诉 AI
```
用户: 配置 gitea
用户: 初始化 gitea 连接
用户: 设置 gitea 环境
```
AI 会自动启动配置向导。
### 方法 3: 手动创建配置文件
如果你熟悉配置格式,可以手动创建:
```bash
mkdir -p ~/.config/gitea/runners
cat > ~/.config/gitea/config.env << 'EOF'
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
EOF
chmod 600 ~/.config/gitea/config.env
```
## 交互式配置流程
### 步骤 1: 输入 Gitea 实例地址
```
请输入 Gitea 实例地址 (例如: https://git.digitevents.com):
```
**要求**
- 必须以 `http://``https://` 开头
- 不要包含尾随斜杠
- 确保可以从当前网络访问
**示例**
```
✓ https://git.digitevents.com
✓ https://gitea.example.com
✗ git.digitevents.com (缺少协议)
✗ https://gitea.com/ (包含尾随斜杠)
```
### 步骤 2: 输入 Personal Access Token
```
请输入 Personal Access Token:
```
**获取 Token 的步骤**
1. 登录 Gitea
2. 点击右上角头像 → **设置**
3. 左侧菜单选择 **应用****访问令牌**
4. 点击 **生成新令牌**
5. 设置令牌名称(如 `opencode-cli`
6. 选择权限(见下方推荐权限)
7. 点击 **生成令牌**
8. 复制生成的 Token只显示一次
**推荐权限**
| 权限 | 用途 | 是否必需 |
|------|------|---------|
| `repo` | 创建和管理仓库 | ✅ 必需 |
| `admin:org` | 创建组织级 Runner | ✅ 推荐 |
| `write:runner` | 管理 Runner | ✅ 推荐 |
| `write:user` | 创建用户级 Variables | ✅ 推荐 |
| `admin:repo_hook` | 配置 Webhooks | ⚠️ 可选 |
| `write:issue` | 创建 Release | ⚠️ 可选 |
**安全提示**
- Token 等同于密码,请妥善保管
- 不要在公开场合分享 Token
- 定期轮换 Token建议每 3-6 个月)
- 使用最小权限原则
### 步骤 3: 测试连接
```
正在测试连接...
✓ 连接成功!
```
系统会调用 Gitea API 验证:
- URL 是否可访问
- Token 是否有效
- 网络是否正常
**如果失败**
- 检查 URL 是否正确
- 检查 Token 是否复制完整
- 检查网络连接
- 检查防火墙设置
### 步骤 4: 验证 Token 权限
```
正在检查 Token 权限...
✓ repo (仓库管理)
✓ admin:org (组织管理)
✓ write:runner (Runner 管理)
⚠ 缺少 admin:repo_hook 权限(可能影响 Webhook 配置)
```
系统会测试 Token 的实际权限,并给出建议。
**权限不足时**
- 如果缺少必需权限,建议重新创建 Token
- 如果只缺少可选权限,可以继续使用
- 后续需要时可以更新 Token
### 步骤 5: 输入默认组织(可选)
```
请输入默认组织名称 (可选,回车跳过):
```
**作用**
- 创建仓库时,如果不指定 owner使用此默认组织
- 创建组织级 Runner 时使用
- 可以随时使用 `/gitea-switch-org` 切换
**示例**
```
ai → 创建仓库时使用 ai/repo-name
my-team → 创建仓库时使用 my-team/repo-name
(留空) → 创建仓库时使用当前登录用户
```
**注意**:留空是完全可以的,系统会自动使用当前登录用户创建个人仓库。
### 步骤 6: 输入 Gitea 用户名(用于 Actions Variables
```
请输入 Gitea 用户名 (将创建为用户级 variable):
```
**作用**
- 此用户名将自动注册到 Gitea 用户级 variables变量名`USERNAME`
- 可在所有个人仓库的 Actions workflow 中通过 `${{ vars.USERNAME }}` 使用
- 用于需要 Git 操作的 workflow如推送代码、创建 tag 等)
**示例**
```
your_username → 在 workflow 中可使用 ${{ vars.USERNAME }}
john → 你的 Gitea 登录用户名
```
**重要说明**
- Gitea 不允许 variable 名称以 `GITEA_``GITHUB_` 开头
- 因此配置项 `GITEA_USERNAME` 会被注册为 `USERNAME` variable
- 如果此 variable 已存在于 Gitea 服务器,系统会自动更新为新值
### 步骤 7: 输入 Gitea 密码(用于 Actions
```
请输入 Gitea 密码:
```
**作用**
- 密码将存储在本地配置文件 `config.env` 中(权限 600
- 用于需要认证的 Git 操作
- 也可以选择在 workflow 中使用 Secret 方式(需要手动创建)
**安全说明**
- ✅ 配置文件权限为 600仅所有者可读写
-`.gitignore` 自动排除配置文件
- ⚠️ 不建议在公共环境使用明文密码
- 💡 建议使用 Personal Access Token 替代密码
**留空说明**:如果不需要在 workflow 中进行 Git 推送操作,可以留空。
### 步骤 8: 输入 Actions 通知 Webhook URL可选
```
请输入 Actions 通知 Webhook URL (可选,回车跳过):
```
**作用**
- 用于 workflow 完成后发送通知到第三方平台(如飞书、钉钉、企业微信等)
- 此 URL 将自动注册到 Gitea 用户级 variables变量名`WEBHOOK_URL`
- 可在 workflow 中通过 `${{ vars.WEBHOOK_URL }}` 使用
**示例**
```
https://www.feishu.cn/flow/api/trigger-webhook/xxx (飞书)
https://oapi.dingtalk.com/robot/send?access_token=xxx (钉钉)
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx (企业微信)
```
**使用方式**
```yaml
- name: 发送通知
run: |
curl -X POST "${{ vars.WEBHOOK_URL }}" \
-H "Content-Type: application/json" \
-d '{"msg_type":"text","content":{"text":"构建完成"}}'
```
**说明**
- 留空则不创建 `WEBHOOK_URL` variable
- 如果此 variable 已存在于 Gitea 服务器,系统会更新为新值
### 步骤 9: 注册用户级 Variables
```
正在检查并注册用户级 Variables...
检查 USERNAME...
✓ USERNAME 已创建
检查 WEBHOOK_URL...
✓ WEBHOOK_URL 已创建
```
系统会自动调用 Gitea API 创建以下用户级 variables
| Variable 名称 | 来源配置 | 说明 |
|--------------|---------|------|
| `USERNAME` | `GITEA_USERNAME` | Gitea 用户名 |
| `WEBHOOK_URL` | `GITEA_WEBHOOK_URL` | Actions 通知 Webhook |
**重要**Gitea 不允许 variable 名称以 `GITEA_``GITHUB_` 开头,所以 `GITEA_USERNAME` 配置项会被注册为 `USERNAME` variable。
**API 端点**
```
POST /api/v1/user/actions/variables/{variable_name}
```
**在 Workflow 中使用**
```yaml
steps:
- name: 使用 Variables
run: |
echo "用户名: ${{ vars.USERNAME }}"
echo "Webhook: ${{ vars.WEBHOOK_URL }}"
```
**查看已创建的 Variables**
- 访问:`https://git.digitevents.com/user/settings/actions/variables`
- 或使用命令:`/gitea-list-variables`
### 步骤 10: 保存配置
```
✓ 配置已保存
配置文件: ~/.config/gitea/config.env
Runner 目录: ~/.config/gitea/runners
```
配置文件内容:
```bash
# Gitea Configuration
# Generated at 2026-01-12 22:30:00
GITEA_URL=https://git.digitevents.com
GITEA_TOKEN=git_xxxxxxxxxxxxxxxxxxxx
GITEA_DEFAULT_ORG=ai
# Gitea 仓库认证信息(用于 Actions
GITEA_USERNAME=your_username
GITEA_PASSWORD=your_password_here
# Actions 通知 Webhook可选
GITEA_WEBHOOK_URL=https://www.feishu.cn/flow/api/trigger-webhook/xxx
# Runner Default Settings
GITEA_RUNNER_CAPACITY=2
GITEA_RUNNER_TIMEOUT=3h
# Optional: Override auto-detected labels
# GITEA_RUNNER_LABELS=custom-label-1:host,custom-label-2:host
```
## 配置验证
配置完成后,验证配置是否正确:
```bash
/gitea-config
```
应该看到:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
当前 Gitea 配置
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL: https://git.digitevents.com
默认组织: ai
Token 状态: ✓ 有效 (用户: your_username)
配置文件: ~/.config/gitea/config.env
```
## 配置文件说明
### 必需配置项
| 配置项 | 说明 | 示例 |
|--------|------|------|
| `GITEA_URL` | Gitea 实例地址 | `https://git.digitevents.com` |
| `GITEA_TOKEN` | Personal Access Token | `git_xxxxxxxxxx` |
### 推荐配置项(用于 Actions
| 配置项 | 说明 | 示例 | 自动创建为 Variable |
|--------|------|------|-------------------|
| `GITEA_USERNAME` | Gitea 用户名 | `your_username` | ✅ 是 → `USERNAME` |
| `GITEA_PASSWORD` | Gitea 密码 | `your_password` | ❌ 否(仅本地使用) |
| `GITEA_WEBHOOK_URL` | Actions 通知 Webhook | `https://...` | ✅ 是 → `WEBHOOK_URL` |
**说明**
- 标记为 ✅ 的配置项会在初始化时自动创建为 Gitea 用户级 variables
- 这些 variables 可在所有个人仓库的 Actions workflow 中使用
- 使用方式:`${{ vars.USERNAME }}``${{ vars.WEBHOOK_URL }}`
- **注意**Gitea 不允许 variable 名称以 `GITEA_``GITHUB_` 开头,所以会自动转换名称
### 可选配置项
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `GITEA_DEFAULT_ORG` | 默认组织名称 | 无 |
| `GITEA_RUNNER_CAPACITY` | Runner 并发任务数 | `2` |
| `GITEA_RUNNER_TIMEOUT` | Runner 任务超时时间 | `3h` |
| `GITEA_RUNNER_LABELS` | 覆盖自动检测的 labels | 自动检测 |
### 自定义 Runner Labels
如果自动检测的 labels 不符合需求,可以手动覆盖:
```bash
# 编辑配置文件
vim ~/.config/gitea/config.env
# 取消注释并修改
GITEA_RUNNER_LABELS=self-hosted:host,linux:host,x64:host,custom:host
```
创建新 Runner 时会优先使用此配置。
## 配置管理
### 查看当前配置
```bash
/gitea-config
```
显示:
- Gitea URL
- 默认组织
- Token 状态和关联用户
- 已配置的 Runner 数量
- 配置文件路径
### 切换默认组织
```bash
/gitea-switch-org new-org-name
```
### 重置配置
```bash
/gitea-reset
```
会重新启动配置向导,覆盖现有配置。
**警告**:重置配置不会影响已创建的 Runner但 Runner 会继续使用旧的注册信息。
### 更新配置
#### 方法 1: 使用命令(推荐)
```bash
/gitea-reset # 完整重置
/gitea-switch-org my-org # 只切换组织
```
#### 方法 2: 手动编辑
```bash
vim ~/.config/gitea/config.env
```
修改后无需重启,下次使用时自动生效。
## 多环境配置
如果需要管理多个 Gitea 实例,推荐做法:
### 方法 1: 使用不同的配置文件
```bash
# 开发环境
cp ~/.config/gitea/config.env ~/.config/gitea/config.dev.env
# 生产环境
cp ~/.config/gitea/config.env ~/.config/gitea/config.prod.env
# 使用时手动切换
cp ~/.config/gitea/config.prod.env ~/.config/gitea/config.env
```
### 方法 2: 创建切换脚本
```bash
# ~/.config/gitea/switch-env.sh
#!/bin/bash
case "$1" in
dev)
cp ~/.config/gitea/config.dev.env ~/.config/gitea/config.env
echo "✓ 切换到开发环境"
;;
prod)
cp ~/.config/gitea/config.prod.env ~/.config/gitea/config.env
echo "✓ 切换到生产环境"
;;
*)
echo "用法: $0 {dev|prod}"
exit 1
;;
esac
```
使用:
```bash
bash ~/.config/gitea/switch-env.sh dev
```
## 安全最佳实践
### 1. 文件权限
确保配置文件只有所有者可读写:
```bash
chmod 600 ~/.config/gitea/config.env
```
### 2. Token 安全
- ✅ 使用最小权限原则
- ✅ 定期轮换 Token
- ✅ 不要将 Token 提交到 Git
- ✅ 使用 `.gitignore` 排除配置文件
- ❌ 不要在公开场合分享 Token
- ❌ 不要使用永不过期的 Token
### 3. 配置备份
定期备份配置(移除 Token 后):
```bash
# 创建备份(移除敏感信息)
grep -v "GITEA_TOKEN" ~/.config/gitea/config.env > ~/gitea-config-backup.env
```
### 4. .gitignore 配置
自动生成的 `.gitignore` 文件:
```
# ~/.config/gitea/.gitignore
config.env
runners/*/.runner
runners/*/.env
```
确保敏感文件不会被意外提交。
## 故障排查
### 连接失败
**症状**
```
❌ 连接失败 (HTTP 404)
请检查 URL 和 Token 是否正确
```
**解决方案**
1. 检查 URL 是否正确(不要包含 `/api/v1`
2. 检查网络连接
3. 尝试在浏览器中访问 URL
4. 检查防火墙设置
### Token 无效
**症状**
```
❌ 连接失败 (HTTP 401)
```
**解决方案**
1. Token 可能已过期,重新生成
2. Token 可能被撤销,检查 Gitea 设置
3. Token 复制不完整,重新复制
4. 确认 Token 有足够的权限
### 权限不足
**症状**
```
⚠ 缺少 admin:org 权限(可能影响组织 Runner 创建)
```
**解决方案**
1. 重新创建 Token选择更多权限
2. 联系 Gitea 管理员提升权限
3. 使用个人 Runner 而非组织 Runner
### 配置文件损坏
**症状**
```
❌ 配置文件不完整,请运行 /gitea-reset 重新配置
```
**解决方案**
```bash
/gitea-reset
```
## 下一步
配置完成后,你可以:
1. **创建第一个 Runner**(自动后台启动):
```
用户: 创建一个 runner
```
- 默认创建全局 Runner可用于所有组织和仓库
- 如果 Token 没有管理员权限,自动降级到组织 Runner
- 创建后 Runner 会自动在后台运行
2. **创建仓库**
```bash
/gitea-create-repo my-project
```
3. **生成 Workflow**
```
用户: 为我的项目生成 workflow
```
4. **查看配置**
```bash
/gitea-config
```
---
**相关文档**
- [Runner 管理](./runner-management.md)
- [Workflow 生成器](./workflow-generator.md)
- [仓库操作](./repository-operations.md)
- [API 参考](./api-reference.md)

View File

@@ -0,0 +1,692 @@
# Gitea 故障排查
常见问题的诊断和解决方案。
## 配置问题
### 1. 配置文件不存在
**症状**
```
❌ Gitea 未配置,请运行 /gitea-reset
```
**原因**
- 首次使用,未进行配置
- 配置文件被删除或移动
**解决方案**
```bash
/gitea-reset
```
按照提示完成配置。
---
### 2. Token 无效或已过期
**症状**
```
Token 状态: ✗ 无效或已过期
```
**原因**
- Token 已过期
- Token 被撤销
- Token 复制不完整
**解决方案**
1. 重新生成 Token
- 登录 Gitea → 设置 → 应用 → 访问令牌
- 生成新 Token权限repo, admin:org, write:runner
2. 更新配置:
```bash
/gitea-reset
```
3. 或手动编辑配置文件:
```bash
vim ~/.config/gitea/config.env
# 更新 GITEA_TOKEN=new_token
```
---
### 3. 连接 Gitea 失败
**症状**
```
❌ 连接失败 (HTTP 404)
❌ 连接失败 (HTTP 500)
```
**原因**
- URL 错误
- 网络问题
- Gitea 服务器宕机
**诊断步骤**
1. 检查 URL
```bash
source ~/.config/gitea/config.env
echo $GITEA_URL
```
2. 测试网络连接:
```bash
curl -s "$GITEA_URL/api/v1/version"
```
3. 在浏览器中访问 URL
**解决方案**
- 修正 URL不要包含 `/api/v1`
- 检查网络连接
- 联系 Gitea 管理员
---
### 4. 权限不足
**症状**
```
❌ 权限不足 (HTTP 403)
⚠ 缺少 admin:org 权限
```
**原因**
- Token 权限不足
- 不是组织成员
**解决方案**
1. 重新创建 Token选择更多权限
2. 联系组织管理员添加为成员
3. 使用个人仓库/Runner 代替组织级别
---
## Runner 问题
### 1. Runner 创建失败
**症状**
```
❌ 获取注册 Token 失败
❌ Runner 注册失败
```
**原因**
- Token 缺少 `write:runner` 权限
- 组织不存在
- 网络问题
**诊断步骤**
1. 检查 Token 权限:
```bash
/gitea-config
```
2. 验证组织存在:
```bash
source ~/.config/gitea/config.env
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/$GITEA_DEFAULT_ORG"
```
**解决方案**
- 更新 Token 权限
- 设置正确的组织:`/gitea-switch-org <org>`
---
### 2. Runner 无法启动
**症状**
```bash
act_runner daemon --config ...
# 进程立即退出或报错
```
**原因**
- `act_runner` 未安装
- 配置文件错误
- 端口被占用cache service
**诊断步骤**
1. 检查 act_runner
```bash
which act_runner
act_runner --version
```
2. 验证配置文件:
```bash
cat ~/.config/gitea/runners/runner-name/config.yaml
```
3. 检查端口占用:
```bash
lsof -i :9000
```
**解决方案**
1. 安装 act_runner
```bash
brew install act_runner
```
2. 修复配置文件(确保路径正确)
3. 更改端口(如果 9000 被占用):
```bash
vim ~/.config/gitea/runners/runner-name/config.yaml
# 修改 port: 9001
```
---
### 3. Runner 已注册但不在线
**症状**
- Gitea 中看不到 Runner
- Workflow 无法分配到 Runner
**原因**
- Runner 进程未运行
- 网络连接问题
- Labels 不匹配
**诊断步骤**
1. 检查 Runner 进程:
```bash
/gitea-list-runners
```
2. 查看 Runner 日志:
```bash
tail -f ~/.config/gitea/runners/runner-name/runner.log
```
3. 测试 Gitea 连接:
```bash
source ~/.config/gitea/config.env
curl -s "$GITEA_URL/api/v1/version"
```
**解决方案**
1. 启动 Runner
```bash
act_runner daemon --config ~/.config/gitea/runners/runner-name/config.yaml
```
2. 检查网络和防火墙设置
3. 验证 Labels 匹配
---
### 4. Labels 不匹配
**症状**
```
Workflow 一直 pending不执行
```
**原因**
- Workflow 的 `runs-on` 与 Runner labels 不匹配
**诊断步骤**
1. 检查 Runner labels
```bash
/gitea-list-runners
# 或
cat ~/.config/gitea/runners/runner-name/.runner | jq '.labels'
```
2. 检查 Workflow
```yaml
jobs:
build:
runs-on: darwin-arm64 # 这个 label 必须存在
```
**解决方案**
1. 修改 Workflow 的 `runs-on` 匹配 Runner labels
2. 或重新创建 Runner 使用正确的 labels
---
## Workflow 问题
### 1. Workflow 不触发
**症状**
- 推送代码后 Workflow 不执行
**原因**
- 路径过滤不匹配
- 分支不匹配
- Runner 不在线
**诊断步骤**
1. 检查触发条件:
```yaml
on:
push:
paths:
- 'backend/**' # 确保修改的文件在此路径下
```
2. 检查 Runner 状态:
```bash
/gitea-list-runners
```
**解决方案**
- 修改触发条件(删除或调整 `paths`
- 确保 Runner 在线
- 检查 Gitea Actions 是否启用
---
### 2. Workflow 执行失败
**症状**
```
Job failed
```
**原因**
- 构建命令错误
- 依赖缺失
- Secret 未配置
**诊断步骤**
1. 查看 Workflow 运行日志(在 Gitea UI 中)
2. 检查 Secrets 配置
3. 在本地手动执行构建命令
**解决方案**
- 修复构建命令
- 安装缺失的依赖
- 配置必需的 Secrets
---
### 3. Cache 不生效
**症状**
- 每次构建都重新下载依赖
- 构建时间没有减少
**原因**
- Cache key 每次都变化
- Cache 目录不正确
- Runner cache service 未启动
**诊断步骤**
1. 检查 cache key
```yaml
key: cache-${{ hashFiles('**/lockfile') }}
# 确保 lockfile 路径正确
```
2. 检查 Runner 配置:
```yaml
cache:
enabled: true
dir: "..."
```
**解决方案**
- 修正 cache key 的 hash 文件路径
- 确保 Runner cache service 启用
- 检查 cache 目录权限
---
## 仓库操作问题
### 1. 创建仓库失败
**症状**
```
❌ 仓库已存在
❌ Owner 不存在或无权限
```
**原因**
- 仓库名冲突
- 组织不存在
- Token 权限不足
**诊断步骤**
1. 检查仓库是否存在:
```bash
source ~/.config/gitea/config.env
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/owner/repo"
```
2. 列出组织的所有仓库:
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/owner/repos" | jq -r '.[].name'
```
**解决方案**
- 使用不同的仓库名
- 验证组织名正确
- 确保 Token 有 `repo` 权限
---
### 2. Git Remote 添加失败
**症状**
```
❌ origin remote 已存在
```
**原因**
- 已经配置了 origin remote
**解决方案**
1. 查看现有 remote
```bash
git remote -v
```
2. 更新 remote URL
```bash
git remote set-url origin <new-url>
```
3. 或删除后重新添加:
```bash
git remote remove origin
git remote add origin <new-url>
```
---
## 开发环境问题
### 1. Android SDK 未找到
**症状**
```
ANDROID_HOME not set
SDK location not found
```
**原因**
- 未安装 Android SDK
- 环境变量未配置
- Runner 用户不同
**诊断步骤**
1. 检查环境变量:
```bash
echo $ANDROID_HOME
ls $ANDROID_HOME
```
2. 检查 Runner 用户:
```bash
ps aux | grep act_runner
```
**解决方案**
1. 安装 Android SDK
```bash
brew install --cask android-commandlinetools
```
2. 配置环境变量(在 `~/.zshrc`
```bash
export ANDROID_HOME=~/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
```
3. 确保 Runner 以正确用户运行
---
### 2. JDK 版本错误
**症状**
```
Android Gradle Plugin requires Java 17
```
**原因**
- JDK 版本过低
- JAVA_HOME 指向错误版本
**诊断步骤**
```bash
java -version
echo $JAVA_HOME
```
**解决方案**
1. 安装 JDK 17
```bash
brew install openjdk@17
```
2. 更新 JAVA_HOME
```bash
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
export PATH=$PATH:$JAVA_HOME/bin
```
---
## API 调用问题
### 1. API 返回 404
**原因**
- Endpoint 错误
- 资源不存在
- 组织/仓库名错误
**解决方案**
- 检查 API 路径
- 验证资源存在
- 参考 [API 文档](./api-reference.md)
---
### 2. API 返回 401
**原因**
- Token 无效
- 未提供 Authorization header
**解决方案**
- 检查 Token
- 确保 header 格式正确:`Authorization: token YOUR_TOKEN`
---
### 3. API 返回 403
**原因**
- 权限不足
- Token 缺少必要权限
**解决方案**
- 重新创建 Token选择更多权限
- 联系管理员提升权限
---
## 性能问题
### 1. 构建速度慢
**原因**
- 未使用缓存
- 依赖下载慢
- Runner 性能不足
**解决方案**
1. 启用缓存:
```yaml
- uses: https://github.com/actions/cache@v3
with:
path: ~/.cache
key: cache-${{ hashFiles('**/lockfile') }}
```
2. 使用镜像源(如 Go proxy、npm registry
3. 升级 Runner 硬件
---
### 2. Cache 占用空间大
**原因**
- 长时间未清理
- 多个 Runner 共享 cache
**解决方案**
1. 定期清理:
```bash
~/.config/gitea/cleanup-cache.sh
```
2. 设置 crontab 自动清理:
```bash
crontab -e
# 添加: 0 3 * * 0 ~/.config/gitea/cleanup-cache.sh
```
---
## 诊断工具
### 快速诊断脚本
```bash
#!/bin/bash
echo "=== Gitea 环境诊断 ==="
echo ""
# 1. 配置文件
echo "1. 配置文件:"
config_file="$HOME/.config/gitea/config.env"
if [ -f "$config_file" ]; then
echo " ✓ 存在: $config_file"
source "$config_file"
echo " URL: $GITEA_URL"
else
echo " ✗ 不存在"
fi
echo ""
# 2. Token 验证
if [ -n "$GITEA_TOKEN" ]; then
echo "2. Token 验证:"
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/user")
http_code=$(echo "$response" | tail -n1)
if [ "$http_code" = "200" ]; then
echo " ✓ 有效"
else
echo " ✗ 无效 (HTTP $http_code)"
fi
echo ""
fi
# 3. Runner 状态
echo "3. Runner 状态:"
runners_dir="$HOME/.config/gitea/runners"
if [ -d "$runners_dir" ]; then
runner_count=$(ls -1 "$runners_dir" 2>/dev/null | wc -l | tr -d ' ')
echo " 配置数量: $runner_count"
for runner in $(ls -1 "$runners_dir" 2>/dev/null); do
config_file="$runners_dir/$runner/config.yaml"
if pgrep -f "act_runner daemon --config $config_file" > /dev/null; then
echo " ✓ $runner (运行中)"
else
echo " ✗ $runner (已停止)"
fi
done
else
echo " 未配置 Runner"
fi
echo ""
# 4. 工具检查
echo "4. 工具检查:"
for tool in act_runner jq curl git; do
if command -v $tool &> /dev/null; then
echo " ✓ $tool"
else
echo " ✗ $tool (未安装)"
fi
done
```
保存为 `~/.config/gitea/diagnose.sh` 并执行:
```bash
chmod +x ~/.config/gitea/diagnose.sh
~/.config/gitea/diagnose.sh
```
---
## 获取帮助
如果问题仍未解决:
1. **查看日志**
- Runner 日志:`~/.config/gitea/runners/runner-name/runner.log`
- Gitea UI 中的 Workflow 运行日志
2. **检查文档**
- [环境配置](./setup-guide.md)
- [Runner 管理](./runner-management.md)
- [API 参考](./api-reference.md)
3. **联系支持**
- Gitea 官方文档https://docs.gitea.com/
- Gitea 社区论坛https://discourse.gitea.io/
---
## 版本
- **文档版本**: 1.0
- **最后更新**: 2026-01-12

View File

@@ -0,0 +1,624 @@
# Gitea Workflow 生成器
根据项目类型自动生成 CI/CD workflow 文件。
## 概述
Gitea Actions 使用 GitHub Actions 兼容的 workflow 语法,定义在 `.gitea/workflows/*.yml` 文件中。
本 skill 提供:
- 自动检测项目类型
- 根据类型生成适配的 workflow 模板
- 自动填充项目特定变量
- 智能配置触发条件和缓存策略
## 项目类型模板
| 类型 | 模板文档 | 适用场景 |
|------|---------|---------|
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
| 微信小程序 | [wechat-miniprogram.md](./workflow-templates/wechat-miniprogram.md) | 微信小程序 CI/CD |
## 自动生成流程
### 步骤 1: 检测项目类型
当用户说"为我的项目生成 workflow"时AI 会自动检测项目类型:
```bash
# Go 项目特征
if [ -f "go.mod" ] || [ -f "main.go" ]; then
project_type="go"
fi
# Node.js 项目特征
if [ -f "package.json" ]; then
project_type="nodejs"
# 细分类型
if grep -q "\"react\"" package.json; then
framework="react"
elif grep -q "\"vue\"" package.json; then
framework="vue"
elif grep -q "\"vite\"" package.json; then
framework="vite"
fi
fi
# Android 项目特征
if [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
if [ -d "app/src/main/java" ] || [ -d "app/src/main/kotlin" ]; then
project_type="android"
fi
fi
# 微信小程序特征
if [ -f "project.config.json" ] && [ -f "app.json" ]; then
project_type="wechat-miniprogram"
fi
```
### 步骤 2: 提示用户确认
```
检测到项目类型: Go 后端服务
服务目录: ./backend
是否正确? [Y/n]
```
### 步骤 3: 收集项目信息
根据项目类型,收集必要信息:
**Go 项目**
- 服务目录(如 `./backend`
- 服务名称(如 `api-server`
- 是否需要 Docker 构建
- Docker Registry 地址
**Node.js 项目**
- 项目目录
- 包管理器npm/pnpm/yarn
- 构建命令
- 输出目录
**Android 项目**
- 模块名称(如 `app`
- 构建类型release/debug
- 签名配置
**微信小程序**
- 项目目录
- 版本号规则
- 上传配置
### 步骤 4: 选择 Runner
```
请选择 Runner:
1) darwin-arm64 (macOS ARM64)
2) ubuntu-latest (Docker)
3) 自定义
[1]:
```
### 步骤 5: 生成 Workflow 文件
基于模板生成 workflow自动替换变量
```yaml
name: Backend Service - Build & Publish
on:
push:
paths:
- 'backend/**' # 自动填充:项目目录
- '.gitea/workflows/backend.yml'
tags:
- 'backend-*' # 自动填充:服务前缀
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
SERVICE_PREFIX: backend # 自动填充:服务名称
SERVICE_DIR: backend # 自动填充:服务目录
GOPROXY: https://goproxy.cn,direct
jobs:
build-and-publish:
name: Build & Publish
runs-on: darwin-arm64 # 自动填充Runner
# ... 其余配置
```
### 步骤 6: 创建文件
```bash
# 创建 .gitea/workflows 目录
mkdir -p .gitea/workflows
# 写入 workflow 文件
cat > .gitea/workflows/backend.yml << 'EOF'
[生成的 workflow 内容]
EOF
echo "✓ Workflow 已生成: .gitea/workflows/backend.yml"
```
### 步骤 7: 提示配置 Secrets
根据 workflow 需求,提示用户配置 Secrets
```
需要配置以下 Secrets:
- REGISTRY_PASSWORD: Docker Registry 密码
- RELEASE_TOKEN: Gitea API Token创建 Release 用)
配置方法:
1. 在 Gitea 中打开仓库设置
2. 进入 Settings → Secrets → Actions
3. 添加上述 Secrets
或使用 API:
source ~/.config/gitea/config.env
echo -n "password" | base64 | xargs -I {} \
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data":"{}"}' \
"$GITEA_URL/api/v1/repos/owner/repo/actions/secrets/REGISTRY_PASSWORD"
```
## Workflow 基础结构
### 完整骨架
```yaml
name: Service Name - Build & Publish
# 触发条件
on:
push:
paths:
- 'service-dir/**'
- '.gitea/workflows/this-workflow.yml'
tags:
- 'service-prefix-*'
# 并发控制
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# 环境变量
env:
SERVICE_PREFIX: service-name
SERVICE_DIR: service-dir
jobs:
build:
name: Build
runs-on: darwin-arm64
permissions:
contents: read
packages: write
outputs:
version: ${{ steps.vars.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# 项目特定的构建步骤
release:
name: Create Release
runs-on: darwin-arm64
needs: build
if: startsWith(github.ref, 'refs/tags/service-prefix-')
steps:
# Release 步骤
```
## 触发条件配置
### 常用触发模式
```yaml
on:
# 分支推送
push:
branches: [main, develop]
# 路径过滤(推荐:仅相关文件变更时触发)
push:
paths:
- 'src/**'
- '*.yml'
# Tag 推送(用于 Release
push:
tags:
- 'v*'
- 'service-*'
# Pull Request
pull_request:
branches: [main]
# 手动触发
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'staging'
# 定时触发
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点
```
### 并发控制
避免同一分支的多个 workflow 同时运行:
```yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 取消旧的运行
```
## 通用组件
### Checkout
```yaml
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # 完整历史,用于 git describe
# fetch-depth: 1 # 仅最新提交,加快速度
```
### 变量设置
```yaml
- name: Set variables
id: vars
run: |
git_tag=$(git describe --tags --abbrev=0 --always)
registry=$(echo ${{ github.server_url }} | cut -d '/' -f 3)
# 写入环境变量(当前 job 可用)
{
echo "git_tag=${git_tag}"
echo "registry=${registry}"
} >> $GITHUB_ENV
# 写入输出(其他 job 可用)
echo "version=${git_tag}" >> $GITHUB_OUTPUT
```
### Cache Action
```yaml
- name: Cache dependencies
uses: https://github.com/actions/cache@v3
with:
path: |
~/.cache/directory
./node_modules
key: cache-name-${{ hashFiles('**/lockfile') }}
restore-keys: cache-name-
```
**各语言缓存路径**
| 语言 | 缓存路径 | Key 文件 |
|------|---------|----------|
| Go | `~/go/pkg/mod`, `~/.cache/go-build` | `go.mod`, `go.sum` |
| Node.js (pnpm) | `~/.pnpm-store`, `node_modules` | `pnpm-lock.yaml` |
| Node.js (npm) | `~/.npm`, `node_modules` | `package-lock.json` |
| Gradle | `~/.gradle/caches`, `~/.gradle/wrapper` | `*.gradle*`, `gradle-wrapper.properties` |
### Docker 构建推送
```yaml
- name: Docker - Login
uses: docker/login-action@v3
with:
registry: ${{ env.registry }}
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Docker - Setup Buildx
uses: docker/setup-buildx-action@v3
- name: Docker - Build & Push
uses: docker/build-push-action@v6
with:
context: ./service-dir
file: ./service-dir/Dockerfile
push: true
platforms: linux/amd64
tags: |
${{ env.registry }}/owner/image:latest
${{ env.registry }}/owner/image:${{ env.git_tag }}
cache-from: type=registry,ref=image:buildcache
cache-to: type=registry,ref=image:buildcache,mode=max
```
### Artifact 上传/下载
```yaml
# 上传
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: build-artifact
path: dist/
# 下载(另一个 job
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: build-artifact
path: dist/
```
### 通知 Webhook
```yaml
- name: Notify
if: always()
continue-on-error: true
env:
WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
run: |
status="${{ job.status }}"
[ "$status" = "success" ] && text="Build Success" || text="Build Failed"
curl -s -H "Content-Type: application/json" -X POST \
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"${{ env.SERVICE_PREFIX }} ${text}\"}}" \
"$WEBHOOK_URL"
```
### Release 创建Gitea API
```yaml
- name: Create Release
env:
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
git_tag=$(git describe --tags --abbrev=0)
api_url="${{ github.server_url }}/api/v1"
repo="${{ github.repository }}"
# 创建 Release
release_id=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
"${api_url}/repos/${repo}/releases" | jq -r '.id')
# 上传附件
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-F "attachment=@dist/artifact.zip" \
"${api_url}/repos/${repo}/releases/${release_id}/assets"
```
## Secrets 配置
### 通用 Secrets
| Secret | 用途 | 适用项目 |
|--------|------|---------|
| `REGISTRY_PASSWORD` | Docker Registry 密码 | 需要 Docker 发布的项目 |
| `RELEASE_TOKEN` | Gitea API 令牌 | 需要创建 Release 的项目 |
### 安全最佳实践
1. **不要在日志中打印 secrets**
2. **使用 `vars.` 存储非敏感变量**如用户名、URL
3. **secrets 仅用于敏感信息**(如密码、密钥)
4. **定期轮换密钥**
### 配置 Secrets
**方法 1: 通过 Gitea UI**
1. 打开仓库 → Settings → Secrets → Actions
2. 点击 "Add Secret"
3. 输入 Name 和 Value
4. 保存
**方法 2: 通过 API**
```bash
source ~/.config/gitea/config.env
secret_name="REGISTRY_PASSWORD"
secret_value="my-password"
# Base64 编码
encoded=$(echo -n "$secret_value" | base64)
# 调用 API
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":\"${encoded}\"}" \
"$GITEA_URL/api/v1/repos/owner/repo/actions/secrets/$secret_name"
```
## 最佳实践
### 1. 路径过滤
仅相关文件变更时触发,避免无关构建:
```yaml
on:
push:
paths:
- 'backend/**'
- '.gitea/workflows/backend.yml'
```
### 2. Tag 命名规范
使用前缀区分不同服务:
```bash
git tag backend-1.0.0 && git push origin backend-1.0.0
git tag frontend-1.0.0 && git push origin frontend-1.0.0
git tag android-1.0.0 && git push origin android-1.0.0
```
### 3. Job 输出传递
```yaml
jobs:
build:
outputs:
version: ${{ steps.vars.outputs.version }}
deploy:
needs: build
env:
VERSION: ${{ needs.build.outputs.version }}
```
### 4. 条件执行
```yaml
# 仅 Tag 推送时执行
if: startsWith(github.ref, 'refs/tags/')
# 仅主分支执行
if: github.ref == 'refs/heads/main'
# 始终执行(用于通知)
if: always()
```
### 5. 使用缓存加速构建
合理使用缓存可以显著减少构建时间:
```yaml
# Go 项目
- name: Cache Go modules
uses: https://github.com/actions/cache@v3
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: go-${{ hashFiles('**/go.sum') }}
# Node.js 项目
- name: Cache pnpm store
uses: https://github.com/actions/cache@v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
```
## 项目特定模板
### Go 后端服务
详见:[Go 后端模板](./workflow-templates/go-backend.md)
**特点**
- 支持 monorepo 和 polyrepo
- Docker 多阶段构建
- 自动版本管理
- Release 创建和附件上传
### Node.js 前端应用
详见:[Node.js 前端模板](./workflow-templates/nodejs-frontend.md)
**特点**
- pnpm/npm/yarn 支持
- 依赖缓存优化
- 静态资源构建
- Docker 部署
### Android 应用
详见:[Android 应用模板](./workflow-templates/android-app.md)
**特点**
- Gradle 缓存优化
- 多 flavor 支持
- 签名配置
- APK/AAB 生成
### 微信小程序
详见:[微信小程序模板](./workflow-templates/wechat-miniprogram.md)
**特点**
- 自动版本号管理
- miniprogram-ci 集成
- 预览/上传自动化
- 体验版分发
## 快速参考
| 任务 | 命令/语法 |
|------|----------|
| 获取 git tag | `git describe --tags --abbrev=0 --always` |
| 提取 registry | `echo ${{ github.server_url }} \| cut -d '/' -f 3` |
| 设置环境变量 | `echo "KEY=value" >> $GITHUB_ENV` |
| 设置输出 | `echo "key=value" >> $GITHUB_OUTPUT` |
| 计算哈希 | `sha256sum file1 file2 \| sha256sum \| head -c 16` |
## 使用方式
1. **自然语言触发**
```
用户: 为我的项目生成 workflow
用户: 创建 CI/CD 配置
用户: 添加自动化构建
```
2. **AI 自动检测项目类型**
3. **填充项目特定信息**
4. **生成 workflow 文件**`.gitea/workflows/*.yml`
5. **配置 Secrets**(如需要)
6. **推送代码触发**
```bash
git add .gitea/workflows
git commit -m "Add CI/CD workflow"
git push origin main
```
## 相关资源
- [Gitea Actions 文档](https://docs.gitea.com/usage/actions/overview)
- [GitHub Actions Workflow 语法](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
- [环境配置指南](./setup-guide.md)
- [Runner 管理](./runner-management.md)
## 版本
- **文档版本**: 1.0
- **最后更新**: 2026-01-12
- **整合内容**: gitea-workflow skill 的所有模板