- 新增:统一的 git 命令文档(add/commit/push/pull 等) - 新增:整合的 Gitea 技能文档(API、运行器、工作流等) - 新增:工作流模板(Android、Go、Node.js 等) - 移除:已弃用的旧命令脚本和发布脚本 - 改进:.gitignore 添加敏感文件保护规则 - 改进:AGENTS.md 完善了开发规范和示例 此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
694 lines
14 KiB
Markdown
694 lines
14 KiB
Markdown
# 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
|