Files
opencode/skill/gitea/repository-operations.md
voson 32d674a4c0 fix(gitea): 修复 delete-runner API 端点错误
- 修复 delete-runner.md 中的 API 端点从 /api/v1/admin/runners 改为 /api/v1/admin/actions/runners
- 更新 SKILL.md 和 repository-operations.md 文档
- 更新 opencode.json 配置
2026-01-28 08:48:04 +08:00

865 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gitea 仓库操作
创建和管理 Gitea 仓库的完整指南。
## 概述
本文档介绍如何通过 Gitea API 创建和管理仓库,包括:
- 创建组织/用户仓库
- 初始化仓库结构
- 配置 Actions 设置
- 管理 Secrets 和 Variables
- 设置 Webhooks
## 快速使用
### 核心原则(简洁高效)
1. **智能解析**:自动识别 `组织/仓库` 格式,优先使用指定组织而非默认组织
2. **默认私有**:除非明确指定,所有仓库默认创建为私有
3. **简化验证**默认假设组织存在API创建失败时清晰提示解决方案
4. **Git集成**自动检查Git仓库状态提供一键初始化、提交、推送完整流程
5. **错误处理**API失败时给出具体操作建议而非预先复杂验证
### 常用命令(简洁高效)
```bash
# 智能解析组织/仓库格式(默认私有)
/gitea-create-repo shigongcao/shigongcao
# 使用默认组织创建公开仓库
/gitea-create-repo my-project public
# 自动检查Git状态提供完整初始化流程
/gitea-create-repo org/project
# 特性说明:
# 1. 自动识别组织/仓库格式
# 2. 默认创建私有仓库除非指定public
# 3. 自动检查当前目录Git状态
# 4. 提供一键初始化、提交、推送选项
# 5. API失败时给出清晰解决方案如组织不存在
```
## 创建仓库
### 使用命令创建
**快速创建**(使用默认组织):
```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"
# 智能解析:优先使用用户指定的组织
if [[ "$input" =~ / ]]; then
owner=$(echo "$input" | cut -d'/' -f1)
repo=$(echo "$input" | cut -d'/' -f2)
echo "使用指定组织: $owner"
echo "提示假设组织存在如不存在会在API创建时提示"
else
# 未指定组织,使用默认组织或当前用户
if [ -z "$GITEA_DEFAULT_ORG" ]; then
# 获取当前用户
echo "未指定组织,获取当前用户..."
owner=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"${GITEA_URL}/api/v1/user" | jq -r '.login')
if [ -z "$owner" ] || [ "$owner" = "null" ]; then
echo "❌ 无法获取当前用户信息,请使用 组织/仓库 格式"
echo "例如:/gitea-create-repo shigongcao/shigongcao"
exit 1
fi
echo "使用当前用户: $owner"
else
owner="$GITEA_DEFAULT_ORG"
echo "使用默认组织: $owner"
fi
repo="$input"
fi
# 解析可见性:默认私有仓库(除非明确指定公开)
visibility="${2:-private}"
if [[ "$visibility" != "private" && "$visibility" != "public" ]]; then
echo "⚠️ 可见性参数无效,使用默认值: private"
visibility="private"
fi
private_bool=$([ "$visibility" = "private" ] && echo "true" || echo "false")
echo "仓库可见性: $visibility"
# 提前检查当前目录是否是 Git 仓库(为后续步骤做准备)
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "⚠️ 当前目录不是 Git 仓库"
echo "提示:创建远程仓库后可以初始化本地 Git 仓库并推送代码"
fi
```
#### 步骤 3: 验证仓库名
```bash
# 仓库名只能包含字母、数字、下划线、连字符和点
if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
echo "❌ 仓库名只能包含字母、数字、下划线、连字符和点"
exit 1
fi
```
#### 步骤 4: 调用 API 创建(带详细错误处理)
```bash
echo "正在创建仓库: $owner/$repo ($visibility)"
# 检查 Token 权限
echo "检查 Token 权限..."
user_info=$(curl -s -H "Authorization: token $GITEA_TOKEN" "${GITEA_URL}/api/v1/user")
username=$(echo "$user_info" | jq -r '.login // empty')
if [ -z "$username" ] || [ "$username" = "null" ]; then
echo "❌ Token 无效或权限不足"
echo "请检查:"
echo "1. Token 是否有效"
echo "2. Token 是否有 'repo' 权限"
echo "3. GITEA_URL 是否正确"
exit 1
fi
echo "✓ Token 有效,当前用户: $username"
# 尝试创建组织仓库
echo "调用 Gitea API 创建仓库..."
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\",
\"description\": \"\"
}" \
"${GITEA_URL}/api/v1/orgs/${owner}/repos")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
# 处理响应
case "$http_code" in
201)
echo "✓ 仓库创建成功"
;;
400)
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
echo "❌ 请求参数错误: $error_msg"
echo "请检查:"
echo "1. 仓库名格式是否正确"
echo "2. 是否缺少必要参数"
exit 1
;;
403)
echo "❌ 权限不足"
echo "请检查:"
echo "1. 是否有在组织 '$owner' 下创建仓库的权限"
echo "2. 是否是组织成员"
echo "3. Token 权限是否足够"
exit 1
;;
404)
# 组织不存在API 返回 404
echo "❌ API 创建失败:组织 '$owner' 不存在"
# 检查是否为当前用户(可能用户输入的是自己的用户名)
if [ "$owner" = "$username" ]; then
echo "检测到 '$owner' 是当前用户,创建个人仓库..."
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${repo}\",
\"private\": ${private_bool},
\"auto_init\": false,
\"default_branch\": \"main\"
}" \
"${GITEA_URL}/api/v1/user/repos")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" = "201" ]; then
echo "✓ 个人仓库创建成功"
else
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
echo "❌ 个人仓库创建失败 (HTTP $http_code): $error_msg"
exit 1
fi
else
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "组织不存在,请先创建组织"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "您可以通过以下方式创建组织 '$owner'"
echo "1. 访问 ${GITEA_URL}/org/create"
echo "2. 使用 Gitea Web 界面创建组织"
echo "3. 或者使用个人仓库格式: $username/$repo"
echo ""
echo "创建组织后,重新运行此命令创建仓库。"
exit 1
fi
;;
409)
echo "❌ 仓库已存在: $owner/$repo"
echo "请使用不同的仓库名或删除现有仓库"
exit 1
;;
*)
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
echo "❌ 创建失败 (HTTP $http_code): $error_msg"
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 仓库集成(简洁高效版)
```bash
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Git 仓库集成"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# 检查是否是 Git 仓库
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "当前目录不是 Git 仓库"
read -p "是否初始化 Git 仓库并添加 remote? [Y/n] " init_git
if [[ "$init_git" =~ ^[Nn]$ ]]; then
echo "跳过 Git 初始化,仅创建远程仓库。"
echo "您可以在需要时手动执行:"
echo " git init"
echo " git remote add origin \"$clone_url\""
exit 0
fi
# 初始化 Git 仓库
echo "正在初始化 Git 仓库..."
git init
echo "✓ Git 仓库已初始化"
# 检查 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 已更新为: $clone_url"
else
echo "保持现有的 origin remote"
fi
else
git remote add origin "$clone_url"
echo "✓ origin remote 已添加: $clone_url"
fi
# 可选:添加文件、提交并推送
echo ""
read -p "是否添加当前文件、提交并推送到远程仓库? [Y/n] " push_code
if [[ ! "$push_code" =~ ^[Nn]$ ]]; then
echo "添加所有文件到暂存区..."
git add .
echo "创建初始提交..."
git commit -m "Initial commit" || {
echo "⚠️ 提交失败(可能没有文件可提交)"
echo "请手动添加文件后提交"
}
echo "推送到远程仓库 (main 分支)..."
git branch -M main 2>/dev/null
git push -u origin main
echo "✓ 代码已推送到远程仓库"
else
echo "跳过推送,您可以在需要时手动推送代码。"
fi
else
# 已经是 Git 仓库,询问是否添加/更新 remote
echo "当前目录已是 Git 仓库"
read -p "是否添加/更新 origin remote 为此仓库? [Y/n] " add_remote
if [[ ! "$add_remote" =~ ^[Nn]$ ]]; then
# 检查 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 已更新"
else
echo "保持现有的 origin remote"
fi
else
git remote add origin "$clone_url"
echo "✓ origin remote 已添加"
fi
fi
fi
# 显示当前状态
echo ""
echo "当前 Git 状态:"
git status --short 2>/dev/null || echo "(非 Git 仓库)"
echo ""
echo "Remote 配置:"
git remote -v 2>/dev/null || echo "(无 remote 配置)"
```
## 仓库初始化
### 初始化基本结构
创建常见的仓库文件:
```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.1
- **最后更新**: 2026-01-23
- **主要改进**:
- 智能解析输入:优先使用指定组织而非默认组织
- 组织存在性验证和清晰错误提示
- 默认私有仓库策略(除非明确指定公开)
- 增强的错误处理Token验证、权限检查、详细错误消息
- 完整的Git集成流程可选自动初始化和推送