- 新增 setup.sh 配置脚本 - 新增 api-examples.sh API 函数库 - 新增 gitea-cli.py Python CLI 工具 - 完善文档结构 (1640 行) - 添加实际用例和工作流示例 - 增强故障排除和最佳实践指南
44 KiB
name, description
| name | description |
|---|---|
| gitea-actor | 类似 GitHub Copilot 的 Gitea 操作技能,支持仓库管理、PR/Issue 操作、代码审查等 |
Gitea-Actor
此技能提供类似 GitHub Copilot 的 Gitea 操作功能,支持自托管 Gitea 实例的完整 Git 工作流。
何时使用此技能
当用户需要操作 Gitea 仓库时使用此技能,包括:
- 创建、克隆、管理 Gitea 仓库
- 处理 Pull Request(合并请求)
- 管理 Issue 和任务
- 进行代码审查和评论
- 管理分支、标签和版本
- 配置 Gitea 实例和身份验证
触发关键词:gitea, git, repository, repo, pull request, pr, issue, code review, merge, branch, tag, clone, push, pull
前置要求
1. Gitea 实例配置
用户需要提供 Gitea 实例的 URL 和个人访问令牌。
2. 环境变量配置
# 设置 Gitea 实例 URL(默认为 https://gitea.com)
export GITEA_URL="https://your-gitea-instance.com"
# 设置个人访问令牌
export GITEA_TOKEN="your_personal_access_token_here"
3. 验证配置
# 验证 Gitea 连接
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | jq .
快速开始
方法一:使用配置脚本(推荐)
# 下载并运行配置脚本
curl -s https://raw.githubusercontent.com/your-repo/gitea-actor/main/scripts/setup.sh | bash
# 或手动下载后运行
chmod +x setup.sh
./setup.sh
方法二:手动配置
# 设置环境变量
export GITEA_URL="https://your-gitea-instance.com"
export GITEA_TOKEN="your_personal_access_token_here"
# 验证连接
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | jq .
方法三:使用 Python CLI 工具
# 安装依赖
pip install requests
# 使用 CLI
python gitea-cli.py config test
核心功能指令
1. 仓库管理
1.1 创建仓库
# 创建新仓库
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"my-new-repo", "description":"My new repository", "private":false}' \
"$GITEA_URL/api/v1/user/repos"
1.2 克隆仓库
# 克隆仓库
git clone "$GITEA_URL/<owner>/<repo>.git"
cd <repo>
1.3 列出用户仓库
# 列出用户的所有仓库
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user/repos" | jq '.[] | .full_name'
2. Pull Request 管理
2.1 创建 Pull Request
# 创建 PR
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title":"Feature: Add new functionality",
"body":"This PR adds new functionality to improve performance.",
"head":"feature-branch",
"base":"main"
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls"
2.2 列出 Pull Requests
# 列出仓库的所有 PR
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls" | jq '.[] | .number, .title'
2.3 合并 Pull Request
# 合并 PR
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"Do":"merge"}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls/<pr-number>/merge"
3. Issue 管理
3.1 创建 Issue
# 创建新 Issue
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title":"Bug: Fix memory leak",
"body":"There is a memory leak in the cache module.",
"labels":["bug", "high-priority"]
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/issues"
3.2 分配 Issue
# 分配 Issue 给用户
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"assignees":["username"]}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/issues/<issue-number>/assignees"
4. 代码审查
4.1 添加 PR 评论
# 在 PR 中添加评论
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body":"This looks good! Just one small suggestion...",
"path":"src/main.js",
"line":42
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls/<pr-number>/comments"
4.2 查看代码差异
# 获取 PR 的差异
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls/<pr-number>.diff"
5. 分支和标签管理
5.1 创建分支
# 从现有分支创建新分支
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"new_branch_name":"feature/new-feature",
"old_branch_name":"main"
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/branches"
5.2 创建标签
# 创建新标签
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tag_name":"v1.0.0",
"message":"Release version 1.0.0",
"target":"main"
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/tags"
工作流程示例
示例 1:完整的 PR 工作流
# 1. 创建功能分支
git checkout -b feature/new-feature
# 2. 进行更改并提交
git add .
git commit -m "Add new feature"
# 3. 推送到远程
git push origin feature/new-feature
# 4. 创建 Pull Request
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title":"Feature: Add new feature",
"body":"## Description\nThis PR adds a new feature to improve user experience.\n\n## Changes\n- Added new API endpoint\n- Updated documentation\n- Added tests",
"head":"feature/new-feature",
"base":"main"
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/pulls"
示例 2:Issue 跟踪工作流
# 1. 创建 Bug Issue
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title":"Bug: Application crashes on startup",
"body":"## Steps to reproduce\n1. Start the application\n2. Click on settings\n3. Application crashes\n\n## Expected behavior\nApplication should not crash",
"labels":["bug", "critical"],
"assignees":["developer1"]
}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/issues"
# 2. 修复后关闭 Issue
curl -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"state":"closed"}' \
"$GITEA_URL/api/v1/repos/<owner>/<repo>/issues/<issue-number>"
实际用例
以下是一些真实场景下的 Gitea 自动化用例:
用例 1:自动化项目初始化
场景: 新项目启动需要快速创建仓库、配置 CI/CD、添加基础文件
#!/bin/bash
# init-project.sh
set -e
# 配置参数
PROJECT_NAME="my-project"
DESCRIPTION="一个新的微服务项目"
TEAM="backend-developers"
# 1. 创建仓库
echo "创建仓库: $PROJECT_NAME"
REPO_JSON=$(curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg name "$PROJECT_NAME" \
--arg desc "$DESCRIPTION" \
--argjson private true \
'{name: $name, description: $desc, private: $private, auto_init: true}')" \
"$GITEA_URL/api/v1/user/repos")
REPO_OWNER=$(echo "$REPO_JSON" | jq -r '.owner.login')
REPO_NAME=$(echo "$REPO_JSON" | jq -r '.name')
# 2. 添加团队访问
echo "配置团队权限"
curl -X PUT -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/teams/$TEAM/repos/$REPO_OWNER/$REPO_NAME"
# 3. 添加基础文件
echo "添加基础文件"
add_file() {
local path=$1
local content=$2
local message=$3
curl -s -X PUT -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg content "$(echo "$content" | base64)" \
--arg message "$message" \
--arg branch "main" \
'{content: $content, message: $message, branch: $branch}')" \
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/contents/$path" > /dev/null
}
# 添加 README
add_file "README.md" "# $PROJECT_NAME\n\n$DESCRIPTION" "添加 README"
# 添加 .gitignore
add_file ".gitignore" "node_modules/\n.env\n*.log\n" "添加 .gitignore"
# 添加 CI 配置
add_file ".gitea/workflows/ci.yml" "$(cat <<'EOF'
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo 'CI 流水线就绪'
EOF
)" "添加 CI 配置"
# 4. 创建开发分支
echo "创建开发分支"
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"new_branch_name": "develop", "old_branch_name": "main"}' \
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/branches"
# 5. 创建初始 Issue
echo "创建初始任务"
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg title "项目初始化" \
--arg body "## 待办事项\n- [ ] 配置开发环境\n- [ ] 编写 API 文档\n- [ ] 设置测试框架" \
'{title: $title, body: $body, labels: ["enhancement", "documentation"]}')" \
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/issues"
echo "项目初始化完成: $GITEA_URL/$REPO_OWNER/$REPO_NAME"
用例 2:自动化代码审查工作流
场景: 团队需要标准化代码审查流程
#!/bin/bash
# code-review-automation.sh
# 检查所有开放的 PR,自动分配评审者并添加评论
check_open_prs() {
local owner=$1
local repo=$2
echo "检查 $owner/$repo 的开放 PR..."
prs=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/pulls?state=open")
echo "$prs" | jq -c '.[]' | while read pr; do
pr_number=$(echo "$pr" | jq -r '.number')
pr_title=$(echo "$pr" | jq -r '.title')
pr_author=$(echo "$pr" | jq -r '.user.login')
echo "处理 PR #$pr_number: $pr_title (作者: $pr_author)"
# 检查是否已分配评审者
reviewers=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/pulls/$pr_number/requested_reviewers")
if [[ $(echo "$reviewers" | jq '.users | length') -eq 0 ]]; then
# 自动分配评审者(基于轮询或专业知识)
assign_reviewer "$owner" "$repo" "$pr_number" "$pr_author"
fi
# 检查是否缺少描述
pr_body=$(echo "$pr" | jq -r '.body')
if [[ -z "$pr_body" || "$pr_body" == "null" ]]; then
add_pr_comment "$owner" "$repo" "$pr_number" \
"⚠️ 请添加 PR 描述,说明更改内容和原因。"
fi
# 检查是否关联 Issue
if ! echo "$pr_body" | grep -q -E "(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #[0-9]+"; then
add_pr_comment "$owner" "$repo" "$pr_number" \
"💡 建议关联相关 Issue,使用 'fixes #123' 语法。"
fi
done
}
assign_reviewer() {
local owner=$1 repo=$2 pr_number=$3 author=$4
# 排除作者自己,从团队中随机选择评审者
reviewers=("alice" "bob" "charlie")
for reviewer in "${reviewers[@]}"; do
if [[ "$reviewer" != "$author" ]]; then
selected_reviewer=$reviewer
break
fi
done
echo "分配评审者: $selected_reviewer"
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg reviewer "$selected_reviewer" \
'{reviewers: [$reviewer]}')" \
"$GITEA_URL/api/v1/repos/$owner/$repo/pulls/$pr_number/requested_reviewers" > /dev/null
}
add_pr_comment() {
local owner=$1 repo=$2 pr_number=$3 comment=$4
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg body "$comment" \
'{body: $body}')" \
"$GITEA_URL/api/v1/repos/$owner/$repo/pulls/$pr_number/comments" > /dev/null
}
# 定时运行(例如通过 cron)
# */30 * * * * /path/to/code-review-automation.sh owner repo
用例 3:监控和报告生成
场景: 定期生成团队活动报告
#!/bin/bash
# generate-team-report.sh
generate_weekly_report() {
local team=$1
local start_date=$(date -d "7 days ago" +%Y-%m-%d)
local end_date=$(date +%Y-%m-%d)
echo "# 团队周报: $team"
echo "时间段: $start_date 至 $end_date"
echo "生成时间: $(date)"
echo ""
# 获取团队仓库
team_repos=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/teams/$team/repos")
echo "## 仓库活动汇总"
echo ""
echo "$team_repos" | jq -c '.[]' | while read repo; do
repo_name=$(echo "$repo" | jq -r '.full_name')
# 获取仓库活动
events=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$repo_name/events?since=$start_date")
push_count=$(echo "$events" | jq '[.[] | select(.type == "push")] | length')
pr_count=$(echo "$events" | jq '[.[] | select(.type == "pull_request")] | length')
issue_count=$(echo "$events" | jq '[.[] | select(.type == "issues")] | length')
echo "### $repo_name"
echo "- 推送次数: $push_count"
echo "- PR 数量: $pr_count"
echo "- Issue 数量: $issue_count"
echo ""
# 列出新创建的 PR
if [[ $pr_count -gt 0 ]]; then
echo "#### 新 PR:"
echo "$events" | jq -r '.[] | select(.type == "pull_request" and .payload.action == "opened") | "- #\(.payload.number): \(.payload.pull_request.title) (\(.actor.login))"' | head -5
echo ""
fi
# 列出关闭的 Issue
if [[ $issue_count -gt 0 ]]; then
echo "#### 已关闭 Issue:"
echo "$events" | jq -r '.[] | select(.type == "issues" and .payload.action == "closed") | "- #\(.payload.issue.number): \(.payload.issue.title) (\(.actor.login))"' | head -5
echo ""
fi
done
# 保存报告
report_file="/tmp/team-report-$team-$(date +%Y%m%d).md"
echo "报告已保存到: $report_file"
# 可选:发送到团队频道
# send_to_slack "$(cat $report_file)" "#team-reports"
}
# 生成报告
generate_weekly_report "developers"
用例 4:自动化发布管理
场景: 自动化版本发布和变更日志生成
#!/bin/bash
# release-manager.sh
create_release() {
local owner=$1
local repo=$2
local version=$3
local release_notes=$4
echo "创建发布: $owner/$repo v$version"
# 1. 创建发布分支
branch_name="release/v$version"
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg branch "$branch_name" \
--arg base "main" \
'{new_branch_name: $branch, old_branch_name: $base}')" \
"$GITEA_URL/api/v1/repos/$owner/$repo/branches"
# 2. 更新版本文件
update_version_file "$owner" "$repo" "$branch_name" "$version"
# 3. 创建 PR
pr_title="Release v$version"
pr_body="## 版本 $version\n\n$release_notes\n\n### 变更内容\n$(generate_changelog $owner $repo $version)"
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg title "$pr_title" \
--arg body "$pr_body" \
--arg head "$branch_name" \
--arg base "main" \
'{title: $title, body: $body, head: $head, base: $base}')" \
"$GITEA_URL/api/v1/repos/$owner/$repo/pulls"
# 4. 合并 PR 后创建标签
echo "请合并 PR 后运行:"
echo " create_tag \"$owner\" \"$repo\" \"v$version\" \"Release version $version\" \"main\""
}
generate_changelog() {
local owner=$1 repo=$2 version=$3
# 获取上一个版本
prev_tag=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/tags" | \
jq -r '.[0].name' 2>/dev/null || echo "v0.0.0")
# 获取提交历史
commits=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/compare/$prev_tag...main")
echo "$commits" | jq -r '.commits[] | "- \(.commit.message | split("\n")[0]) (\(.author.login))"' | head -20
}
# 使用示例
# create_release "owner" "repo" "1.2.0" "功能更新和错误修复"
工具和脚本
本技能提供以下实用脚本,简化 Gitea 操作:
1. 配置脚本 (setup.sh)
交互式配置向导,帮助设置 Gitea 环境变量和测试连接。
功能:
- 交互式输入 Gitea URL 和访问令牌
- 自动验证连接
- 保存配置到
~/.gitea-actor.env - 支持颜色输出和错误处理
使用方法:
# 授予执行权限
chmod +x scripts/setup.sh
# 运行配置向导
./scripts/setup.sh
# 加载配置
source ~/.gitea-actor.env
2. API 示例脚本 (api-examples.sh)
包含常用 Gitea API 操作的 Bash 函数库。
功能:
- 20+ 个常用 API 函数
- 统一的错误处理
- 友好的输出格式
- 可直接在 Shell 中使用
使用方法:
# 加载函数到当前 Shell
source scripts/api-examples.sh
# 使用函数
get_current_user
list_user_repos
create_repository "my-repo" "描述" false
3. Python CLI 工具 (gitea-cli.py)
功能完整的命令行工具,支持所有主要 Gitea 操作。
功能:
- 完整的命令行界面
- 支持所有主要 Gitea API
- JSON 输出格式
- 错误处理和验证
安装和使用:
# 安装依赖
pip install requests
# 查看帮助
python scripts/gitea-cli.py --help
# 示例命令
python scripts/gitea-cli.py user info
python scripts/gitea-cli.py repo create --name myrepo --description "测试仓库"
python scripts/gitea-cli.py pr create --owner admin --repo myrepo --title "测试PR" --head feature-branch
故障排除
常见问题及解决方案
1. 认证失败 (401 Unauthorized)
症状: API 返回 401 状态码 可能原因:
- 令牌无效或已过期
- 令牌权限不足
- URL 格式错误
解决方案:
# 1. 重新生成令牌(Gitea 设置 -> 应用)
# 2. 验证令牌权限(需要 repo、user 等权限)
# 3. 更新环境变量
export GITEA_TOKEN="new_token_here"
# 4. 测试连接
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | jq .
2. 连接超时
症状: Connection timed out 或 Could not resolve host
可能原因:
- 网络不可达
- DNS 解析失败
- 防火墙阻止
解决方案:
# 1. 测试网络连接
ping -c 3 $(echo $GITEA_URL | sed 's|https://||' | sed 's|http://||' | cut -d/ -f1)
# 2. 检查 DNS 解析
nslookup $(echo $GITEA_URL | sed 's|https://||' | sed 's|http://||' | cut -d/ -f1)
# 3. 使用 curl 调试
curl -v $GITEA_URL
3. API 版本不匹配 (404 Not Found)
症状: API 返回 404 状态码 可能原因:
- API 路径错误
- Gitea 版本过旧
- 资源不存在
解决方案:
# 1. 检查 Gitea 版本
curl -s "$GITEA_URL/api/v1/version" | jq .
# 2. 验证 API 端点是否存在
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user"
# 3. 检查 Gitea 文档确认 API 兼容性
4. 权限不足 (403 Forbidden)
症状: API 返回 403 状态码 可能原因:
- 令牌缺少必要权限
- 用户无权访问资源
- 仓库权限设置限制
解决方案:
# 1. 检查令牌权限范围
# 2. 在 Gitea 中检查仓库权限
# 3. 确保令牌有对应操作的权限
5. 速率限制 (429 Too Many Requests)
症状: API 返回 429 状态码 可能原因:
- API 请求过于频繁
- Gitea 实例设置了速率限制
解决方案:
# 1. 添加请求延迟
sleep 1 # 每次请求后等待1秒
# 2. 检查速率限制头
curl -s -I -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user"
# 3. 批量处理请求,减少请求次数
6. JSON 解析错误
症状: jq: parse error 或 JSON 格式错误
可能原因:
- API 响应不是有效的 JSON
- 网络问题导致响应不完整
- Gitea 返回错误页面
解决方案:
# 1. 不使用 jq,先查看原始响应
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user"
# 2. 检查响应内容类型
curl -s -I -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | grep -i "content-type"
# 3. 添加错误处理到脚本
response=$(curl -s -w "\n%{http_code}" ...)
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
7. SSL/TLS 证书问题
症状: SSL certificate problem 或 self-signed certificate
可能原因:
- 自签名证书
- 证书过期
- 证书链不完整
解决方案:
# 1. 跳过证书验证(不推荐用于生产)
curl -k -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user"
# 2. 添加自定义证书
curl --cacert /path/to/cert.pem -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user"
# 3. 更新系统证书存储
调试技巧
-
使用 verbose 模式:
curl -v -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" -
检查响应头:
curl -s -I -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" -
保存调试信息:
curl -s -w "\nStatus: %{http_code}\nTime: %{time_total}s\n" \ -H "Authorization: token $GITEA_TOKEN" \ "$GITEA_URL/api/v1/user" > debug.log -
使用 Python 脚本调试:
import requests response = requests.get(url, headers=headers) print(f"Status: {response.status_code}") print(f"Headers: {response.headers}") print(f"Body: {response.text[:500]}")
最佳实践
1. 安全性最佳实践
令牌管理
- 永不提交令牌: 避免将令牌硬编码在脚本或提交到版本控制系统
- 使用环境变量: 通过环境变量或配置文件管理敏感信息
- 定期轮换: 每 3-6 个月更新一次访问令牌
- 最小权限原则: 只为令牌授予必要的最小权限
- 令牌存储安全: 使用安全的密码管理器存储令牌备份
访问控制
- 使用个人访问令牌: 而非密码进行 API 认证
- 限制令牌范围: 在创建令牌时只选择必要的权限范围
- 监控异常活动: 定期检查 Gitea 审计日志
- 及时撤销未使用的令牌: 删除不再需要的令牌
2. 错误处理和可靠性
健壮的脚本编写
# 示例:带有错误处理的 API 调用函数
call_gitea_api() {
local endpoint=$1
local method=${2:-GET}
local data=${3:-}
local response
local http_code
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-X "$method" \
${data:+-d "$data"} \
"$GITEA_URL/api/v1/$endpoint" 2>/dev/null || echo "CURL_ERROR")
http_code=$(echo "$response" | tail -n1)
local response_body=$(echo "$response" | sed '$d')
if [[ "$http_code" =~ ^[23] ]]; then
echo "$response_body"
return 0
else
echo "API 错误 ($http_code): $response_body" >&2
return 1
fi
}
重试机制
# 示例:带有重试的 API 调用
retry_api_call() {
local max_retries=3
local retry_delay=2
local attempt=1
while [[ $attempt -le $max_retries ]]; do
if call_gitea_api "$@"; then
return 0
fi
if [[ $attempt -lt $max_retries ]]; then
echo "第 $attempt 次尝试失败,${retry_delay}秒后重试..."
sleep $retry_delay
((retry_delay *= 2)) # 指数退避
fi
((attempt++))
done
echo "达到最大重试次数 ($max_retries),操作失败" >&2
return 1
}
3. 性能优化
批量操作
# 避免多次 API 调用,使用批量处理
# 错误示例:每个仓库单独调用 API
for repo in $(list_repos); do
get_repo_info "$repo"
done
# 正确示例:一次获取所有仓库信息
all_repos=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user/repos?limit=100")
缓存策略
# 使用本地缓存减少 API 调用
cache_file="/tmp/gitea_repos_$(echo -n $GITEA_URL | md5sum | cut -d' ' -f1).json"
cache_age=300 # 5分钟
if [[ -f "$cache_file" ]] && \
[[ $(($(date +%s) - $(stat -c %Y "$cache_file"))) -lt $cache_age ]]; then
# 使用缓存
repos=$(cat "$cache_file")
else
# 调用 API 并更新缓存
repos=$(call_gitea_api "user/repos?limit=100")
echo "$repos" > "$cache_file"
fi
合理设置超时
# 根据操作类型设置不同的超时时间
export CURL_TIMEOUT=30 # 常规操作
export CURL_LONG_TIMEOUT=120 # 长时间操作(如创建仓库)
# 在 curl 命令中使用
curl --max-time $CURL_TIMEOUT ...
4. 代码质量和可维护性
模块化设计
# 将功能拆分为独立的函数或脚本
# gitea-functions.sh
source "$(dirname "$0")/gitea-config.sh"
source "$(dirname "$0")/gitea-repos.sh"
source "$(dirname "$0")/gitea-pr.sh"
标准化输出格式
# 使用一致的输出格式
log_info() { echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*"; }
log_error() { echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2; }
log_success() { echo "[SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') $*"; }
文档和注释
#!/bin/bash
# 脚本: gitea-repo-manager.sh
# 作者: Your Name
# 描述: Gitea 仓库管理工具
# 版本: 1.0.0
# 用法: ./gitea-repo-manager.sh <命令> [参数]
5. 自动化工作流
Git Hooks 集成
# 在 .git/hooks/pre-push 中添加 Gitea 集成
#!/bin/bash
# 在推送前检查 Gitea 上是否存在对应的 PR
remote="$1"
url="$2"
if [[ "$url" == *"gitea"* ]]; then
# 执行 Gitea 相关检查
check_gitea_pr_status
fi
CI/CD 管道集成
# .gitea/workflows/ci.yml
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run tests
run: |
# 使用 Gitea API 更新状态
update_gitea_status "pending" "测试进行中"
# 运行测试
./run-tests.sh
update_gitea_status "success" "测试通过"
6. 监控和日志
操作日志记录
# 记录所有重要操作
log_operation() {
local operation=$1
local status=$2
local details=$3
echo "$(date '+%Y-%m-%d %H:%M:%S') | $operation | $status | $details" \
>> "/var/log/gitea-actor.log"
# 可选:发送到远程日志系统
send_to_logging_service "$operation" "$status" "$details"
}
性能监控
# 监控 API 响应时间
monitor_api_performance() {
local endpoint=$1
local start_time=$(date +%s%N)
call_gitea_api "$endpoint" > /dev/null
local end_time=$(date +%s%N)
local duration=$((($end_time - $start_time) / 1000000))
echo "API $endpoint 响应时间: ${duration}ms"
if [[ $duration -gt 5000 ]]; then
log_warning "API 响应缓慢: $endpoint (${duration}ms)"
fi
}
API 参考
核心 API 端点
用户相关
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/v1/user |
GET | 获取当前用户信息 | - |
/api/v1/users/{username} |
GET | 获取指定用户信息 | - |
/api/v1/user/repos |
GET | 列出用户仓库 | page, limit |
/api/v1/user/repos |
POST | 创建仓库 | name, description, private, auto_init |
/api/v1/user/teams |
GET | 列出用户团队 | - |
仓库相关
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/v1/repos/{owner}/{repo} |
GET | 获取仓库信息 | - |
/api/v1/repos/{owner}/{repo} |
DELETE | 删除仓库 | - |
/api/v1/repos/{owner}/{repo}/contents |
GET | 获取文件内容 | ref |
/api/v1/repos/{owner}/{repo}/contents/{filepath} |
PUT | 创建/更新文件 | content, message, branch |
/api/v1/repos/{owner}/{repo}/branches |
GET | 列出分支 | - |
/api/v1/repos/{owner}/{repo}/branches |
POST | 创建分支 | new_branch_name, old_branch_name |
/api/v1/repos/{owner}/{repo}/tags |
GET | 列出标签 | - |
/api/v1/repos/{owner}/{repo}/tags |
POST | 创建标签 | tag_name, message, target |
Pull Request 相关
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/v1/repos/{owner}/{repo}/pulls |
GET | 列出 PRs | state, page, limit |
/api/v1/repos/{owner}/{repo}/pulls |
POST | 创建 PR | title, body, head, base |
/api/v1/repos/{owner}/{repo}/pulls/{index} |
GET | 获取 PR 详情 | - |
/api/v1/repos/{owner}/{repo}/pulls/{index}/merge |
POST | 合并 PR | Do |
/api/v1/repos/{owner}/{repo}/pulls/{index}/comments |
GET | 获取 PR 评论 | - |
/api/v1/repos/{owner}/{repo}/pulls/{index}/comments |
POST | 添加 PR 评论 | body, path, line |
Issue 相关
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/v1/repos/{owner}/{repo}/issues |
GET | 列出 Issues | state, labels, page |
/api/v1/repos/{owner}/{repo}/issues |
POST | 创建 Issue | title, body, labels, assignees |
/api/v1/repos/{owner}/{repo}/issues/{index} |
GET | 获取 Issue 详情 | - |
/api/v1/repos/{owner}/{repo}/issues/{index} |
PATCH | 更新 Issue | title, body, state, labels |
/api/v1/repos/{owner}/{repo}/issues/{index}/comments |
GET | 获取 Issue 评论 | - |
/api/v1/repos/{owner}/{repo}/issues/{index}/comments |
POST | 添加 Issue 评论 | body |
搜索相关
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/v1/repos/search |
GET | 搜索仓库 | q, limit, page |
/api/v1/users/search |
GET | 搜索用户 | q, limit, page |
请求和响应格式
认证头
# 使用个人访问令牌
Authorization: token {personal_access_token}
# 或使用基本认证(不推荐)
Authorization: Basic $(echo -n "username:password" | base64)
请求头
# 常用请求头
Content-Type: application/json
Accept: application/json
User-Agent: Gitea-Actor/1.0.0
# 分页请求头
Link: <https://gitea.com/api/v1/user/repos?page=2>; rel="next"
响应格式
{
"id": 1,
"name": "example",
"full_name": "owner/example",
"description": "示例仓库",
"private": false,
"html_url": "https://gitea.com/owner/example",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T00:00:00Z"
}
错误响应
{
"message": "令牌无效",
"documentation_url": "https://docs.gitea.com/api"
}
分页和限制
分页参数
# 基本分页
curl -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user/repos?page=1&limit=20"
# 处理分页响应
while true; do
response=$(call_gitea_api "user/repos?page=$page&limit=20")
# 处理数据...
# 检查是否有下一页
next_link=$(echo "$response" | grep -i 'rel="next"' || true)
if [[ -z "$next_link" ]]; then
break
fi
((page++))
done
速率限制
Gitea API 通常有速率限制,可以通过响应头查看:
# 检查速率限制头
curl -s -I -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user" | grep -i "rate"
# 常见速率限制头
X-RateLimit-Limit: 60 # 每分钟最大请求数
X-RateLimit-Remaining: 58 # 剩余请求数
X-RateLimit-Reset: 1625097600 # 重置时间戳
实用 API 示例
创建仓库并初始化文件
# 1. 创建仓库
repo_data=$(jq -n \
--arg name "my-repo" \
--arg desc "我的仓库" \
'{name: $name, description: $desc, auto_init: true}')
repo=$(curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$repo_data" \
"$GITEA_URL/api/v1/user/repos")
# 2. 添加初始文件
readme_data=$(jq -n \
--arg content "# 我的项目\n\n这是一个示例项目。" \
--arg message "添加 README" \
--arg branch "main" \
'{content: $content | @base64, message: $message, branch: $branch}')
curl -s -X PUT -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$readme_data" \
"$GITEA_URL/api/v1/repos/$(echo $repo | jq -r '.owner.login')/$(echo $repo | jq -r '.name')/contents/README.md"
批量操作示例
# 批量创建 Issues
issues=(
'{"title": "Bug: 修复登录问题", "body": "用户无法登录", "labels": ["bug"]}'
'{"title": "功能: 添加搜索", "body": "需要全文搜索功能", "labels": ["enhancement"]}'
'{"title": "文档: 更新 API 文档", "body": "API 文档需要更新", "labels": ["documentation"]}'
)
for issue_data in "${issues[@]}"; do
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$issue_data" \
"$GITEA_URL/api/v1/repos/owner/repo/issues" > /dev/null
echo "创建 Issue: $(echo $issue_data | jq -r '.title')"
sleep 1 # 避免速率限制
done
API 版本和兼容性
检查 API 版本
# 获取 Gitea 版本信息
curl -s "$GITEA_URL/api/v1/version" | jq .
# 响应示例
{
"version": "1.20.0",
"built": "2024-01-01T00:00:00Z"
}
API 兼容性提示
- Gitea 1.15+ 支持完整的 API v1
- 某些端点可能需要特定版本
- 建议使用最新稳定版 Gitea
- 定期检查 Gitea API 文档 获取更新
高级功能和集成
1. Webhook 自动化
Webhook 配置
# 创建 Webhook
webhook_data=$(jq -n \
--arg url "https://your-webhook-server.com/webhook" \
--argjson active true \
'{
type: "gitea",
config: {url: $url, content_type: "json"},
events: ["push", "pull_request", "issue", "release"],
active: $active
}')
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$webhook_data" \
"$GITEA_URL/api/v1/repos/owner/repo/hooks"
Webhook 处理器示例
#!/usr/bin/env python3
# webhook-server.py
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
WEBHOOK_SECRET = "your_secret_here"
@app.route('/webhook', methods=['POST'])
def handle_webhook():
# 验证签名
signature = request.headers.get('X-Gitea-Signature')
payload = request.get_data()
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return jsonify({"error": "Invalid signature"}), 401
event = request.headers.get('X-Gitea-Event')
payload = request.json
# 处理不同事件
if event == 'push':
handle_push_event(payload)
elif event == 'pull_request':
handle_pr_event(payload)
elif event == 'issue':
handle_issue_event(payload)
return jsonify({"status": "ok"}), 200
def handle_push_event(payload):
print(f"Push event: {payload['ref']}")
# 触发 CI/CD 或其他自动化
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2. CI/CD 流水线集成
Gitea Actions
# .gitea/workflows/main.yml
name: CI Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest
- name: Notify Gitea
run: |
# 使用 API 更新 PR 状态
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"state": "success",
"target_url": "https://ci.example.com/build/123",
"description": "测试通过",
"context": "CI/tests"
}' \
"$GITEA_URL/api/v1/repos/${{ github.repository }}/statuses/${{ github.sha }}"
外部 CI 集成
# 在 CI 脚本中使用 Gitea API
update_build_status() {
local state=$1 # pending, success, failure, error
local description=$2
local context=${3:-"CI/build"}
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg state "$state" \
--arg desc "$description" \
--arg context "$context" \
--arg url "$CI_PIPELINE_URL" \
'{state: $state, description: $desc, context: $context, target_url: $url}')" \
"$GITEA_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/statuses/$COMMIT_SHA"
}
# 在 CI 阶段调用
update_build_status "pending" "构建进行中"
# ... 执行构建 ...
update_build_status "success" "构建成功"
3. 团队和权限管理
团队管理
# 创建团队
team_data=$(jq -n \
--arg name "developers" \
--arg desc "开发团队" \
--argjson permission "write" \
'{name: $name, description: $desc, permission: $permission, includes_all_repositories: false}')
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$team_data" \
"$GITEA_URL/api/v1/orgs/org-name/teams"
# 添加团队成员
curl -X PUT -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/teams/{team-id}/members/{username}"
仓库权限管理
# 添加协作者
curl -X PUT -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/owner/repo/collaborators/username"
# 设置协作者权限
collab_data=$(jq -n \
--argjson permission "write" \
'{permission: $permission}')
curl -X PUT -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$collab_data" \
"$GITEA_URL/api/v1/repos/owner/repo/collaborators/username"
4. 高级搜索和报告
高级搜索
# 搜索代码
search_query="TODO in:file language:go"
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/owner/repo/search?q=${search_query// /%20}" | jq .
# 搜索 Issues
issues_query="is:open label:bug assignee:user1"
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/owner/repo/issues?q=${issues_query// /%20}" | jq .
生成报告
# 生成仓库报告
generate_repo_report() {
local owner=$1
local repo=$2
echo "# 仓库报告: $owner/$repo"
echo "生成时间: $(date)"
echo ""
# 获取仓库信息
repo_info=$(call_gitea_api "repos/$owner/$repo")
echo "## 基本信息"
echo "- 描述: $(echo $repo_info | jq -r '.description')"
echo "- 创建时间: $(echo $repo_info | jq -r '.created_at')"
echo "- 星标数: $(echo $repo_info | jq -r '.stars_count')"
echo ""
# 获取开放 Issues
echo "## 开放 Issues"
issues=$(call_gitea_api "repos/$owner/$repo/issues?state=open")
echo "$issues" | jq -r '.[] | "- #\(.number): \(.title) (\(.user.login))"'
echo ""
# 获取开放 PRs
echo "## 开放 Pull Requests"
prs=$(call_gitea_api "repos/$owner/$repo/pulls?state=open")
echo "$prs" | jq -r '.[] | "- #\(.number): \(.title) (\(.user.login))"'
}
# 保存报告
generate_repo_report "owner" "repo" > repo-report.md
5. Git 操作自动化
自动同步分支
#!/bin/bash
# sync-branches.sh
# 自动同步所有仓库的分支
for repo in $(list_user_repos | jq -r '.full_name'); do
echo "同步仓库: $repo"
# 克隆仓库
git clone "$GITEA_URL/$repo.git" temp-repo
cd temp-repo
# 获取远程分支
git fetch origin
# 同步所有分支
for branch in $(git branch -r | grep -v '\->'); do
branch_name=${branch#origin/}
git checkout -b "$branch_name" "$branch" 2>/dev/null || git checkout "$branch_name"
git pull origin "$branch_name"
done
# 清理
cd ..
rm -rf temp-repo
done
批量仓库操作
# 批量更新仓库描述
update_repo_descriptions() {
local pattern=$1
local new_description=$2
repos=$(call_gitea_api "user/repos")
echo "$repos" | jq -r ".[] | select(.name | test(\"$pattern\")) | .full_name" | while read repo; do
owner=$(echo "$repo" | cut -d/ -f1)
name=$(echo "$repo" | cut -d/ -f2)
update_data=$(jq -n \
--arg desc "$new_description" \
'{description: $desc}')
echo "更新: $repo"
curl -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$update_data" \
"$GITEA_URL/api/v1/repos/$owner/$name"
done
}
6. 监控和告警
监控脚本
#!/bin/bash
# monitor-gitea.sh
# 监控 Gitea 实例健康状态
check_gitea_health() {
# 检查 API 响应时间
start_time=$(date +%s%N)
response=$(curl -s -w "\n%{http_code}" -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user")
end_time=$(date +%s%N)
response_time=$((($end_time - $start_time) / 1000000))
http_code=$(echo "$response" | tail -n1)
if [[ "$http_code" != "200" ]]; then
echo "警报: Gitea API 返回 $http_code (响应时间: ${response_time}ms)"
send_alert "Gitea API 异常" "HTTP $http_code"
elif [[ $response_time -gt 1000 ]]; then
echo "警告: API 响应缓慢 (${response_time}ms)"
fi
# 检查磁盘空间
disk_usage=$(ssh gitea-server "df -h /var/lib/gitea | tail -1")
echo "磁盘使用: $disk_usage"
# 检查服务状态
service_status=$(ssh gitea-server "systemctl is-active gitea")
if [[ "$service_status" != "active" ]]; then
echo "警报: Gitea 服务状态: $service_status"
send_alert "Gitea 服务异常" "状态: $service_status"
fi
}
# 定期检查
while true; do
check_gitea_health
sleep 300 # 5分钟
done
7. 备份和迁移
仓库备份
#!/bin/bash
# backup-gitea-repos.sh
# 备份所有仓库
BACKUP_DIR="/backup/gitea/repos"
mkdir -p "$BACKUP_DIR"
# 备份所有仓库
for repo in $(list_user_repos | jq -r '.full_name'); do
echo "备份: $repo"
# 使用 git bundle 创建备份
git clone --mirror "$GITEA_URL/$repo.git" "$BACKUP_DIR/$repo.git"
# 创建压缩包
tar -czf "$BACKUP_DIR/${repo//\//-}.$(date +%Y%m%d).tar.gz" -C "$BACKUP_DIR" "$repo.git"
rm -rf "$BACKUP_DIR/$repo.git"
done
# 备份到远程
rsync -avz "$BACKUP_DIR/" "backup-server:/gitea-backups/"
迁移工具
# 迁移仓库到新实例
migrate_repo() {
local source_url=$1
local target_url=$2
local repo_name=$3
echo "迁移: $repo_name"
# 克隆源仓库
git clone --mirror "$source_url/$repo_name.git"
cd "$(basename "$repo_name.git")"
# 推送到目标
git push --mirror "$target_url/$repo_name.git"
cd ..
rm -rf "$(basename "$repo_name.git")"
}
8. 集成第三方服务
集成 Slack
# 发送通知到 Slack
send_to_slack() {
local message=$1
local channel=${2:-"#gitea-notifications"}
curl -X POST -H "Content-Type: application/json" \
-d "$(jq -n \
--arg text "$message" \
--arg channel "$channel" \
'{text: $text, channel: $channel}')" \
"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
}
# 在 Webhook 处理器中使用
handle_pr_event() {
local payload=$1
local action=$(echo "$payload" | jq -r '.action')
local pr_number=$(echo "$payload" | jq -r '.number')
local title=$(echo "$payload" | jq -r '.pull_request.title')
message="PR #$pr_number $action: $title"
send_to_slack "$message"
}
集成 JIRA
# 同步 Issue 到 JIRA
sync_to_jira() {
local issue_data=$1
local title=$(echo "$issue_data" | jq -r '.title')
local body=$(echo "$issue_data" | jq -r '.body')
local labels=$(echo "$issue_data" | jq -r '.labels[]?.name' | tr '\n' ',')
# 创建 JIRA Issue
jira_data=$(jq -n \
--arg title "$title" \
--arg desc "$body" \
--arg labels "$labels" \
'{
fields: {
project: {key: "PROJ"},
summary: $title,
description: $desc,
issuetype: {name: "Task"},
labels: ($labels | split(",") | map(select(. != "")))
}
}')
curl -X POST -u "user:token" \
-H "Content-Type: application/json" \
-d "$jira_data" \
"https://jira.example.com/rest/api/2/issue"
}