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

20 KiB
Raw Blame History

Gitea 仓库操作

创建和管理 Gitea 仓库的完整指南。

概述

本文档介绍如何通过 Gitea API 创建和管理仓库,包括:

  • 创建组织/用户仓库
  • 初始化仓库结构
  • 配置 Actions 设置
  • 管理 Secrets 和 Variables
  • 设置 Webhooks

快速使用

核心原则(简洁高效)

  1. 智能解析:自动识别 组织/仓库 格式,优先使用指定组织而非默认组织
  2. 默认私有:除非明确指定,所有仓库默认创建为私有
  3. 简化验证默认假设组织存在API创建失败时清晰提示解决方案
  4. Git集成自动检查Git仓库状态提供一键初始化、提交、推送完整流程
  5. 错误处理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 会自动:

  1. 加载 Gitea 配置
  2. 解析仓库名称和 owner
  3. 调用 API 创建仓库
  4. 提示是否添加为 Git remote
  5. 显示仓库信息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

  1. 打开仓库 → Settings → Secrets → Actions
  2. 点击 "New Secret"
  3. 输入 Name 和 Value
  4. 保存

方法 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集成流程可选自动初始化和推送