feat: 优化 gitea-actor 技能,新增脚本工具和完整文档
- 新增 setup.sh 配置脚本 - 新增 api-examples.sh API 函数库 - 新增 gitea-cli.py Python CLI 工具 - 完善文档结构 (1640 行) - 添加实际用例和工作流示例 - 增强故障排除和最佳实践指南
This commit is contained in:
1640
skills/gitea-actor/SKILL.md
Normal file
1640
skills/gitea-actor/SKILL.md
Normal file
File diff suppressed because it is too large
Load Diff
290
skills/gitea-actor/scripts/api-examples.sh
Executable file
290
skills/gitea-actor/scripts/api-examples.sh
Executable file
@@ -0,0 +1,290 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Gitea API 示例脚本
|
||||
# 包含常用 Gitea API 操作的函数示例
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 检查环境变量
|
||||
check_env() {
|
||||
if [[ -z "$GITEA_URL" || -z "$GITEA_TOKEN" ]]; then
|
||||
echo -e "${RED}[ERROR]${NC} 请先设置 Gitea 环境变量"
|
||||
echo " 运行: source ~/.gitea-actor.env"
|
||||
echo " 或设置: export GITEA_URL=..., export GITEA_TOKEN=..."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 通用 API 请求函数
|
||||
gitea_api() {
|
||||
local method=$1
|
||||
local endpoint=$2
|
||||
local data=$3
|
||||
|
||||
local url="${GITEA_URL}/api/v1/${endpoint}"
|
||||
local curl_cmd="curl -s -H 'Authorization: token $GITEA_TOKEN' -H 'Accept: application/json'"
|
||||
|
||||
if [[ -n "$data" ]]; then
|
||||
curl_cmd="$curl_cmd -H 'Content-Type: application/json' -d '$data'"
|
||||
fi
|
||||
|
||||
curl_cmd="$curl_cmd -X $method '$url'"
|
||||
|
||||
eval "$curl_cmd"
|
||||
}
|
||||
|
||||
# 1. 用户相关操作
|
||||
get_current_user() {
|
||||
check_env || return 1
|
||||
echo -e "${BLUE}[INFO]${NC} 获取当前用户信息..."
|
||||
gitea_api "GET" "user" | jq .
|
||||
}
|
||||
|
||||
list_user_repos() {
|
||||
check_env || return 1
|
||||
local page=${1:-1}
|
||||
local limit=${2:-20}
|
||||
echo -e "${BLUE}[INFO]${NC} 列出用户仓库 (第 $page 页, 每页 $limit 个)..."
|
||||
gitea_api "GET" "user/repos?page=$page&limit=$limit" | jq '.[] | {id, full_name, description, private, html_url}'
|
||||
}
|
||||
|
||||
# 2. 仓库操作
|
||||
create_repository() {
|
||||
check_env || return 1
|
||||
local name=$1
|
||||
local description=${2:-""}
|
||||
local private=${3:-false}
|
||||
|
||||
if [[ -z "$name" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} create_repository <name> [description] [private(true/false)]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg name "$name" \
|
||||
--arg desc "$description" \
|
||||
--argjson private "$private" \
|
||||
'{name: $name, description: $desc, private: $private, auto_init: true}')
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 创建仓库: $name"
|
||||
gitea_api "POST" "user/repos" "$data" | jq .
|
||||
}
|
||||
|
||||
get_repository() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} get_repository <owner> <repo>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 获取仓库信息: $owner/$repo"
|
||||
gitea_api "GET" "repos/$owner/$repo" | jq .
|
||||
}
|
||||
|
||||
# 3. Pull Request 操作
|
||||
create_pull_request() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local title=$3
|
||||
local body=$4
|
||||
local head=$5
|
||||
local base=${6:-"main"}
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" || -z "$title" || -z "$head" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} create_pull_request <owner> <repo> <title> <body> <head> [base]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg body "$body" \
|
||||
--arg head "$head" \
|
||||
--arg base "$base" \
|
||||
'{title: $title, body: $body, head: $head, base: $base}')
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 创建 Pull Request: $title"
|
||||
gitea_api "POST" "repos/$owner/$repo/pulls" "$data" | jq .
|
||||
}
|
||||
|
||||
list_pull_requests() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local state=${3:-"open"}
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} list_pull_requests <owner> <repo> [state(open/closed/all)]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 列出 Pull Requests: $owner/$repo (状态: $state)"
|
||||
gitea_api "GET" "repos/$owner/$repo/pulls?state=$state" | jq '.[] | {number, title, state, user: .user.login, created_at}'
|
||||
}
|
||||
|
||||
merge_pull_request() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local pr_number=$3
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" || -z "$pr_number" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} merge_pull_request <owner> <repo> <pr-number>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data='{"Do":"merge"}'
|
||||
echo -e "${BLUE}[INFO]${NC} 合并 Pull Request: #$pr_number"
|
||||
gitea_api "POST" "repos/$owner/$repo/pulls/$pr_number/merge" "$data" | jq .
|
||||
}
|
||||
|
||||
# 4. Issue 操作
|
||||
create_issue() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local title=$3
|
||||
local body=$4
|
||||
local labels=$5
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" || -z "$title" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} create_issue <owner> <repo> <title> [body] [labels逗号分隔]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data="{\"title\":\"$title\""
|
||||
|
||||
if [[ -n "$body" ]]; then
|
||||
data="$data, \"body\":\"$body\""
|
||||
fi
|
||||
|
||||
if [[ -n "$labels" ]]; then
|
||||
IFS=',' read -ra label_array <<< "$labels"
|
||||
local labels_json=$(printf '"%s",' "${label_array[@]}")
|
||||
labels_json="[${labels_json%,}]"
|
||||
data="$data, \"labels\":$labels_json"
|
||||
fi
|
||||
|
||||
data="$data}"
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 创建 Issue: $title"
|
||||
gitea_api "POST" "repos/$owner/$repo/issues" "$data" | jq .
|
||||
}
|
||||
|
||||
# 5. 分支和标签
|
||||
create_branch() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local new_branch=$3
|
||||
local from_branch=${4:-"main"}
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" || -z "$new_branch" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} create_branch <owner> <repo> <new-branch> [from-branch]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg new_branch "$new_branch" \
|
||||
--arg old_branch "$from_branch" \
|
||||
'{new_branch_name: $new_branch, old_branch_name: $old_branch}')
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 创建分支: $new_branch (从 $from_branch)"
|
||||
gitea_api "POST" "repos/$owner/$repo/branches" "$data" | jq .
|
||||
}
|
||||
|
||||
create_tag() {
|
||||
check_env || return 1
|
||||
local owner=$1
|
||||
local repo=$2
|
||||
local tag_name=$3
|
||||
local message=${4:-"Release $tag_name"}
|
||||
local target=${5:-"main"}
|
||||
|
||||
if [[ -z "$owner" || -z "$repo" || -z "$tag_name" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} create_tag <owner> <repo> <tag-name> [message] [target-branch]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local data=$(jq -n \
|
||||
--arg tag_name "$tag_name" \
|
||||
--arg message "$message" \
|
||||
--arg target "$target" \
|
||||
'{tag_name: $tag_name, message: $message, target: $target}')
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 创建标签: $tag_name"
|
||||
gitea_api "POST" "repos/$owner/$repo/tags" "$data" | jq .
|
||||
}
|
||||
|
||||
# 6. 搜索操作
|
||||
search_repositories() {
|
||||
check_env || return 1
|
||||
local query=$1
|
||||
local limit=${2:-10}
|
||||
|
||||
if [[ -z "$query" ]]; then
|
||||
echo -e "${YELLOW}[USAGE]${NC} search_repositories <query> [limit]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}[INFO]${NC} 搜索仓库: $query"
|
||||
gitea_api "GET" "repos/search?q=$query&limit=$limit" | jq '.data[] | {full_name, description, stars_count, forks_count}'
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo -e "${GREEN}Gitea API 示例脚本${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}使用方法:${NC}"
|
||||
echo " source api-examples.sh # 加载函数到当前shell"
|
||||
echo " 然后调用任意函数"
|
||||
echo ""
|
||||
echo -e "${BLUE}可用函数:${NC}"
|
||||
echo " 用户操作:"
|
||||
echo " get_current_user"
|
||||
echo " list_user_repos [page] [limit]"
|
||||
echo ""
|
||||
echo " 仓库操作:"
|
||||
echo " create_repository <name> [description] [private]"
|
||||
echo " get_repository <owner> <repo>"
|
||||
echo ""
|
||||
echo " Pull Request 操作:"
|
||||
echo " create_pull_request <owner> <repo> <title> <body> <head> [base]"
|
||||
echo " list_pull_requests <owner> <repo> [state]"
|
||||
echo " merge_pull_request <owner> <repo> <pr-number>"
|
||||
echo ""
|
||||
echo " Issue 操作:"
|
||||
echo " create_issue <owner> <repo> <title> [body] [labels]"
|
||||
echo ""
|
||||
echo " 分支和标签:"
|
||||
echo " create_branch <owner> <repo> <new-branch> [from-branch]"
|
||||
echo " create_tag <owner> <repo> <tag-name> [message] [target]"
|
||||
echo ""
|
||||
echo " 搜索操作:"
|
||||
echo " search_repositories <query> [limit]"
|
||||
echo ""
|
||||
echo -e "${YELLOW}示例:${NC}"
|
||||
echo " # 获取当前用户信息"
|
||||
echo " get_current_user"
|
||||
echo ""
|
||||
echo " # 创建新仓库"
|
||||
echo " create_repository \"my-new-repo\" \"My description\" false"
|
||||
echo ""
|
||||
echo " # 创建 Pull Request"
|
||||
echo " create_pull_request \"owner\" \"repo\" \"添加新功能\" \"详细描述\" \"feature-branch\" \"main\""
|
||||
}
|
||||
|
||||
# 如果直接运行脚本,显示帮助
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
show_help
|
||||
fi
|
||||
340
skills/gitea-actor/scripts/gitea-cli.py
Executable file
340
skills/gitea-actor/scripts/gitea-cli.py
Executable file
@@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Gitea CLI 工具
|
||||
提供命令行界面访问 Gitea API
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
|
||||
class GiteaClient:
|
||||
"""Gitea API 客户端"""
|
||||
|
||||
def __init__(self, url: str = None, token: str = None):
|
||||
self.url = url or os.environ.get("GITEA_URL", "https://gitea.com")
|
||||
self.token = token or os.environ.get("GITEA_TOKEN")
|
||||
|
||||
if not self.token:
|
||||
print("错误: 未设置 GITEA_TOKEN 环境变量")
|
||||
print("请设置: export GITEA_TOKEN='your_token_here'")
|
||||
sys.exit(1)
|
||||
|
||||
# 移除URL末尾的斜杠
|
||||
self.url = self.url.rstrip("/")
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update(
|
||||
{
|
||||
"Authorization": f"token {self.token}",
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
)
|
||||
|
||||
def _request(self, method: str, endpoint: str, data: Dict = None) -> Dict:
|
||||
"""发送API请求"""
|
||||
url = f"{self.url}/api/v1/{endpoint}"
|
||||
|
||||
try:
|
||||
if method.upper() == "GET":
|
||||
response = self.session.get(url, params=data)
|
||||
elif method.upper() == "POST":
|
||||
response = self.session.post(url, json=data)
|
||||
elif method.upper() == "PUT":
|
||||
response = self.session.put(url, json=data)
|
||||
elif method.upper() == "PATCH":
|
||||
response = self.session.patch(url, json=data)
|
||||
elif method.upper() == "DELETE":
|
||||
response = self.session.delete(url)
|
||||
else:
|
||||
raise ValueError(f"不支持的HTTP方法: {method}")
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
# 对于204 No Content响应,返回空字典
|
||||
if response.status_code == 204:
|
||||
return {}
|
||||
|
||||
return response.json()
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"API请求失败: {e}")
|
||||
if hasattr(e, "response") and e.response is not None:
|
||||
print(f"状态码: {e.response.status_code}")
|
||||
try:
|
||||
error_data = e.response.json()
|
||||
print(f"错误信息: {error_data.get('message', '未知错误')}")
|
||||
except:
|
||||
print(f"响应内容: {e.response.text[:200]}")
|
||||
sys.exit(1)
|
||||
|
||||
def get_current_user(self) -> Dict:
|
||||
"""获取当前用户信息"""
|
||||
return self._request("GET", "user")
|
||||
|
||||
def list_repos(self, page: int = 1, limit: int = 20) -> List[Dict]:
|
||||
"""列出用户仓库"""
|
||||
params = {"page": page, "limit": limit}
|
||||
return self._request("GET", "user/repos", params)
|
||||
|
||||
def create_repo(
|
||||
self, name: str, description: str = "", private: bool = False
|
||||
) -> Dict:
|
||||
"""创建仓库"""
|
||||
data = {
|
||||
"name": name,
|
||||
"description": description,
|
||||
"private": private,
|
||||
"auto_init": True,
|
||||
}
|
||||
return self._request("POST", "user/repos", data)
|
||||
|
||||
def get_repo(self, owner: str, repo: str) -> Dict:
|
||||
"""获取仓库信息"""
|
||||
return self._request("GET", f"repos/{owner}/{repo}")
|
||||
|
||||
def create_pull_request(
|
||||
self,
|
||||
owner: str,
|
||||
repo: str,
|
||||
title: str,
|
||||
body: str,
|
||||
head: str,
|
||||
base: str = "main",
|
||||
) -> Dict:
|
||||
"""创建Pull Request"""
|
||||
data = {"title": title, "body": body, "head": head, "base": base}
|
||||
return self._request("POST", f"repos/{owner}/{repo}/pulls", data)
|
||||
|
||||
def list_pull_requests(
|
||||
self, owner: str, repo: str, state: str = "open"
|
||||
) -> List[Dict]:
|
||||
"""列出Pull Requests"""
|
||||
params = {"state": state}
|
||||
return self._request("GET", f"repos/{owner}/{repo}/pulls", params)
|
||||
|
||||
def merge_pull_request(self, owner: str, repo: str, pr_number: int) -> Dict:
|
||||
"""合并Pull Request"""
|
||||
data = {"Do": "merge"}
|
||||
return self._request(
|
||||
"POST", f"repos/{owner}/{repo}/pulls/{pr_number}/merge", data
|
||||
)
|
||||
|
||||
def create_issue(
|
||||
self,
|
||||
owner: str,
|
||||
repo: str,
|
||||
title: str,
|
||||
body: str = "",
|
||||
labels: List[str] = None,
|
||||
) -> Dict:
|
||||
"""创建Issue"""
|
||||
data = {"title": title}
|
||||
if body:
|
||||
data["body"] = body
|
||||
if labels:
|
||||
data["labels"] = labels
|
||||
return self._request("POST", f"repos/{owner}/{repo}/issues", data)
|
||||
|
||||
def create_branch(
|
||||
self, owner: str, repo: str, new_branch: str, from_branch: str = "main"
|
||||
) -> Dict:
|
||||
"""创建分支"""
|
||||
data = {"new_branch_name": new_branch, "old_branch_name": from_branch}
|
||||
return self._request("POST", f"repos/{owner}/{repo}/branches", data)
|
||||
|
||||
def create_tag(
|
||||
self,
|
||||
owner: str,
|
||||
repo: str,
|
||||
tag_name: str,
|
||||
message: str = "",
|
||||
target: str = "main",
|
||||
) -> Dict:
|
||||
"""创建标签"""
|
||||
data = {
|
||||
"tag_name": tag_name,
|
||||
"message": message or f"Release {tag_name}",
|
||||
"target": target,
|
||||
}
|
||||
return self._request("POST", f"repos/{owner}/{repo}/tags", data)
|
||||
|
||||
def search_repos(self, query: str, limit: int = 10) -> Dict:
|
||||
"""搜索仓库"""
|
||||
params = {"q": query, "limit": limit}
|
||||
return self._request("GET", "repos/search", params)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Gitea CLI 工具")
|
||||
subparsers = parser.add_subparsers(dest="command", help="可用命令")
|
||||
|
||||
# 用户命令
|
||||
user_parser = subparsers.add_parser("user", help="用户相关操作")
|
||||
user_parser.add_argument(
|
||||
"action", choices=["info", "repos"], help="info: 获取用户信息, repos: 列出仓库"
|
||||
)
|
||||
user_parser.add_argument("--page", type=int, default=1, help="页码")
|
||||
user_parser.add_argument("--limit", type=int, default=20, help="每页数量")
|
||||
|
||||
# 仓库命令
|
||||
repo_parser = subparsers.add_parser("repo", help="仓库相关操作")
|
||||
repo_parser.add_argument("action", choices=["create", "get", "search"])
|
||||
repo_parser.add_argument("--name", help="仓库名称 (create时使用)")
|
||||
repo_parser.add_argument("--description", default="", help="仓库描述")
|
||||
repo_parser.add_argument("--private", action="store_true", help="是否私有")
|
||||
repo_parser.add_argument("--owner", help="仓库所有者 (get/search时使用)")
|
||||
repo_parser.add_argument("--repo", help="仓库名称 (get时使用)")
|
||||
repo_parser.add_argument("--query", help="搜索关键词")
|
||||
repo_parser.add_argument("--limit", type=int, default=10, help="搜索结果数量")
|
||||
|
||||
# PR命令
|
||||
pr_parser = subparsers.add_parser("pr", help="Pull Request 相关操作")
|
||||
pr_parser.add_argument("action", choices=["create", "list", "merge"])
|
||||
pr_parser.add_argument("--owner", required=True, help="仓库所有者")
|
||||
pr_parser.add_argument("--repo", required=True, help="仓库名称")
|
||||
pr_parser.add_argument("--title", help="PR标题 (create时使用)")
|
||||
pr_parser.add_argument("--body", default="", help="PR描述")
|
||||
pr_parser.add_argument("--head", help="源分支")
|
||||
pr_parser.add_argument("--base", default="main", help="目标分支")
|
||||
pr_parser.add_argument("--number", type=int, help="PR编号 (merge时使用)")
|
||||
pr_parser.add_argument(
|
||||
"--state",
|
||||
default="open",
|
||||
choices=["open", "closed", "all"],
|
||||
help="PR状态 (list时使用)",
|
||||
)
|
||||
|
||||
# Issue命令
|
||||
issue_parser = subparsers.add_parser("issue", help="Issue 相关操作")
|
||||
issue_parser.add_argument("action", choices=["create"])
|
||||
issue_parser.add_argument("--owner", required=True, help="仓库所有者")
|
||||
issue_parser.add_argument("--repo", required=True, help="仓库名称")
|
||||
issue_parser.add_argument("--title", required=True, help="Issue标题")
|
||||
issue_parser.add_argument("--body", default="", help="Issue描述")
|
||||
issue_parser.add_argument("--labels", help="标签 (逗号分隔)")
|
||||
|
||||
# 分支命令
|
||||
branch_parser = subparsers.add_parser("branch", help="分支相关操作")
|
||||
branch_parser.add_argument("action", choices=["create"])
|
||||
branch_parser.add_argument("--owner", required=True, help="仓库所有者")
|
||||
branch_parser.add_argument("--repo", required=True, help="仓库名称")
|
||||
branch_parser.add_argument("--name", required=True, help="新分支名称")
|
||||
branch_parser.add_argument("--from-branch", default="main", help="源分支")
|
||||
|
||||
# 标签命令
|
||||
tag_parser = subparsers.add_parser("tag", help="标签相关操作")
|
||||
tag_parser.add_argument("action", choices=["create"])
|
||||
tag_parser.add_argument("--owner", required=True, help="仓库所有者")
|
||||
tag_parser.add_argument("--repo", required=True, help="仓库名称")
|
||||
tag_parser.add_argument("--name", required=True, help="标签名称")
|
||||
tag_parser.add_argument("--message", default="", help="标签消息")
|
||||
tag_parser.add_argument("--target", default="main", help="目标分支/提交")
|
||||
|
||||
# 配置命令
|
||||
config_parser = subparsers.add_parser("config", help="配置相关操作")
|
||||
config_parser.add_argument("action", choices=["test"], help="测试连接")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.command:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
# 创建客户端
|
||||
client = GiteaClient()
|
||||
|
||||
# 处理命令
|
||||
try:
|
||||
if args.command == "user":
|
||||
if args.action == "info":
|
||||
user = client.get_current_user()
|
||||
print(json.dumps(user, indent=2, ensure_ascii=False))
|
||||
elif args.action == "repos":
|
||||
repos = client.list_repos(args.page, args.limit)
|
||||
for repo in repos:
|
||||
print(f"{repo['full_name']}: {repo.get('description', '')}")
|
||||
|
||||
elif args.command == "repo":
|
||||
if args.action == "create":
|
||||
if not args.name:
|
||||
print("错误: --name 参数是必需的")
|
||||
sys.exit(1)
|
||||
repo = client.create_repo(args.name, args.description, args.private)
|
||||
print(f"仓库创建成功: {repo['html_url']}")
|
||||
|
||||
elif args.action == "get":
|
||||
if not args.owner or not args.repo:
|
||||
print("错误: --owner 和 --repo 参数是必需的")
|
||||
sys.exit(1)
|
||||
repo = client.get_repo(args.owner, args.repo)
|
||||
print(json.dumps(repo, indent=2, ensure_ascii=False))
|
||||
|
||||
elif args.action == "search":
|
||||
if not args.query:
|
||||
print("错误: --query 参数是必需的")
|
||||
sys.exit(1)
|
||||
result = client.search_repos(args.query, args.limit)
|
||||
for repo in result.get("data", []):
|
||||
print(f"{repo['full_name']} - ★{repo.get('stars_count', 0)}")
|
||||
|
||||
elif args.command == "pr":
|
||||
if args.action == "create":
|
||||
if not all([args.title, args.head]):
|
||||
print("错误: --title 和 --head 参数是必需的")
|
||||
sys.exit(1)
|
||||
pr = client.create_pull_request(
|
||||
args.owner, args.repo, args.title, args.body, args.head, args.base
|
||||
)
|
||||
print(f"PR创建成功: #{pr['number']} - {pr['html_url']}")
|
||||
|
||||
elif args.action == "list":
|
||||
prs = client.list_pull_requests(args.owner, args.repo, args.state)
|
||||
for pr in prs:
|
||||
print(f"#{pr['number']}: {pr['title']} ({pr['state']})")
|
||||
|
||||
elif args.action == "merge":
|
||||
if not args.number:
|
||||
print("错误: --number 参数是必需的")
|
||||
sys.exit(1)
|
||||
result = client.merge_pull_request(args.owner, args.repo, args.number)
|
||||
print(f"PR #{args.number} 合并成功")
|
||||
|
||||
elif args.command == "issue":
|
||||
if args.action == "create":
|
||||
labels = args.labels.split(",") if args.labels else None
|
||||
issue = client.create_issue(
|
||||
args.owner, args.repo, args.title, args.body, labels
|
||||
)
|
||||
print(f"Issue创建成功: #{issue['number']} - {issue['html_url']}")
|
||||
|
||||
elif args.command == "branch":
|
||||
if args.action == "create":
|
||||
branch = client.create_branch(
|
||||
args.owner, args.repo, args.name, args.from_branch
|
||||
)
|
||||
print(f"分支创建成功: {args.name}")
|
||||
|
||||
elif args.command == "tag":
|
||||
if args.action == "create":
|
||||
tag = client.create_tag(
|
||||
args.owner, args.repo, args.name, args.message, args.target
|
||||
)
|
||||
print(f"标签创建成功: {args.name}")
|
||||
|
||||
elif args.command == "config":
|
||||
if args.action == "test":
|
||||
user = client.get_current_user()
|
||||
print(f"连接成功! 用户: {user.get('login', user.get('username'))}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"错误: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
185
skills/gitea-actor/scripts/setup.sh
Executable file
185
skills/gitea-actor/scripts/setup.sh
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Gitea-Actor 配置脚本
|
||||
# 版本: 1.0.0
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies() {
|
||||
local deps=("curl" "jq")
|
||||
for dep in "${deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
log_error "缺少依赖: $dep"
|
||||
log_info "请安装:"
|
||||
if [[ "$dep" == "jq" ]]; then
|
||||
log_info " Ubuntu/Debian: sudo apt install jq"
|
||||
log_info " CentOS/RHEL: sudo yum install jq"
|
||||
log_info " macOS: brew install jq"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 显示标题
|
||||
show_header() {
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${GREEN} Gitea-Actor 配置向导${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 验证 Gitea 连接
|
||||
test_gitea_connection() {
|
||||
local url=$1
|
||||
local token=$2
|
||||
|
||||
log_info "正在验证 Gitea 连接..."
|
||||
|
||||
# 检查 URL 格式
|
||||
if [[ ! "$url" =~ ^https?:// ]]; then
|
||||
log_error "URL 格式不正确,请使用 http:// 或 https:// 开头"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 发送测试请求
|
||||
local response
|
||||
local http_code
|
||||
|
||||
response=$(curl -s -w "\n%{http_code}" \
|
||||
-H "Authorization: token $token" \
|
||||
-H "Accept: application/json" \
|
||||
"$url/api/v1/user" 2>/dev/null || true)
|
||||
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
local response_body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [[ "$http_code" == "200" ]]; then
|
||||
local username=$(echo "$response_body" | jq -r '.login // .username' 2>/dev/null || echo "unknown")
|
||||
log_success "Gitea 连接成功!"
|
||||
log_info "用户: $username"
|
||||
return 0
|
||||
else
|
||||
log_error "Gitea 连接失败 (HTTP $http_code)"
|
||||
if [[ -n "$response_body" ]]; then
|
||||
log_info "错误信息: $(echo "$response_body" | jq -r '.message // .' 2>/dev/null || echo "$response_body")"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
show_header
|
||||
check_dependencies
|
||||
|
||||
# 检查现有配置
|
||||
local config_file="$HOME/.gitea-actor.env"
|
||||
if [[ -f "$config_file" ]]; then
|
||||
log_warn "发现现有配置文件: $config_file"
|
||||
echo ""
|
||||
log_info "现有配置:"
|
||||
grep -E "^(export )?(GITEA_URL|GITEA_TOKEN)=" "$config_file" || true
|
||||
echo ""
|
||||
|
||||
read -p "是否覆盖现有配置? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "已取消配置"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# 获取 Gitea URL
|
||||
local default_url="https://gitea.com"
|
||||
echo -e "${YELLOW}提示:${NC} 请输入您的 Gitea 实例 URL"
|
||||
echo -e " 例如: https://gitea.example.com"
|
||||
echo -e " 或: https://codehub.zlinkcloudtech.com"
|
||||
echo ""
|
||||
read -p "Gitea URL [默认: $default_url]: " gitea_url
|
||||
gitea_url=${gitea_url:-$default_url}
|
||||
|
||||
# 移除末尾的斜杠
|
||||
gitea_url=$(echo "$gitea_url" | sed 's|/$||')
|
||||
|
||||
# 获取访问令牌
|
||||
echo ""
|
||||
echo -e "${YELLOW}提示:${NC} 请提供个人访问令牌 (Personal Access Token)"
|
||||
echo -e " 可以在 Gitea 的 设置 -> 应用 中创建"
|
||||
echo ""
|
||||
read -p "访问令牌: " gitea_token
|
||||
|
||||
if [[ -z "$gitea_token" ]]; then
|
||||
log_error "访问令牌不能为空"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 测试连接
|
||||
echo ""
|
||||
if test_gitea_connection "$gitea_url" "$gitea_token"; then
|
||||
# 保存配置
|
||||
cat > "$config_file" << EOF
|
||||
# Gitea-Actor 配置文件
|
||||
# 生成时间: $(date)
|
||||
export GITEA_URL="$gitea_url"
|
||||
export GITEA_TOKEN="$gitea_token"
|
||||
|
||||
# 使用方式:
|
||||
# source ~/.gitea-actor.env
|
||||
# 或添加到 ~/.bashrc / ~/.zshrc
|
||||
EOF
|
||||
|
||||
log_success "配置已保存到: $config_file"
|
||||
echo ""
|
||||
log_info "使用方法:"
|
||||
echo " 1. 立即加载配置: source $config_file"
|
||||
echo " 2. 永久生效: 将以下行添加到 ~/.bashrc 或 ~/.zshrc:"
|
||||
echo " source $config_file"
|
||||
echo ""
|
||||
log_info "验证命令:"
|
||||
echo " curl -s -H \"Authorization: token \$GITEA_TOKEN\" \"\$GITEA_URL/api/v1/user\" | jq ."
|
||||
|
||||
# 询问是否立即加载配置
|
||||
echo ""
|
||||
read -p "是否立即加载配置到当前shell? (Y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||
if source "$config_file" 2>/dev/null; then
|
||||
log_success "配置已加载到当前shell"
|
||||
else
|
||||
log_warn "无法自动加载配置,请手动运行: source $config_file"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_error "配置失败,请检查URL和令牌是否正确"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 运行主函数
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user