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

此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
2026-01-13 00:27:21 +08:00

19 KiB
Raw Permalink Blame History

Gitea API 参考

Gitea API 使用指南和常用接口参考。

API 基础

认证

所有 API 请求需要在 Header 中包含 Personal Access Token

Authorization: token YOUR_GITEA_TOKEN

Base URL

API 基础路径:

https://your-gitea-instance.com/api/v1

响应格式

所有响应均为 JSON 格式。

HTTP 状态码

状态码 说明
200 请求成功
201 创建成功
204 删除成功(无内容返回)
400 请求参数错误
401 未授权Token 无效或缺失)
403 禁止访问(权限不足)
404 资源不存在
409 冲突(资源已存在)
500 服务器内部错误

通用 API 调用函数

Shell 函数封装

#!/bin/bash

# 加载配置
load_gitea_config() {
  config_file="$HOME/.config/gitea/config.env"
  
  if [ ! -f "$config_file" ]; then
    echo "❌ Gitea 未配置" >&2
    return 1
  fi
  
  source "$config_file"
  
  if [ -z "$GITEA_URL" ] || [ -z "$GITEA_TOKEN" ]; then
    echo "❌ 配置文件不完整" >&2
    return 1
  fi
}

# 通用 API 调用
gitea_api() {
  local method="$1"
  local endpoint="$2"
  local data="$3"
  
  load_gitea_config || return 1
  
  local url="${GITEA_URL}/api/v1${endpoint}"
  
  if [ -n "$data" ]; then
    curl -s -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      -d "$data" \
      "$url"
  else
    curl -s -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      "$url"
  fi
}

# 带状态码的 API 调用
gitea_api_with_status() {
  local method="$1"
  local endpoint="$2"
  local data="$3"
  
  load_gitea_config || return 1
  
  local url="${GITEA_URL}/api/v1${endpoint}"
  
  if [ -n "$data" ]; then
    curl -s -w "\n%{http_code}" -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      -d "$data" \
      "$url"
  else
    curl -s -w "\n%{http_code}" -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      "$url"
  fi
}

使用示例

# GET 请求
gitea_api GET "/user"

# POST 请求
gitea_api POST "/orgs/myorg/repos" '{
  "name": "my-repo",
  "private": true
}'

# 获取响应状态码
response=$(gitea_api_with_status GET "/user")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')

用户 API

获取当前用户信息

GET /user

示例

gitea_api GET "/user"

响应

{
  "id": 1,
  "login": "your_username",
  "email": "your_username@example.com",
  "full_name": "Voson Chen",
  "avatar_url": "https://...",
  "is_admin": false
}

列出用户的组织

GET /user/orgs

示例

gitea_api GET "/user/orgs"

仓库 API

创建组织仓库

POST /orgs/{org}/repos

请求体

{
  "name": "repo-name",
  "description": "Repository description",
  "private": true,
  "auto_init": false,
  "default_branch": "main"
}

示例

gitea_api POST "/orgs/ai/repos" '{
  "name": "my-project",
  "private": true
}'

创建用户仓库

POST /user/repos

示例

gitea_api POST "/user/repos" '{
  "name": "my-project",
  "private": false
}'

获取仓库信息

GET /repos/{owner}/{repo}

示例

gitea_api GET "/repos/ai/my-project"

删除仓库

DELETE /repos/{owner}/{repo}

示例

gitea_api DELETE "/repos/ai/my-project"

Runner API

获取全局 Runner 注册 Token需要管理员权限

GET /admin/runners/registration-token

示例

response=$(gitea_api GET "/admin/runners/registration-token")
token=$(echo "$response" | jq -r '.token')
echo "Registration Token: $token"

响应

{
  "token": "RUNNER_REGISTRATION_TOKEN"
}

注意:全局 Runner 可用于所有组织和仓库,需要管理员 Token。

获取组织 Runner 注册 Token

POST /orgs/{org}/actions/runners/registration-token

示例

response=$(gitea_api POST "/orgs/ai/actions/runners/registration-token")
token=$(echo "$response" | jq -r '.token')
echo "Registration Token: $token"

响应

{
  "token": "RUNNER_REGISTRATION_TOKEN"
}

获取仓库 Runner 注册 Token

GET /repos/{owner}/{repo}/actions/runners/registration-token

示例

gitea_api GET "/repos/ai/my-project/actions/runners/registration-token"

列出全局 Runners需要管理员权限

GET /admin/actions/runners

示例

gitea_api GET "/admin/actions/runners"

响应

{
  "runners": [
    {
      "id": 1,
      "name": "runner-global",
      "status": "online",
      "busy": false,
      "labels": [...]
    }
  ],
  "total_count": 1
}

列出组织的 Runners

GET /orgs/{org}/actions/runners

示例

gitea_api GET "/orgs/ai/actions/runners"

删除全局 Runner需要管理员权限

DELETE /admin/actions/runners/{id}

示例

runner_id=42
gitea_api DELETE "/admin/actions/runners/${runner_id}"

注意:需要管理员 Token。

删除组织 Runner

DELETE /orgs/{org}/actions/runners/{id}

示例

runner_id=42
org="ai"
gitea_api DELETE "/orgs/${org}/actions/runners/${runner_id}"

注意:需要 write:runner 权限和组织管理权限。

Actions API

列出仓库的 Workflows

GET /repos/{owner}/{repo}/actions/workflows

示例

gitea_api GET "/repos/ai/my-project/actions/workflows"

列出 Workflow 运行记录

GET /repos/{owner}/{repo}/actions/runs

示例

gitea_api GET "/repos/ai/my-project/actions/runs"

获取特定运行的详情

GET /repos/{owner}/{repo}/actions/runs/{run_id}

取消 Workflow 运行

POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel

组织 API

获取组织信息

GET /orgs/{org}

示例

gitea_api GET "/orgs/ai"

列出组织成员

GET /orgs/{org}/members

列出组织的仓库

GET /orgs/{org}/repos

示例

gitea_api GET "/orgs/ai/repos"

Secrets 和 Variables API

Variables API

Variables 用于存储非敏感的配置信息,可以在 Actions workflow 中使用。Gitea 支持三个级别的 variables

  • 用户级User-level:适用于当前用户的所有仓库
  • 组织级Organization-level:适用于组织下的所有仓库
  • 仓库级Repository-level:仅适用于特定仓库

注意Gitea 目前不支持系统全局级Admin-levelvariables。

列出用户级 Variables

GET /user/actions/variables

示例

gitea_api GET "/user/actions/variables"

响应

[
  {
    "owner_id": 1,
    "repo_id": 0,
    "name": "USERNAME",
    "data": "your_username",
    "description": ""
  },
  {
    "owner_id": 1,
    "repo_id": 0,
    "name": "WEBHOOK_URL",
    "data": "https://www.feishu.cn/flow/api/trigger-webhook/xxx",
    "description": ""
  }
]

创建/更新用户级 Variable

POST /user/actions/variables/{variable_name}

请求体

{
  "value": "variable_value"
}

示例

# 注意Variable 名称不能以 GITEA_ 或 GITHUB_ 开头
gitea_api POST "/user/actions/variables/USERNAME" '{
  "value": "your_username"
}'

gitea_api POST "/user/actions/variables/WEBHOOK_URL" '{
  "value": "https://www.feishu.cn/flow/api/trigger-webhook/xxx"
}'

命名限制

  • Variable 名称只能包含字母、数字和下划线
  • 不能以 GITEA_GITHUB_ 开头
  • 不能以数字开头
  • 不能以 CI 开头

使用场景

  • 在初始化 Gitea 配置时自动创建
  • 适用于所有个人仓库的 Actions workflow

删除用户级 Variable

DELETE /user/actions/variables/{variable_name}

示例

gitea_api DELETE "/user/actions/variables/OLD_VAR"

列出组织级 Variables

GET /orgs/{org}/actions/variables

示例

gitea_api GET "/orgs/ai/actions/variables"

创建/更新组织级 Variable

POST /orgs/{org}/actions/variables/{variable_name}

请求体

{
  "value": "variable_value"
}

示例

gitea_api POST "/orgs/ai/actions/variables/ORG_VAR" '{
  "value": "organization_value"
}'

创建仓库级 Variable

POST /repos/{owner}/{repo}/actions/variables/{variable_name}

请求体

{
  "value": "variable_value"
}

示例

gitea_api POST "/repos/ai/my-project/actions/variables/MY_VAR" '{
  "value": "production"
}'

在 Workflow 中使用 Variables

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 使用 Variables
        run: |
          echo "用户名: ${{ vars.USERNAME }}"
          echo "Webhook: ${{ vars.WEBHOOK_URL }}"
          echo "组织变量: ${{ vars.ORG_VAR }}"
          echo "仓库变量: ${{ vars.MY_VAR }}"

优先级(从高到低):

  1. 仓库级 Variable
  2. 组织级 Variable
  3. 用户级 Variable

Secrets API

Secrets 用于存储敏感信息如密码、Token 等)。

创建仓库 Secret

PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}

请求体

{
  "data": "base64_encoded_secret_value"
}

示例

secret_value="my-secret-value"
encoded_value=$(echo -n "$secret_value" | base64)

gitea_api PUT "/repos/ai/my-project/actions/secrets/MY_SECRET" "{
  \"data\": \"$encoded_value\"
}"

创建组织 Secret

PUT /orgs/{org}/actions/secrets/{secret_name}

创建用户 Secret

PUT /user/actions/secrets/{secret_name}

示例

password="my_password"
encoded_password=$(echo -n "$password" | base64)

gitea_api PUT "/user/actions/secrets/GITEA_PASSWORD" "{
  \"data\": \"$encoded_password\"
}"

Release API

创建 Release

POST /repos/{owner}/{repo}/releases

请求体

{
  "tag_name": "v1.0.0",
  "name": "Release v1.0.0",
  "body": "Release notes...",
  "draft": false,
  "prerelease": false
}

示例

gitea_api POST "/repos/ai/my-project/releases" '{
  "tag_name": "v1.0.0",
  "name": "Release v1.0.0",
  "body": "Initial release"
}'

上传 Release 附件

POST /repos/{owner}/{repo}/releases/{release_id}/assets

示例

release_id=1
file_path="/path/to/artifact.zip"

curl -X POST \
  -H "Authorization: token $GITEA_TOKEN" \
  -F "attachment=@${file_path}" \
  "${GITEA_URL}/api/v1/repos/ai/my-project/releases/${release_id}/assets"

列出 Releases

GET /repos/{owner}/{repo}/releases

Webhook API

创建 Webhook

POST /repos/{owner}/{repo}/hooks

请求体

{
  "type": "gitea",
  "config": {
    "url": "https://webhook-receiver.com/hook",
    "content_type": "json",
    "secret": "webhook_secret"
  },
  "events": ["push", "pull_request"],
  "active": true
}

示例

gitea_api POST "/repos/ai/my-project/hooks" '{
  "type": "gitea",
  "config": {
    "url": "https://example.com/webhook",
    "content_type": "json"
  },
  "events": ["push"],
  "active": true
}'

列出 Webhooks

GET /repos/{owner}/{repo}/hooks

删除 Webhook

DELETE /repos/{owner}/{repo}/hooks/{hook_id}

实用封装函数

检查仓库是否存在

repo_exists() {
  local owner="$1"
  local repo="$2"
  
  response=$(gitea_api_with_status GET "/repos/${owner}/${repo}")
  http_code=$(echo "$response" | tail -n1)
  
  [ "$http_code" = "200" ]
}

# 使用
if repo_exists "ai" "my-project"; then
  echo "仓库存在"
else
  echo "仓库不存在"
fi

获取 Runner 注册 Token

get_runner_token() {
  local org="$1"
  
  response=$(gitea_api GET "/orgs/${org}/actions/runners/registration-token")
  echo "$response" | jq -r '.token'
}

# 使用
token=$(get_runner_token "ai")
echo "Token: $token"

创建仓库并设置 Secret

create_repo_with_secret() {
  local org="$1"
  local repo="$2"
  local secret_name="$3"
  local secret_value="$4"
  
  # 创建仓库
  gitea_api POST "/orgs/${org}/repos" "{
    \"name\": \"${repo}\",
    \"private\": true
  }"
  
  # 添加 Secret
  encoded=$(echo -n "$secret_value" | base64)
  gitea_api PUT "/repos/${org}/${repo}/actions/secrets/${secret_name}" "{
    \"data\": \"${encoded}\"
  }"
}

# 使用
create_repo_with_secret "ai" "my-project" "API_KEY" "secret123"

批量获取组织仓库

list_org_repos() {
  local org="$1"
  
  gitea_api GET "/orgs/${org}/repos" | jq -r '.[].name'
}

# 使用
echo "组织 'ai' 的所有仓库:"
list_org_repos "ai"

检查并创建用户级 Variables

ensure_user_variable() {
  local var_name="$1"
  local var_value="$2"
  
  # 检查 variable 是否存在
  existing=$(gitea_api GET "/user/actions/variables" | \
    jq -r ".[] | select(.name == \"$var_name\") | .name")
  
  if [ -z "$existing" ]; then
    echo "创建 $var_name..."
    gitea_api POST "/user/actions/variables/$var_name" "{
      \"value\": \"$var_value\"
    }"
    echo "✓ $var_name 已创建"
  else
    echo "✓ $var_name 已存在"
  fi
}

# 使用 (注意:不能使用 GITEA_ 或 GITHUB_ 前缀)
ensure_user_variable "USERNAME" "your_username"
ensure_user_variable "WEBHOOK_URL" "https://example.com/webhook"

同步配置到 Variables

sync_config_to_variables() {
  load_gitea_config || return 1
  
  echo "正在同步配置到用户级 Variables..."
  
  # 同步 USERNAME (注意Gitea 不允许以 GITEA_ 开头)
  if [ -n "$GITEA_USERNAME" ]; then
    ensure_user_variable "USERNAME" "$GITEA_USERNAME"
  fi
  
  # 同步 WEBHOOK_URL
  if [ -n "$GITEA_WEBHOOK_URL" ]; then
    ensure_user_variable "WEBHOOK_URL" "$GITEA_WEBHOOK_URL"
  fi
  
  echo "同步完成!"
}

# 使用
sync_config_to_variables

重要提示

  • Gitea 不允许 variable 名称以 GITEA_GITHUB_ 开头
  • 配置项 GITEA_USERNAME 会被注册为 USERNAME variable
  • 配置项 GITEA_WEBHOOK_URL 会被注册为 WEBHOOK_URL variable

错误处理

标准错误处理模式

make_api_call() {
  local method="$1"
  local endpoint="$2"
  local data="$3"
  
  response=$(gitea_api_with_status "$method" "$endpoint" "$data")
  http_code=$(echo "$response" | tail -n1)
  body=$(echo "$response" | sed '$d')
  
  case "$http_code" in
    200|201|204)
      echo "$body"
      return 0
      ;;
    400)
      echo "❌ 请求参数错误" >&2
      echo "$body" | jq -r '.message' >&2
      return 1
      ;;
    401)
      echo "❌ 未授权,请检查 Token" >&2
      return 1
      ;;
    403)
      echo "❌ 权限不足" >&2
      return 1
      ;;
    404)
      echo "❌ 资源不存在" >&2
      return 1
      ;;
    409)
      echo "❌ 资源已存在" >&2
      return 1
      ;;
    *)
      echo "❌ API 调用失败 (HTTP $http_code)" >&2
      echo "$body" >&2
      return 1
      ;;
  esac
}

带重试的 API 调用

api_call_with_retry() {
  local max_retries=3
  local retry_delay=2
  local attempt=1
  
  while [ $attempt -le $max_retries ]; do
    if response=$(make_api_call "$@"); then
      echo "$response"
      return 0
    fi
    
    echo "⚠️  尝试 $attempt/$max_retries 失败,${retry_delay}秒后重试..." >&2
    sleep $retry_delay
    attempt=$((attempt + 1))
  done
  
  echo "❌ API 调用失败,已重试 $max_retries 次" >&2
  return 1
}

调试技巧

显示 API 请求详情

gitea_api_debug() {
  local method="$1"
  local endpoint="$2"
  local data="$3"
  
  load_gitea_config || return 1
  
  local url="${GITEA_URL}/api/v1${endpoint}"
  
  echo "=== API Request ===" >&2
  echo "Method: $method" >&2
  echo "URL: $url" >&2
  echo "Data: $data" >&2
  echo "==================" >&2
  
  if [ -n "$data" ]; then
    curl -v -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      -d "$data" \
      "$url"
  else
    curl -v -X "$method" \
      -H "Authorization: token $GITEA_TOKEN" \
      -H "Content-Type: application/json" \
      "$url"
  fi
}

使用 jq 格式化响应

gitea_api GET "/user" | jq .

性能优化

使用缓存

cache_dir="$HOME/.cache/gitea-api"
mkdir -p "$cache_dir"

cached_api_call() {
  local endpoint="$1"
  local cache_ttl=300  # 5分钟
  
  local cache_key=$(echo "$endpoint" | md5sum | cut -d' ' -f1)
  local cache_file="$cache_dir/$cache_key"
  
  # 检查缓存
  if [ -f "$cache_file" ]; then
    local cache_age=$(($(date +%s) - $(stat -f %m "$cache_file")))
    if [ $cache_age -lt $cache_ttl ]; then
      cat "$cache_file"
      return 0
    fi
  fi
  
  # 调用 API 并缓存
  response=$(gitea_api GET "$endpoint")
  echo "$response" > "$cache_file"
  echo "$response"
}

并行 API 调用

# 并行获取多个仓库信息
repos=("repo1" "repo2" "repo3")

for repo in "${repos[@]}"; do
  gitea_api GET "/repos/ai/${repo}" &
done

wait  # 等待所有后台任务完成

常见使用场景

场景 1: 批量创建仓库

repos=("project-a" "project-b" "project-c")

for repo in "${repos[@]}"; do
  echo "创建仓库: $repo"
  gitea_api POST "/orgs/ai/repos" "{
    \"name\": \"${repo}\",
    \"private\": true,
    \"auto_init\": true
  }"
  sleep 1  # 避免请求过快
done

场景 2: 备份所有仓库列表

org="ai"
output_file="repos-backup-$(date +%Y%m%d).json"

gitea_api GET "/orgs/${org}/repos" > "$output_file"
echo "✓ 仓库列表已保存到: $output_file"

场景 3: 检查 Token 权限

check_token_permissions() {
  echo "检查 Token 权限..."
  
  # 测试 repo 权限
  if gitea_api GET "/user/repos" >/dev/null 2>&1; then
    echo "  ✓ repo (仓库管理)"
  fi
  
  # 测试 org 权限
  if gitea_api GET "/user/orgs" >/dev/null 2>&1; then
    echo "  ✓ admin:org (组织管理)"
  fi
  
  # 测试 runner 权限
  if gitea_api GET "/orgs/ai/actions/runners/registration-token" >/dev/null 2>&1; then
    echo "  ✓ write:runner (Runner 管理)"
  fi
}

相关资源

版本兼容性

本文档基于 Gitea API v1.20+。不同版本的 API 可能有差异,请参考你的 Gitea 实例的 API 文档。

检查 Gitea 版本:

gitea_api GET "/version"