- 修复 delete-runner.md 中的 API 端点从 /api/v1/admin/runners 改为 /api/v1/admin/actions/runners - 更新 SKILL.md 和 repository-operations.md 文档 - 更新 opencode.json 配置
20 KiB
20 KiB
Gitea 仓库操作
创建和管理 Gitea 仓库的完整指南。
概述
本文档介绍如何通过 Gitea API 创建和管理仓库,包括:
- 创建组织/用户仓库
- 初始化仓库结构
- 配置 Actions 设置
- 管理 Secrets 和 Variables
- 设置 Webhooks
快速使用
核心原则(简洁高效)
- 智能解析:自动识别
组织/仓库格式,优先使用指定组织而非默认组织 - 默认私有:除非明确指定,所有仓库默认创建为私有
- 简化验证:默认假设组织存在,API创建失败时清晰提示解决方案
- Git集成:自动检查Git仓库状态,提供一键初始化、提交、推送完整流程
- 错误处理:API失败时给出具体操作建议,而非预先复杂验证
常用命令(简洁高效)
# 智能解析组织/仓库格式(默认私有)
/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失败时给出清晰解决方案(如组织不存在)
创建仓库
使用命令创建
快速创建(使用默认组织):
/gitea-create-repo my-project
指定 owner:
/create-gitea-repo ai/my-project
/create-gitea-repo username/my-project
指定可见性:
/create-gitea-repo ai/my-project public
/create-gitea-repo ai/my-project private
使用自然语言
用户: 创建一个新的 gitea 仓库,名为 my-project
用户: 在 ai 组织下创建仓库 test-repo
用户: 创建公开仓库 open-source-project
AI 会自动:
- 加载 Gitea 配置
- 解析仓库名称和 owner
- 调用 API 创建仓库
- 提示是否添加为 Git remote
- 显示仓库信息(URLs 等)
创建流程详解
步骤 1: 加载配置
config_file="$HOME/.config/gitea/config.env"
if [ ! -f "$config_file" ]; then
echo "❌ Gitea 未配置,请运行 /gitea-reset"
exit 1
fi
source "$config_file"
步骤 2: 智能解析输入(简洁高效版)
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: 验证仓库名
# 仓库名只能包含字母、数字、下划线、连字符和点
if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
echo "❌ 仓库名只能包含字母、数字、下划线、连字符和点"
exit 1
fi
步骤 4: 调用 API 创建(带详细错误处理)
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: 提取仓库信息
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 仓库集成(简洁高效版)
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 配置)"
仓库初始化
初始化基本结构
创建常见的仓库文件:
# 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
- 打开仓库 → Settings → Secrets → Actions
- 点击 "New Secret"
- 输入 Name 和 Value
- 保存
方法 2: 通过 API
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 用于非敏感配置:
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
#!/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
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
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/hooks" | jq .
删除 Webhook
hook_id=1
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/hooks/$hook_id"
仓库设置
更新仓库信息
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"
启用/禁用功能
# 禁用 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"
协作者管理
添加协作者
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: 管理员
列出协作者
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/collaborators" | jq .
移除协作者
username="collaborator"
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/collaborators/$username"
常见操作
检查仓库是否存在
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
归档仓库
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/archive"
echo "✓ 仓库已归档"
删除仓库
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
批量操作
批量创建仓库
#!/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
#!/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 - 仓库已存在
解决:
# 列出所有仓库
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/$org/repos" | jq -r '.[].name'
Secret 配置失败
症状: HTTP 404 - 仓库不存在
解决:
# 检查仓库是否存在
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo"
权限不足
症状: HTTP 403 - Forbidden
解决:
- 检查 Token 是否有
repo权限 - 检查是否是仓库/组织的成员
- 使用管理员账户
相关资源
版本
- 文档版本: 1.1
- 最后更新: 2026-01-23
- 主要改进:
- 智能解析输入:优先使用指定组织而非默认组织
- 组织存在性验证和清晰错误提示
- 默认私有仓库策略(除非明确指定公开)
- 增强的错误处理:Token验证、权限检查、详细错误消息
- 完整的Git集成流程:可选自动初始化和推送