Add gitea-manager skill for Gitea repository operations
Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
This commit is contained in:
339
gitea-manager/SKILL.md
Normal file
339
gitea-manager/SKILL.md
Normal file
@@ -0,0 +1,339 @@
|
||||
---
|
||||
name: gitea-manager
|
||||
description: 管理 Gitea 仓库的全能工具,支持仓库创建删除、文件操作、分支管理、Issue/PR 管理、组织和用户操作、仓库设置配置等。使用场景:(1) 创建或删除 Gitea 仓库 (2) 管理仓库文件和目录 (3) 操作分支和保护规则 (4) 创建和管理 Issue 和 Pull Request (5) 管理组织和团队成员 (6) 配置 Webhook 和 Deploy Key (7) 搜索仓库和 Issue。必需环境变量:GITEA_URL(实例地址)和 GITEA_TOKEN(API 令牌)。
|
||||
---
|
||||
|
||||
# Gitea Manager
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 环境配置
|
||||
|
||||
使用此 skill 前需要配置 Gitea 连接信息:
|
||||
|
||||
```bash
|
||||
export GITEA_URL="https://gitea.example.com"
|
||||
export GITEA_TOKEN="your-api-token-here"
|
||||
```
|
||||
|
||||
可以通过以下方式获取 API Token:
|
||||
1. 登录 Gitea
|
||||
2. 进入「设置」→「应用」
|
||||
3. 创建新的 API Token
|
||||
|
||||
### 初始化客户端
|
||||
|
||||
在 Python 代码中使用:
|
||||
|
||||
```python
|
||||
import sys
|
||||
sys.path.append("/root/.claude/skills/gitea-manager/scripts")
|
||||
from gitea_client import GiteaClient
|
||||
|
||||
client = GiteaClient()
|
||||
```
|
||||
|
||||
或指定自定义配置:
|
||||
|
||||
```python
|
||||
client = GiteaClient(url="https://gitea.example.com", token="your-token")
|
||||
```
|
||||
|
||||
## 仓库操作
|
||||
|
||||
### 列出仓库
|
||||
|
||||
```python
|
||||
repos = client.list_my_repos()
|
||||
for r in repos:
|
||||
print(f"{r['full_name']}: {r.get('description', '')}")
|
||||
```
|
||||
|
||||
### 创建仓库
|
||||
|
||||
```python
|
||||
repo = client.create_repo(
|
||||
name="my-new-repo",
|
||||
description="这是一个新仓库",
|
||||
private=False,
|
||||
auto_init=True
|
||||
)
|
||||
```
|
||||
|
||||
### 在组织下创建仓库
|
||||
|
||||
```python
|
||||
repo = client.create_org_repo(
|
||||
org="my-org",
|
||||
name="org-repo",
|
||||
description="组织仓库",
|
||||
private=True
|
||||
)
|
||||
```
|
||||
|
||||
### 获取仓库信息
|
||||
|
||||
```python
|
||||
repo = client.get_repo("owner", "repo-name")
|
||||
```
|
||||
|
||||
### 删除仓库
|
||||
|
||||
```python
|
||||
client.delete_repo("owner", "repo-name")
|
||||
```
|
||||
|
||||
## 文件操作
|
||||
|
||||
### 读取文件内容
|
||||
|
||||
```python
|
||||
content = client.get_file_content("owner", "repo", "path/to/file.txt", ref="main")
|
||||
```
|
||||
|
||||
### 获取文件信息
|
||||
|
||||
```python
|
||||
info = client.get_file_info("owner", "repo", "path/to/file.txt", ref="main")
|
||||
```
|
||||
|
||||
### 创建或更新文件
|
||||
|
||||
```python
|
||||
client.create_or_update_file(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
path="new-file.txt",
|
||||
content="文件内容",
|
||||
message="添加新文件",
|
||||
branch="main",
|
||||
email="user@example.com",
|
||||
name="Username"
|
||||
)
|
||||
```
|
||||
|
||||
### 删除文件
|
||||
|
||||
```python
|
||||
info = client.get_file_info("owner", "repo", "file.txt")
|
||||
client.delete_file(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
path="file.txt",
|
||||
message="删除文件",
|
||||
branch="main",
|
||||
sha=info["sha"],
|
||||
email="user@example.com",
|
||||
name="Username"
|
||||
)
|
||||
```
|
||||
|
||||
### 列出目录
|
||||
|
||||
```python
|
||||
files = client.list_directory("owner", "repo", "path/to/dir", ref="main")
|
||||
```
|
||||
|
||||
## 分支操作
|
||||
|
||||
### 列出分支
|
||||
|
||||
```python
|
||||
branches = client.list_branches("owner", "repo")
|
||||
```
|
||||
|
||||
### 获取分支信息
|
||||
|
||||
```python
|
||||
branch = client.get_branch("owner", "repo", "main")
|
||||
```
|
||||
|
||||
### 创建分支
|
||||
|
||||
```python
|
||||
client.create_branch("owner", "repo", "new-branch", "main")
|
||||
```
|
||||
|
||||
### 删除分支
|
||||
|
||||
```python
|
||||
client.delete_branch("owner", "repo", "old-branch")
|
||||
```
|
||||
|
||||
### 设置分支保护
|
||||
|
||||
```python
|
||||
client.set_protected_branch(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
branch="main",
|
||||
enable_push=True,
|
||||
enable_push_whitelist=["developers"],
|
||||
require_pull_request=True,
|
||||
require_approvals=2
|
||||
)
|
||||
```
|
||||
|
||||
## Issue 操作
|
||||
|
||||
### 列出 Issue
|
||||
|
||||
```python
|
||||
issues = client.list_issues("owner", "repo", state="open")
|
||||
```
|
||||
|
||||
### 创建 Issue
|
||||
|
||||
```python
|
||||
issue = client.create_issue(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
title="Bug: 登录失败",
|
||||
body="详细描述问题..."
|
||||
)
|
||||
```
|
||||
|
||||
### 更新 Issue
|
||||
|
||||
```python
|
||||
client.update_issue("owner", "repo", issue_index, title="新标题", state="closed")
|
||||
```
|
||||
|
||||
### 添加评论
|
||||
|
||||
```python
|
||||
comment = client.create_issue_comment("owner", "repo", issue_index, "这是我的评论")
|
||||
```
|
||||
|
||||
## Pull Request 操作
|
||||
|
||||
### 列出 PR
|
||||
|
||||
```python
|
||||
pulls = client.list_pulls("owner", "repo", state="open")
|
||||
```
|
||||
|
||||
### 创建 PR
|
||||
|
||||
```python
|
||||
pr = client.create_pull(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
title="Add new feature",
|
||||
body="PR 描述...",
|
||||
head="feature-branch",
|
||||
base="main"
|
||||
)
|
||||
```
|
||||
|
||||
### 合并 PR
|
||||
|
||||
```python
|
||||
client.merge_pull("owner", "repo", pr_index, merge_style="merge")
|
||||
```
|
||||
|
||||
## 组织操作
|
||||
|
||||
### 列出组织
|
||||
|
||||
```python
|
||||
orgs = client.list_orgs()
|
||||
```
|
||||
|
||||
### 列出组织仓库
|
||||
|
||||
```python
|
||||
repos = client.list_org_repos("my-org")
|
||||
```
|
||||
|
||||
### 创建组织
|
||||
|
||||
```python
|
||||
org = client.create_org(
|
||||
username="new-org",
|
||||
email="org@example.com"
|
||||
)
|
||||
```
|
||||
|
||||
### 列出组织团队
|
||||
|
||||
```python
|
||||
teams = client.list_org_teams("my-org")
|
||||
```
|
||||
|
||||
## Webhook 操作
|
||||
|
||||
### 列出 Webhook
|
||||
|
||||
```python
|
||||
hooks = client.list_hooks("owner", "repo")
|
||||
```
|
||||
|
||||
### 创建 Webhook
|
||||
|
||||
```python
|
||||
hook = client.create_hook(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
config={"url": "https://example.com/webhook", "secret": "secret"},
|
||||
events=["push", "issue", "pull_request"],
|
||||
active=True
|
||||
)
|
||||
```
|
||||
|
||||
### 删除 Webhook
|
||||
|
||||
```python
|
||||
client.delete_hook("owner", "repo", hook_id)
|
||||
```
|
||||
|
||||
## Deploy Key 操作
|
||||
|
||||
### 列出 Deploy Key
|
||||
|
||||
```python
|
||||
keys = client.list_deploy_keys("owner", "repo")
|
||||
```
|
||||
|
||||
### 创建 Deploy Key
|
||||
|
||||
```python
|
||||
key = client.create_deploy_key(
|
||||
owner="owner",
|
||||
repo="repo",
|
||||
title="my-deploy-key",
|
||||
key="ssh-rsa AAAA...",
|
||||
read_only=True
|
||||
)
|
||||
```
|
||||
|
||||
### 删除 Deploy Key
|
||||
|
||||
```python
|
||||
client.delete_deploy_key("owner", "repo", key_id)
|
||||
```
|
||||
|
||||
## 搜索操作
|
||||
|
||||
### 搜索仓库
|
||||
|
||||
```python
|
||||
repos = client.search_repos("keyword", limit=20)
|
||||
```
|
||||
|
||||
### 搜索 Issue
|
||||
|
||||
```python
|
||||
issues = client.search_issues("owner", "repo", "bug", limit=20)
|
||||
```
|
||||
|
||||
## 命令行使用
|
||||
|
||||
脚本也支持命令行调用:
|
||||
|
||||
```bash
|
||||
python gitea_client.py list-repos
|
||||
python gitea_client.py get-repo owner/repo
|
||||
python gitea_client.py create-repo my-repo "描述"
|
||||
python gitea_client.py delete-repo owner/repo
|
||||
```
|
||||
BIN
gitea-manager/gitea-manager.skill
Normal file
BIN
gitea-manager/gitea-manager.skill
Normal file
Binary file not shown.
423
gitea-manager/gitea_client.py
Normal file
423
gitea-manager/gitea_client.py
Normal file
@@ -0,0 +1,423 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Gitea API Client - 封装 Gitea REST API 的所有操作"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
from typing import Optional, Dict, List, Any
|
||||
|
||||
|
||||
class GiteaClient:
|
||||
"""Gitea API 客户端"""
|
||||
|
||||
def __init__(self, url: Optional[str] = None, token: Optional[str] = None):
|
||||
self.url = url or os.environ.get("GITEA_URL", "http://localhost:3000")
|
||||
self.token = token or os.environ.get("GITEA_TOKEN", "")
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update({
|
||||
"Authorization": f"token {self.token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
})
|
||||
if not self.token:
|
||||
raise ValueError("GITEA_TOKEN 环境变量未设置")
|
||||
|
||||
def _request(self, method: str, path: str, **kwargs) -> requests.Response:
|
||||
"""发送 API 请求"""
|
||||
url = f"{self.url.rstrip('/')}{path}"
|
||||
response = self.session.request(method, url, **kwargs)
|
||||
response.raise_for_status()
|
||||
return response
|
||||
|
||||
# ==================== 用户操作 ====================
|
||||
|
||||
def get_current_user(self) -> Dict:
|
||||
"""获取当前认证用户信息"""
|
||||
return self._request("GET", "/user").json()
|
||||
|
||||
def get_user(self, username: str) -> Dict:
|
||||
"""获取指定用户信息"""
|
||||
return self._request("GET", f"/users/{username}").json()
|
||||
|
||||
def list_user_repos(self, username: str, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出用户的所有仓库"""
|
||||
return self._request("GET", f"/users/{username}/repos", params={"page": page, "limit": limit}).json()
|
||||
|
||||
def create_user(self, email: str, username: str, password: str, **kwargs) -> Dict:
|
||||
"""创建用户(需要管理员权限)"""
|
||||
data = {"email": email, "username": username, "password": password}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", "/admin/users", json=data).json()
|
||||
|
||||
def delete_user(self, username: str) -> None:
|
||||
"""删除用户(需要管理员权限)"""
|
||||
self._request("DELETE", f"/admin/users/{username}")
|
||||
|
||||
# ==================== 组织操作 ====================
|
||||
|
||||
def list_orgs(self, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出当前用户所属组织"""
|
||||
return self._request("GET", "/user/orgs", params={"page": page, "limit": limit}).json()
|
||||
|
||||
def get_org(self, username: str) -> Dict:
|
||||
"""获取组织信息"""
|
||||
return self._request("GET", f"/orgs/{username}").json()
|
||||
|
||||
def create_org(self, username: str, email: str, **kwargs) -> Dict:
|
||||
"""创建组织"""
|
||||
data = {"username": username, "email": email}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", "/admin/orgs", json=data).json()
|
||||
|
||||
def list_org_repos(self, org: str, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出组织的所有仓库"""
|
||||
return self._request("GET", f"/orgs/{org}/repos", params={"page": page, "limit": limit}).json()
|
||||
|
||||
# ==================== 仓库操作 ====================
|
||||
|
||||
def list_my_repos(self, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出当前用户的仓库"""
|
||||
return self._request("GET", "/user/repos", params={"page": page, "limit": limit}).json()
|
||||
|
||||
def get_repo(self, owner: str, repo: str) -> Dict:
|
||||
"""获取仓库信息"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}").json()
|
||||
|
||||
def create_repo(self, name: str, description: str = "", private: bool = False,
|
||||
auto_init: bool = True, **kwargs) -> Dict:
|
||||
"""创建仓库"""
|
||||
data = {
|
||||
"name": name,
|
||||
"description": description,
|
||||
"private": private,
|
||||
"auto_init": auto_init
|
||||
}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", "/user/repos", json=data).json()
|
||||
|
||||
def create_org_repo(self, org: str, name: str, description: str = "",
|
||||
private: bool = False, auto_init: bool = True, **kwargs) -> Dict:
|
||||
"""在组织下创建仓库"""
|
||||
data = {
|
||||
"name": name,
|
||||
"description": description,
|
||||
"private": private,
|
||||
"auto_init": auto_init
|
||||
}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", f"/orgs/{org}/repos", json=data).json()
|
||||
|
||||
def delete_repo(self, owner: str, repo: str) -> None:
|
||||
"""删除仓库"""
|
||||
self._request("DELETE", f"/repos/{owner}/{repo}")
|
||||
|
||||
def get_repo_info(self, owner: str, repo: str) -> Dict:
|
||||
"""获取仓库详细信息"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}").json()
|
||||
|
||||
def update_repo(self, owner: str, repo: str, **kwargs) -> Dict:
|
||||
"""更新仓库设置"""
|
||||
return self._request("PATCH", f"/repos/{owner}/{repo}", json=kwargs).json()
|
||||
|
||||
# ==================== 分支操作 ====================
|
||||
|
||||
def list_branches(self, owner: str, repo: str, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出仓库分支"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/branches",
|
||||
params={"page": page, "limit": limit}).json()
|
||||
|
||||
def get_branch(self, owner: str, repo: str, branch: str) -> Dict:
|
||||
"""获取分支信息"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/branches/{branch}").json()
|
||||
|
||||
def create_branch(self, owner: str, repo: str, branch_name: str, from_branch: str) -> Dict:
|
||||
"""创建分支"""
|
||||
data = {
|
||||
"new_branch_name": branch_name,
|
||||
"from_branch": from_branch
|
||||
}
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/branches", json=data).json()
|
||||
|
||||
def delete_branch(self, owner: str, repo: str, branch: str) -> None:
|
||||
"""删除分支"""
|
||||
self._request("DELETE", f"/repos/{owner}/{repo}/branches/{branch}")
|
||||
|
||||
def list_protected_branches(self, owner: str, repo: str) -> List[Dict]:
|
||||
"""列出受保护分支"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/protected_branches").json()
|
||||
|
||||
def get_protected_branch(self, owner: str, repo: str, branch: str) -> Dict:
|
||||
"""获取受保护分支规则"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/protected_branches/{branch}").json()
|
||||
|
||||
def set_protected_branch(self, owner: str, repo: str, branch: str, **kwargs) -> Dict:
|
||||
"""设置分支保护规则"""
|
||||
return self._request("PUT", f"/repos/{owner}/{repo}/protected_branches/{branch}", json=kwargs).json()
|
||||
|
||||
# ==================== 文件操作 ====================
|
||||
|
||||
def get_file_content(self, owner: str, repo: str, path: str, ref: str = "main") -> str:
|
||||
"""获取文件内容(Base64 编码)"""
|
||||
response = self._request("GET", f"/repos/{owner}/{repo}/raw/{path}", params={"ref": ref})
|
||||
import base64
|
||||
return base64.b64encode(response.content).decode('utf-8')
|
||||
|
||||
def get_file_info(self, owner: str, repo: str, path: str, ref: str = "main") -> Dict:
|
||||
"""获取文件信息"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/contents/{path}", params={"ref": ref}).json()
|
||||
|
||||
def create_or_update_file(self, owner: str, repo: str, path: str, content: str,
|
||||
message: str, branch: str, email: str, name: str) -> Dict:
|
||||
"""创建或更新文件"""
|
||||
import base64
|
||||
data = {
|
||||
"content": base64.b64encode(content.encode()).decode('utf-8'),
|
||||
"message": message,
|
||||
"branch": branch,
|
||||
"author": {"email": email, "name": name},
|
||||
"committer": {"email": email, "name": name}
|
||||
}
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/contents/{path}", json=data).json()
|
||||
|
||||
def delete_file(self, owner: str, repo: str, path: str, message: str,
|
||||
branch: str, sha: str, email: str, name: str) -> Dict:
|
||||
"""删除文件"""
|
||||
data = {
|
||||
"message": message,
|
||||
"branch": branch,
|
||||
"sha": sha,
|
||||
"author": {"email": email, "name": name},
|
||||
"committer": {"email": email, "name": name}
|
||||
}
|
||||
return self._request("DELETE", f"/repos/{owner}/{repo}/contents/{path}", json=data).json()
|
||||
|
||||
def list_directory(self, owner: str, repo: str, path: str = "",
|
||||
ref: str = "main", page: int = 1, limit: int = 100) -> List[Dict]:
|
||||
"""列出目录内容"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/contents/{path}",
|
||||
params={"ref": ref, "page": page, "limit": limit}).json()
|
||||
|
||||
# ==================== Issue 操作 ====================
|
||||
|
||||
def list_issues(self, owner: str, repo: str, state: str = "open",
|
||||
page: int = 1, limit: int = 50, **kwargs) -> List[Dict]:
|
||||
"""列出仓库的 Issue"""
|
||||
params = {"state": state, "page": page, "limit": limit}
|
||||
params.update(kwargs)
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/issues", params=params).json()
|
||||
|
||||
def get_issue(self, owner: str, repo: str, index: int) -> Dict:
|
||||
"""获取 Issue 详情"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/issues/{index}").json()
|
||||
|
||||
def create_issue(self, owner: str, repo: str, title: str, body: str = "",
|
||||
**kwargs) -> Dict:
|
||||
"""创建 Issue"""
|
||||
data = {"title": title, "body": body}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/issues", json=data).json()
|
||||
|
||||
def update_issue(self, owner: str, repo: str, index: int, **kwargs) -> Dict:
|
||||
"""更新 Issue"""
|
||||
return self._request("PATCH", f"/repos/{owner}/{repo}/issues/{index}", json=kwargs).json()
|
||||
|
||||
def close_issue(self, owner: str, repo: str, index: int) -> Dict:
|
||||
"""关闭 Issue"""
|
||||
return self.update_issue(owner, repo, index, state="closed")
|
||||
|
||||
def list_issue_comments(self, owner: str, repo: str, issue_index: int,
|
||||
page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出 Issue 的评论"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/issues/{issue_index}/comments",
|
||||
params={"page": page, "limit": limit}).json()
|
||||
|
||||
def create_issue_comment(self, owner: str, repo: str, issue_index: int, body: str) -> Dict:
|
||||
"""创建 Issue 评论"""
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/issues/{issue_index}/comments",
|
||||
json={"body": body}).json()
|
||||
|
||||
# ==================== Pull Request 操作 ====================
|
||||
|
||||
def list_pulls(self, owner: str, repo: str, state: str = "open",
|
||||
page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出 Pull Request"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/pulls",
|
||||
params={"state": state, "page": page, "limit": limit}).json()
|
||||
|
||||
def get_pull(self, owner: str, repo: str, index: int) -> Dict:
|
||||
"""获取 Pull Request 详情"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/pulls/{index}").json()
|
||||
|
||||
def create_pull(self, owner: str, repo: str, title: str, body: str,
|
||||
head: str, base: str, **kwargs) -> Dict:
|
||||
"""创建 Pull Request"""
|
||||
data = {
|
||||
"title": title,
|
||||
"body": body,
|
||||
"head": head,
|
||||
"base": base
|
||||
}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/pulls", json=data).json()
|
||||
|
||||
def update_pull(self, owner: str, repo: str, index: int, **kwargs) -> Dict:
|
||||
"""更新 Pull Request"""
|
||||
return self._request("PATCH", f"/repos/{owner}/{repo}/pulls/{index}", json=kwargs).json()
|
||||
|
||||
def merge_pull(self, owner: str, repo: str, index: int,
|
||||
merge_message: str = "", merge_style: str = "merge") -> Dict:
|
||||
"""合并 Pull Request"""
|
||||
data = {
|
||||
"merge_commit_message": merge_message,
|
||||
"merge_style": merge_style
|
||||
}
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/pulls/{index}/merge", json=data).json()
|
||||
|
||||
def list_pull_comments(self, owner: str, repo: str, index: int) -> List[Dict]:
|
||||
"""列出 Pull Request 的评论"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/issues/{index}/comments").json()
|
||||
|
||||
# ==================== Webhook 操作 ====================
|
||||
|
||||
def list_hooks(self, owner: str, repo: str) -> List[Dict]:
|
||||
"""列出仓库的 Webhook"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/hooks").json()
|
||||
|
||||
def create_hook(self, owner: str, repo: str, config: Dict, events: List[str],
|
||||
active: bool = True) -> Dict:
|
||||
"""创建 Webhook"""
|
||||
data = {
|
||||
"type": "gitea",
|
||||
"config": config,
|
||||
"events": events,
|
||||
"active": active
|
||||
}
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/hooks", json=data).json()
|
||||
|
||||
def delete_hook(self, owner: str, repo: str, hook_id: int) -> None:
|
||||
"""删除 Webhook"""
|
||||
self._request("DELETE", f"/repos/{owner}/{repo}/hooks/{hook_id}")
|
||||
|
||||
# ==================== Deploy Key 操作 ====================
|
||||
|
||||
def list_deploy_keys(self, owner: str, repo: str) -> List[Dict]:
|
||||
"""列出仓库的 Deploy Key"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/keys").json()
|
||||
|
||||
def create_deploy_key(self, owner: str, repo: str, title: str, key: str,
|
||||
read_only: bool = True) -> Dict:
|
||||
"""创建 Deploy Key"""
|
||||
data = {
|
||||
"title": title,
|
||||
"key": key,
|
||||
"read_only": read_only
|
||||
}
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/keys", json=data).json()
|
||||
|
||||
def delete_deploy_key(self, owner: str, repo: str, key_id: int) -> None:
|
||||
"""删除 Deploy Key"""
|
||||
self._request("DELETE", f"/repos/{owner}/{repo}/keys/{key_id}")
|
||||
|
||||
# ==================== 标签操作 ====================
|
||||
|
||||
def list_tags(self, owner: str, repo: str, page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""列出仓库的标签"""
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/tags",
|
||||
params={"page": page, "limit": limit}).json()
|
||||
|
||||
def create_tag(self, owner: str, repo: str, tag_name: str, target: str,
|
||||
message: str = "", **kwargs) -> Dict:
|
||||
"""创建标签"""
|
||||
data = {
|
||||
"tag_name": tag_name,
|
||||
"target": target,
|
||||
"message": message
|
||||
}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", f"/repos/{owner}/{repo}/tags", json=data).json()
|
||||
|
||||
# ==================== 搜索操作 ====================
|
||||
|
||||
def search_repos(self, query: str, page: int = 1, limit: int = 50, **kwargs) -> List[Dict]:
|
||||
"""搜索仓库"""
|
||||
params = {"q": query, "page": page, "limit": limit}
|
||||
params.update(kwargs)
|
||||
return self._request("GET", "/repos/search", params=params).json().get("data", [])
|
||||
|
||||
def search_issues(self, owner: str, repo: str, query: str,
|
||||
page: int = 1, limit: int = 50) -> List[Dict]:
|
||||
"""搜索 Issue"""
|
||||
params = {"q": query, "page": page, "limit": limit}
|
||||
return self._request("GET", f"/repos/{owner}/{repo}/issues/search", params=params).json()
|
||||
|
||||
# ==================== 团队操作 ====================
|
||||
|
||||
def list_org_teams(self, org: str) -> List[Dict]:
|
||||
"""列出组织的团队"""
|
||||
return self._request("GET", f"/orgs/{org}/teams").json()
|
||||
|
||||
def create_team(self, org: str, name: str, permission: str = "read", **kwargs) -> Dict:
|
||||
"""创建团队"""
|
||||
data = {"name": name, "permission": permission}
|
||||
data.update(kwargs)
|
||||
return self._request("POST", f"/orgs/{org}/teams", json=data).json()
|
||||
|
||||
def add_team_member(self, org: str, team: str, username: str) -> None:
|
||||
"""添加团队成员"""
|
||||
self._request("PUT", f"/orgs/{org}/teams/{team}/members/{username}")
|
||||
|
||||
def remove_team_member(self, org: str, team: str, username: str) -> None:
|
||||
"""移除团队成员"""
|
||||
self._request("DELETE", f"/orgs/{org}/teams/{team}/members/{username}")
|
||||
|
||||
def add_team_repo(self, org: str, team: str, owner: str, repo: str) -> None:
|
||||
"""添加团队仓库"""
|
||||
self._request("PUT", f"/orgs/{org}/teams/{team}/repos/{owner}/{repo}")
|
||||
|
||||
def remove_team_repo(self, org: str, team: str, owner: str, repo: str) -> None:
|
||||
"""移除团队仓库"""
|
||||
self._request("DELETE", f"/orgs/{org}/teams/{team}/repos/{owner}/{repo}")
|
||||
|
||||
|
||||
def main():
|
||||
"""命令行入口"""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Gitea API Client")
|
||||
parser.add_argument("--url", default=None, help="Gitea URL")
|
||||
parser.add_argument("--token", default=None, help="API Token")
|
||||
parser.add_argument("command", help="要执行的命令")
|
||||
parser.add_argument("args", nargs="*", help="命令参数")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
client = GiteaClient(url=args.url, token=args.token)
|
||||
|
||||
if args.command == "list-repos":
|
||||
repos = client.list_my_repos()
|
||||
for r in repos:
|
||||
print(f"{r['full_name']}: {r.get('description', '')}")
|
||||
|
||||
elif args.command == "get-repo":
|
||||
owner, repo = args.args[0].split("/")
|
||||
r = client.get_repo(owner, repo)
|
||||
print(json.dumps(r, indent=2))
|
||||
|
||||
elif args.command == "create-repo":
|
||||
name = args.args[0]
|
||||
description = args.args[1] if len(args.args) > 1 else ""
|
||||
r = client.create_repo(name, description)
|
||||
print(json.dumps(r, indent=2))
|
||||
|
||||
elif args.command == "delete-repo":
|
||||
owner, repo = args.args[0].split("/")
|
||||
client.delete_repo(owner, repo)
|
||||
print(f"Repository {owner}/{repo} deleted")
|
||||
|
||||
else:
|
||||
print(f"Unknown command: {args.command}")
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user