Merge PR #268: feat(branch): add lifecycle shortcuts
# Conflicts: # README.zh-CN.md # shortcuts/branch/branch.go
This commit is contained in:
commit
d77c12593e
|
|
@ -460,6 +460,10 @@ gitlink-cli pr +review --owner Gitlink --repo forgeplus -i 42 --status approved
|
|||
```bash
|
||||
# List branches
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus --keyword fix --state deleted
|
||||
|
||||
# List all branches without pagination
|
||||
gitlink-cli branch +all --owner Gitlink --repo forgeplus
|
||||
|
||||
# Create a branch
|
||||
gitlink-cli branch +create --name feature/new-feature
|
||||
|
|
@ -472,6 +476,10 @@ gitlink-cli branch +protect --name main
|
|||
|
||||
# Remove branch protection
|
||||
gitlink-cli branch +unprotect --name main
|
||||
|
||||
# Set default branch or restore a deleted branch (preview first)
|
||||
gitlink-cli branch +set-default --owner Gitlink --repo forgeplus --name main --dry-run
|
||||
gitlink-cli branch +restore --owner Gitlink --repo forgeplus --id 7 --name feature/old --dry-run
|
||||
```
|
||||
|
||||
### Release Management
|
||||
|
|
|
|||
384
README.zh-CN.md
384
README.zh-CN.md
|
|
@ -107,24 +107,19 @@
|
|||
| 🐛 Issue | 创建、更新、关闭、批量关闭/更新/删除、评论 Issue |
|
||||
| 🔖 标签 | 创建、列出、更新、删除 Issue 标签 |
|
||||
| 🔀 PR | 创建、合并、Review Pull Request,查看变更文件 |
|
||||
| 🧭 Compare | 对比分支、标签或提交,查看变更文件,筛选提交并汇总差异热点 |
|
||||
| 👥 成员 | 列出、添加、移除仓库成员,调整角色,生成和接受邀请链接 |
|
||||
| 📨 邀请 | 生成邀请链接、查看邀请信息、接受邀请、加入/退出项目 |
|
||||
| 🌿 分支 | 创建、删除、保护分支 |
|
||||
| 🏷️ 发布 | 创建、编辑、更新、查看、删除 Release |
|
||||
| 🏢 组织 | 管理组织、列出成员、查看团队 |
|
||||
| 🏢 组织 | 管理组织、成员、团队 |
|
||||
| 🔧 CI | 查看构建、日志、CI/CD 操作 |
|
||||
| ⚙️ Pipeline | 运行、查看、启停、删除流水线工作流并查询日志 |
|
||||
| 🔔 消息通知设置 | 查看并更新个人消息通知投递偏好 |
|
||||
| 📖 Wiki | 列出、查看、创建、更新、删除 Wiki 页面 |
|
||||
| 🔔 通知 | 列出、已读、删除用户消息 |
|
||||
| 🔍 搜索 | 搜索仓库、用户 |
|
||||
| 📊 数据集 | 按项目查询科研数据集 |
|
||||
| 👤 用户 | 查看用户资料、贡献热力图、活跃度与能力统计 |
|
||||
| 👤 用户 | 查看用户资料和信息 |
|
||||
| 📊 画像 | 用户开发能力、角色定位、专业定位、近期活动、贡献热力图统计 |
|
||||
| 📋 项目管理 | Sprint 管理、看板、周报 |
|
||||
| 🤖 工作流 | AI 驱动的 Issue 分类、PR Review、Release Notes |
|
||||
| 🩺 Doctor | 一键体检配置、认证、仓库上下文与 API 连通性 |
|
||||
|
||||
## 安装与快速上手
|
||||
|
||||
|
|
@ -185,29 +180,6 @@ export GITLINK_TOKEN="your-token" # 或设置环境变量(适用于 CI/CD、
|
|||
gitlink-cli repo +list
|
||||
```
|
||||
|
||||
#### Shell 自动补全
|
||||
|
||||
安装后可以为常用 shell 生成自动补全脚本:
|
||||
|
||||
```bash
|
||||
# Bash
|
||||
mkdir -p ~/.local/share/bash-completion/completions
|
||||
gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli
|
||||
|
||||
# Zsh
|
||||
gitlink-cli completion zsh > "${fpath[1]}/_gitlink-cli"
|
||||
|
||||
# Fish
|
||||
mkdir -p ~/.config/fish/completions
|
||||
gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish
|
||||
|
||||
# PowerShell
|
||||
gitlink-cli completion powershell > gitlink-cli.ps1
|
||||
. ./gitlink-cli.ps1
|
||||
```
|
||||
|
||||
如果当前终端不需要补全说明文本,可以追加 `--no-descriptions` 生成更精简的脚本。
|
||||
|
||||
### 快速上手(AI Agent)
|
||||
|
||||
> 以下步骤面向 AI Agent。部分步骤需要用户在浏览器中完成操作。
|
||||
|
|
@ -259,17 +231,8 @@ gitlink-cli repo +list
|
|||
# 查看仓库信息
|
||||
gitlink-cli repo +info --owner Gitlink --repo forgeplus
|
||||
|
||||
# 使用 git 克隆仓库(对标 `gh repo clone`)
|
||||
gitlink-cli repo +clone --owner Gitlink --repo forgeplus
|
||||
gitlink-cli repo +clone --owner Gitlink --repo forgeplus -d ./forgeplus -b develop
|
||||
|
||||
# 读取仓库 README
|
||||
gitlink-cli repo +readme --owner Gitlink --repo forgeplus --ref master
|
||||
gitlink-cli repo +readme --owner Gitlink --repo forgeplus --ref master --path docs
|
||||
|
||||
# 读取仓库任意文件
|
||||
gitlink-cli repo +file --owner Gitlink --repo forgeplus --path go.mod --ref master
|
||||
gitlink-cli repo +file --owner Gitlink --repo forgeplus --path .gitignore --content-only
|
||||
|
||||
# 列出仓库根目录或指定目录文件
|
||||
gitlink-cli repo +tree --owner Gitlink --repo forgeplus --ref master
|
||||
|
|
@ -301,74 +264,8 @@ gitlink-cli repo +unlike --owner Gitlink --repo forgeplus --project-id 123
|
|||
# 创建仓库
|
||||
gitlink-cli repo +create -n my-project -d "项目描述"
|
||||
|
||||
# 更新仓库设置(只修改指定字段)
|
||||
gitlink-cli repo +edit --owner me --repo my-project -d "新描述" --website "https://example.org"
|
||||
gitlink-cli repo +edit --owner me --repo my-project --private true
|
||||
gitlink-cli repo +edit --owner me --repo my-project --default-branch main
|
||||
|
||||
# Fork 仓库
|
||||
gitlink-cli repo +fork --owner Gitlink --repo forgeplus
|
||||
|
||||
# 列出可接收仓库转移的组织
|
||||
gitlink-cli repo +transfer-orgs --owner Gitlink --repo forgeplus
|
||||
|
||||
# 预览仓库转移请求,不修改线上数据
|
||||
gitlink-cli repo +transfer --owner Gitlink --repo forgeplus --target-owner my-org --dry-run
|
||||
|
||||
# 确认后发起仓库转移
|
||||
gitlink-cli repo +transfer --owner Gitlink --repo forgeplus --target-owner my-org --yes
|
||||
|
||||
# 预览取消待处理的仓库转移
|
||||
gitlink-cli repo +transfer-cancel --owner Gitlink --repo forgeplus --dry-run
|
||||
|
||||
# 确认后取消待处理的仓库转移
|
||||
gitlink-cli repo +transfer-cancel --owner Gitlink --repo forgeplus --yes
|
||||
```
|
||||
|
||||
### 消息通知设置
|
||||
|
||||
```bash
|
||||
# 列出可用的消息通知设置分组和键
|
||||
gitlink-cli message-settings +catalog
|
||||
|
||||
# 查看当前用户生效中的消息通知设置
|
||||
gitlink-cli message-settings +view
|
||||
|
||||
# 只看另一个用户的仓库管理类消息设置
|
||||
gitlink-cli message-settings +view --login Mengz --group ManageProject
|
||||
|
||||
# 预览关闭指定设置键的站内通知,不发送请求
|
||||
gitlink-cli message-settings +update \
|
||||
--channel notification \
|
||||
--state off \
|
||||
--keys Normal::Permission,ManageProject::Issue \
|
||||
--dry-run
|
||||
|
||||
# 将预设应用到所有已知设置
|
||||
gitlink-cli message-settings +preset --name notification-only --all
|
||||
```
|
||||
|
||||
### 消息通知设置
|
||||
|
||||
```bash
|
||||
# 列出可用的消息通知设置分组和键
|
||||
gitlink-cli message-settings +catalog
|
||||
|
||||
# 查看当前用户生效中的消息通知设置
|
||||
gitlink-cli message-settings +view
|
||||
|
||||
# 只看另一个用户的仓库管理类消息设置
|
||||
gitlink-cli message-settings +view --login Mengz --group ManageProject
|
||||
|
||||
# 预览关闭指定设置键的站内通知,不发送请求
|
||||
gitlink-cli message-settings +update \
|
||||
--channel notification \
|
||||
--state off \
|
||||
--keys Normal::Permission,ManageProject::Issue \
|
||||
--dry-run
|
||||
|
||||
# 将预设应用到所有已知设置
|
||||
gitlink-cli message-settings +preset --name notification-only --all
|
||||
```
|
||||
|
||||
### Webhook 管理
|
||||
|
|
@ -391,13 +288,10 @@ gitlink-cli webhook +tasks --owner Gitlink --repo forgeplus --id 68
|
|||
### Wiki 管理
|
||||
|
||||
```bash
|
||||
# 列出 Wiki 页面(目录结构);省略 --project-id 时自动从仓库信息解析
|
||||
gitlink-cli wiki +list --owner Gitlink --repo forgeplus
|
||||
# 列出 Wiki 页面(目录结构)
|
||||
gitlink-cli wiki +list --owner Gitlink --repo forgeplus --project-id 12345
|
||||
|
||||
# 查看 Wiki 页面
|
||||
gitlink-cli wiki +view --owner Gitlink --repo forgeplus -n home
|
||||
|
||||
# 也可显式传 --project-id 以省去一次查询请求
|
||||
gitlink-cli wiki +view --owner Gitlink --repo forgeplus --project-id 12345 -n home
|
||||
|
||||
# 创建 Wiki 页面
|
||||
|
|
@ -413,25 +307,6 @@ gitlink-cli wiki +update --owner Gitlink --repo forgeplus --project-id 12345 -n
|
|||
gitlink-cli wiki +delete --owner Gitlink --repo forgeplus --project-id 12345 -n old-page
|
||||
```
|
||||
|
||||
### 通知管理
|
||||
|
||||
```bash
|
||||
# 列出当前用户未读系统消息
|
||||
gitlink-cli notification +list --type notification --status unread
|
||||
|
||||
# 列出指定用户的 @我消息
|
||||
gitlink-cli notification +list --user Mengz --type atme
|
||||
|
||||
# 标记消息为已读
|
||||
gitlink-cli notification +read --type atme --ids 101,102
|
||||
|
||||
# 将全部未读系统消息标记为已读
|
||||
gitlink-cli notification +read --type notification --ids -1
|
||||
|
||||
# 删除消息
|
||||
gitlink-cli notification +delete --type notification --ids 101,102
|
||||
```
|
||||
|
||||
### 成员管理
|
||||
|
||||
```bash
|
||||
|
|
@ -452,29 +327,6 @@ gitlink-cli member +role --owner Gitlink --repo forgeplus --user-id 101 --role D
|
|||
|
||||
# 生成邀请链接
|
||||
gitlink-cli member +invite-link --owner Gitlink --repo forgeplus --role developer --apply true
|
||||
|
||||
# 通过邀请码申请加入项目
|
||||
gitlink-cli member +apply --code MPzQgH --role developer --dry-run
|
||||
|
||||
# 退出仓库成员关系
|
||||
gitlink-cli member +quit --owner Gitlink --repo forgeplus --dry-run
|
||||
gitlink-cli member +quit --owner Gitlink --repo forgeplus --yes
|
||||
```
|
||||
|
||||
### 组织管理
|
||||
|
||||
```bash
|
||||
# 列出组织
|
||||
gitlink-cli org +list
|
||||
|
||||
# 查看组织详情
|
||||
gitlink-cli org +info --id Gitlink
|
||||
|
||||
# 列出组织成员
|
||||
gitlink-cli org +members --id Gitlink --page 1 --limit 20
|
||||
|
||||
# 列出组织团队
|
||||
gitlink-cli org +teams --id Gitlink --page 1 --limit 20
|
||||
```
|
||||
|
||||
### Issue 管理
|
||||
|
|
@ -498,9 +350,6 @@ gitlink-cli issue +update --owner Gitlink --repo forgeplus --number 123 --priori
|
|||
# 关闭 Issue
|
||||
gitlink-cli issue +close --owner Gitlink --repo forgeplus -i 123
|
||||
|
||||
# 删除 Issue(破坏性操作,需 --yes 确认)
|
||||
gitlink-cli issue +delete --owner Gitlink --repo forgeplus --number 123 --yes
|
||||
|
||||
# 预览批量关闭,不修改数据
|
||||
gitlink-cli issue +batch-close --owner Gitlink --repo forgeplus --numbers 123,124 --dry-run
|
||||
|
||||
|
|
@ -553,35 +402,8 @@ gitlink-cli label +create --owner Gitlink --repo forgeplus -n bug -d "功能缺
|
|||
# 更新标签(未指定的字段会被保留)
|
||||
gitlink-cli label +update --owner Gitlink --repo forgeplus -i 42 -c "#00FF00"
|
||||
|
||||
# 安全删除标签
|
||||
gitlink-cli label +delete --owner Gitlink --repo forgeplus -i 42 --dry-run
|
||||
gitlink-cli label +delete --owner Gitlink --repo forgeplus -i 42 --yes
|
||||
|
||||
# 安全批量创建标签
|
||||
gitlink-cli label +batch-create --owner Gitlink --repo forgeplus \
|
||||
--labels 'bug:#ee0701:Bug 修复;feature:#0075ca:新功能' --dry-run
|
||||
gitlink-cli label +batch-create --owner Gitlink --repo forgeplus \
|
||||
--labels 'bug:#ee0701:Bug 修复;feature:#0075ca:新功能' --yes
|
||||
|
||||
# 安全批量删除标签
|
||||
gitlink-cli label +batch-delete --owner Gitlink --repo forgeplus --ids 3,5,8 --dry-run
|
||||
gitlink-cli label +batch-delete --owner Gitlink --repo forgeplus --ids 3,5,8 --yes
|
||||
```
|
||||
|
||||
### Compare
|
||||
|
||||
```bash
|
||||
# 对比两个分支、标签或提交
|
||||
gitlink-cli compare +view --owner Gitlink --repo forgeplus --head feature/search --base master
|
||||
|
||||
# 列出两个版本之间的变更文件
|
||||
gitlink-cli compare +files --owner Gitlink --repo forgeplus --head feature/search --base master
|
||||
|
||||
# 按作者或关键字筛选提交
|
||||
gitlink-cli compare +commits --owner Gitlink --repo forgeplus --head feature/search --base master --author alice -k fix -l 10
|
||||
|
||||
# 汇总提交、热点文件、目录分布和扩展名分布
|
||||
gitlink-cli compare +summary --owner Gitlink --repo forgeplus --head feature/search --base master --top-files 5
|
||||
# 删除标签
|
||||
gitlink-cli label +delete --owner Gitlink --repo forgeplus -i 42
|
||||
```
|
||||
|
||||
### Pull Request
|
||||
|
|
@ -598,11 +420,6 @@ gitlink-cli pr +create --owner Gitlink --repo forgeplus -t "feat: 新功能" --h
|
|||
|
||||
# 查看 PR
|
||||
gitlink-cli pr +view --owner Gitlink --repo forgeplus -i 42
|
||||
# 对于已合并或已关闭的 PR,JSON 输出会尽量补齐 `created_at`、`merged_at`、`closed_at` 和 `closed_on`。
|
||||
|
||||
# 在本地检出 PR 分支(对标 `gh pr checkout`;需在 git 克隆目录内执行)
|
||||
gitlink-cli pr +checkout --owner Gitlink --repo forgeplus -i 42
|
||||
gitlink-cli pr +checkout --owner Gitlink --repo forgeplus -i 42 -b review-42
|
||||
|
||||
# 合并 PR
|
||||
gitlink-cli pr +merge --owner Gitlink --repo forgeplus -i 42
|
||||
|
|
@ -625,33 +442,27 @@ gitlink-cli pr +reviews --owner Gitlink --repo forgeplus -i 42
|
|||
# 创建 PR 审查(支持 dry-run 预览)
|
||||
gitlink-cli pr +review --owner Gitlink --repo forgeplus -i 42 --status approved -c "LGTM" --dry-run
|
||||
gitlink-cli pr +review --owner Gitlink --repo forgeplus -i 42 --status approved -c "LGTM"
|
||||
|
||||
# 查看行级审查评论和未解决讨论
|
||||
gitlink-cli pr +review-comments --owner Gitlink --repo forgeplus -i 42 --state opened --need-respond true --full
|
||||
|
||||
# 创建行级审查评论或回复
|
||||
gitlink-cli pr +review-comment --owner Gitlink --repo forgeplus -i 42 -b "请处理这个边界情况" --type problem --review-id 7 --line-code abc_1_2 --commit deadbeef --path main.go --dry-run
|
||||
|
||||
# 解决、编辑或删除审查评论
|
||||
gitlink-cli pr +review-comment-update --owner Gitlink --repo forgeplus -i 42 --comment-id 99 --state resolved
|
||||
gitlink-cli pr +review-comment-delete --owner Gitlink --repo forgeplus -i 42 --comment-id 99
|
||||
```
|
||||
|
||||
### 工作流 Agent 命令
|
||||
### 分支管理
|
||||
|
||||
```bash
|
||||
# 只读获取 PR 审查上下文包(仓库、PR、文件、Review、Issue、标签)
|
||||
gitlink-cli workflow +review-context --owner Gitlink --repo forgeplus --number 42 --format json
|
||||
# 列出分支,支持关键词和删除分支过滤
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus --keyword fix --state deleted
|
||||
|
||||
# 生成 PR 审查摘要
|
||||
gitlink-cli workflow +pr-summary --owner Gitlink --repo forgeplus --number 42 --format markdown
|
||||
# 无分页列出全部分支
|
||||
gitlink-cli branch +all --owner Gitlink --repo forgeplus
|
||||
|
||||
# 生成仓库工作流报告
|
||||
gitlink-cli workflow +repo-report --owner Gitlink --repo forgeplus --format markdown
|
||||
# 创建 / 删除分支
|
||||
gitlink-cli branch +create --owner Gitlink --repo forgeplus --name feature/new-feature
|
||||
gitlink-cli branch +delete --owner Gitlink --repo forgeplus --name feature/old-feature
|
||||
|
||||
# 设置默认分支或恢复已删除分支(先 dry-run 预览)
|
||||
gitlink-cli branch +set-default --owner Gitlink --repo forgeplus --name main --dry-run
|
||||
gitlink-cli branch +restore --owner Gitlink --repo forgeplus --id 7 --name feature/old --dry-run
|
||||
```
|
||||
|
||||
> `workflow +review-context` 只读取 GitLink 数据,不会评论、审批、拒绝、合并或修改标签。
|
||||
|
||||
### 发布管理
|
||||
|
||||
```bash
|
||||
|
|
@ -672,26 +483,6 @@ gitlink-cli release +update --owner Gitlink --repo forgeplus -i <version_id> -b
|
|||
gitlink-cli release +delete --owner Gitlink --repo forgeplus -i <version_id> --dry-run
|
||||
```
|
||||
|
||||
### CI/CD 操作
|
||||
|
||||
```bash
|
||||
# 查看构建列表
|
||||
gitlink-cli ci +builds --owner Gitlink --repo forgeplus
|
||||
|
||||
# 查看构建日志
|
||||
gitlink-cli ci +logs --owner Gitlink --repo forgeplus --build <build_id>
|
||||
|
||||
# 重启或停止构建
|
||||
gitlink-cli ci +restart --owner Gitlink --repo forgeplus --build <build_id>
|
||||
gitlink-cli ci +stop --owner Gitlink --repo forgeplus --build <build_id>
|
||||
|
||||
# 查看 CI 授权状态并安全启停仓库 CI
|
||||
gitlink-cli ci +authorize --owner Gitlink --repo forgeplus
|
||||
gitlink-cli ci +activate --owner Gitlink --repo forgeplus --dry-run
|
||||
gitlink-cli ci +activate --owner Gitlink --repo forgeplus --yes
|
||||
gitlink-cli ci +deactivate --owner Gitlink --repo forgeplus --dry-run
|
||||
```
|
||||
|
||||
### 流水线管理
|
||||
|
||||
```bash
|
||||
|
|
@ -714,25 +505,6 @@ gitlink-cli pipeline +disable --owner Gitlink --repo forgeplus --id 7 --workflow
|
|||
gitlink-cli pipeline +delete --owner Gitlink --repo forgeplus --id 7 --dry-run
|
||||
```
|
||||
|
||||
### 项目邀请管理
|
||||
|
||||
```bash
|
||||
# 生成邀请链接
|
||||
gitlink-cli invite +generate --owner Gitlink --repo forgeplus --role developer --is-apply true
|
||||
|
||||
# 查看邀请链接信息
|
||||
gitlink-cli invite +show --owner Gitlink --repo forgeplus --invite-sign abc123
|
||||
|
||||
# 通过链接接受邀请
|
||||
gitlink-cli invite +accept --owner Gitlink --repo forgeplus --invite-sign abc123
|
||||
|
||||
# 通过邀请码加入项目
|
||||
gitlink-cli invite +join --code ABCDEF --role developer
|
||||
|
||||
# 退出项目
|
||||
gitlink-cli invite +quit --owner Gitlink --repo forgeplus
|
||||
```
|
||||
|
||||
### 忽略文件模板
|
||||
|
||||
```bash
|
||||
|
|
@ -743,21 +515,6 @@ gitlink-cli ignore +list
|
|||
gitlink-cli ignore +list --name Go
|
||||
```
|
||||
|
||||
### 用户统计
|
||||
|
||||
```bash
|
||||
# 用户资料与当前账户
|
||||
gitlink-cli user +me
|
||||
gitlink-cli user +info --login alice
|
||||
|
||||
# 贡献和活跃度分析
|
||||
gitlink-cli user +activity --login alice
|
||||
gitlink-cli user +headmap --login alice --year 2026
|
||||
gitlink-cli user +develop --login alice --start-time 1717200000 --end-time 1719800000
|
||||
gitlink-cli user +role --login alice
|
||||
gitlink-cli user +major --login alice
|
||||
```
|
||||
|
||||
### 搜索
|
||||
|
||||
```bash
|
||||
|
|
@ -766,9 +523,6 @@ gitlink-cli search +repos -k "machine learning"
|
|||
|
||||
# 搜索用户
|
||||
gitlink-cli search +users -k "zhangsan"
|
||||
|
||||
# 列出推荐/精选项目
|
||||
gitlink-cli search +recommend
|
||||
```
|
||||
|
||||
### 用户画像
|
||||
|
|
@ -794,49 +548,6 @@ gitlink-cli profile +activity
|
|||
gitlink-cli profile +contribution --user zhangsan --year 2025
|
||||
```
|
||||
|
||||
### Workflow Agent 命令
|
||||
|
||||
`workflow` 提供面向维护者和 AI Agent 的规则化仓库分析能力,目前支持:
|
||||
|
||||
- `workflow +triage`
|
||||
- `workflow +health`
|
||||
- `workflow +pr-summary`
|
||||
- `workflow +repo-report`
|
||||
- `workflow +release-notes`
|
||||
|
||||
`workflow +pr-summary` 在未指定 `--format` 时默认输出 `table`。
|
||||
`workflow +repo-report` 和 `workflow +release-notes` 在未指定 `--format` 时默认输出 `markdown`。
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
# Issue 分诊
|
||||
gitlink-cli workflow +triage --title "安装失败" --body "运行 go install 时报错" --format table
|
||||
|
||||
# 仓库健康度
|
||||
gitlink-cli workflow +health --owner Gitlink --repo gitlink-cli --stale-days 30 --format table
|
||||
|
||||
# PR 审阅摘要
|
||||
gitlink-cli workflow +pr-summary --owner Gitlink --repo gitlink-cli --number 1 --format markdown
|
||||
|
||||
# 仓库工作流报告
|
||||
gitlink-cli workflow +repo-report --owner Gitlink --repo gitlink-cli --format markdown
|
||||
|
||||
# 基于只读 compare fetch 生成 Release Notes
|
||||
gitlink-cli workflow +release-notes --owner Gitlink --repo gitlink-cli --from-ref v0.1.0 --to-ref master --version v0.2.0 --format markdown
|
||||
|
||||
# 从本地 JSON 生成 Release Notes
|
||||
gitlink-cli workflow +release-notes --from shortcuts/workflow/testdata/release_notes.json --format json
|
||||
```
|
||||
|
||||
安全边界:
|
||||
|
||||
- 当前 workflow 命令默认只读,可读取 GitLink 数据或本地 JSON。
|
||||
- 不依赖 LLM API。
|
||||
- `workflow +pr-summary` 不评论、不 approve/reject、不合并 PR。
|
||||
- `workflow +repo-report` 聚合健康度、Issue 分诊和 PR 摘要信号,不写远端。
|
||||
- `workflow +release-notes` 只读取 compare 数据并渲染版本说明,不创建 Release 或评论。
|
||||
|
||||
### 数据集
|
||||
|
||||
`dataset` 管理并查询 GitLink 科研数据集(标题、描述、论文内容、许可证、所属项目)。
|
||||
|
|
@ -858,21 +569,6 @@ gitlink-cli dataset +delete-attachment --owner me --repo proj --uuid <uuid> --ye
|
|||
```
|
||||
|
||||
> 注意:`dataset +list`(平台数据集查询)已在生产 gitlink.org.cn 验证可用。按仓库的 `+view`/`+create`/`+update` 遵循已发布的 OpenAPI 契约,但生产环境尚未部署(当前返回 404),待平台上线后即可生效。
|
||||
### 环境自诊断(Doctor)
|
||||
|
||||
```bash
|
||||
# 运行全部检查:配置文件、配置取值、认证、仓库上下文、API 连通性
|
||||
gitlink-cli doctor
|
||||
|
||||
# 结构化输出,适合脚本 / AI Agent 使用
|
||||
gitlink-cli doctor --format json
|
||||
|
||||
# 离线模式:跳过需认证的 API 连通性检查
|
||||
gitlink-cli doctor --skip-network
|
||||
```
|
||||
|
||||
每项检查返回 `ok` / `warning` / `error` 及修复建议(suggestion);warning 不影响使用。
|
||||
|
||||
### Raw API
|
||||
|
||||
Shortcuts 未覆盖的接口可通过 Raw API 直接调用:
|
||||
|
|
@ -892,38 +588,8 @@ Get-Content issue.json | gitlink-cli api POST /Gitlink/forgeplus/issues --body-s
|
|||
|
||||
# 带查询参数
|
||||
gitlink-cli api GET /Gitlink/forgeplus/commits --query 'page=1&limit=5'
|
||||
|
||||
# 鍗曟璇锋眰涓洿鎺ュ鐢?--owner / --repo 鍗犱綅绗?
|
||||
gitlink-cli api GET /:owner/:repo/issues --owner Gitlink --repo gitlink-cli --query 'page=1&limit=5'
|
||||
|
||||
# 鍦?path / query / body / header 涓覆鏌撲竴娆℃€фā鏉垮彉閲?
|
||||
gitlink-cli api POST /{{owner}}/{{repo}}/issues/{{number}}/journals \
|
||||
--var owner=Gitlink --var repo=gitlink-cli --var number=42 --var actor=codex \
|
||||
--query 'notify={{actor}}' \
|
||||
--header 'X-Actor: {{actor}}' \
|
||||
--body '{"notes":"handled by {{actor}}"}'
|
||||
```
|
||||
|
||||
### Shell 自动补全
|
||||
|
||||
`gitlink-cli` 内置 bash / zsh / fish / PowerShell 补全:
|
||||
|
||||
```bash
|
||||
# Bash(加入 ~/.bashrc)
|
||||
source <(gitlink-cli completion bash)
|
||||
|
||||
# Zsh(加入 ~/.zshrc)
|
||||
source <(gitlink-cli completion zsh)
|
||||
|
||||
# Fish
|
||||
gitlink-cli completion fish | source
|
||||
|
||||
# PowerShell
|
||||
gitlink-cli completion powershell | Out-String | Invoke-Expression
|
||||
```
|
||||
|
||||
各 shell 的一次性安装方式见 `gitlink-cli completion <shell> --help`。
|
||||
|
||||
## 全局参数
|
||||
|
||||
| 参数 | 说明 | 示例 |
|
||||
|
|
@ -932,8 +598,6 @@ gitlink-cli completion powershell | Out-String | Invoke-Expression
|
|||
| `--repo` | 仓库名称 | `--repo forgeplus` |
|
||||
| `--format` | 输出格式(json/table/yaml) | `--format json` |
|
||||
| `--debug` | 启用调试输出 | `--debug` |
|
||||
| `--lang` | 界面语言(en/zh) | `--lang zh` |
|
||||
| `--jq` | 按点分路径从输出中提取字段 | `--jq data.issues.0.subject` |
|
||||
|
||||
**自动上下文解析**:在 git 仓库目录下,`--owner` 和 `--repo` 会自动从 `git remote origin` 解析。
|
||||
|
||||
|
|
@ -970,12 +634,10 @@ git push gitlink
|
|||
| `gitlink-issue` | Issue 操作(创建、更新、关闭、批量更新/删除、评论等) |
|
||||
| `gitlink-pr` | Pull Request 操作(创建、合并、Review 等) |
|
||||
| `gitlink-member` | 仓库成员与邀请链接管理 |
|
||||
| `gitlink-invite` | 项目邀请管理(生成链接、接受邀请、加入/退出项目) |
|
||||
| `gitlink-release` | 发布管理(创建、编辑、更新、查看、删除等) |
|
||||
| `gitlink-org` | 组织管理(成员、团队等) |
|
||||
| `gitlink-ci` | CI/CD 操作(构建、日志等) |
|
||||
| `gitlink-pipeline` | 流水线工作流操作(运行、日志、启停、删除等) |
|
||||
| `gitlink-notification` | 用户消息(列表、标记已读、删除) |
|
||||
| `gitlink-search` | 搜索功能(仓库、用户等) |
|
||||
| `gitlink-user` | 用户管理(个人信息等) |
|
||||
| `gitlink-pm` | 项目管理(Sprint、看板、周报等) |
|
||||
|
|
@ -1076,14 +738,6 @@ gitlink-cli repo +list # 直接可用
|
|||
gitlink-cli auth status # 显示 "✓ Logged in via GITLINK_TOKEN environment variable"
|
||||
```
|
||||
|
||||
脚本中复用当前生效的 token(例如直接 `curl` CLI 尚未封装的端点):
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $(gitlink-cli auth token)" https://www.gitlink.org.cn/api/v1/...
|
||||
gitlink-cli auth status --show-token # 查看原始 token(默认隐藏)
|
||||
echo $MY_TOKEN | gitlink-cli auth login --with-token # 非交互登录(CI/脚本)
|
||||
```
|
||||
|
||||
Token 优先级:`GITLINK_TOKEN` 环境变量 > keyring/文件存储的 token。不设置环境变量时完全兼容原有交互式登录。
|
||||
|
||||
### Q: npm 安装成功但 `gitlink-cli` 提示缺少二进制怎么办?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# Branch Lifecycle Shortcuts
|
||||
|
||||
## Background
|
||||
|
||||
GitLink OpenAPI exposes branch lifecycle capabilities that were not fully reachable from `gitlink-cli`: keyword/state branch listing, no-pagination listing, default branch switching, and deleted branch restoration.
|
||||
|
||||
## What Changed
|
||||
|
||||
Extended the `branch` shortcut group with documented OpenAPI coverage:
|
||||
|
||||
- `branch +list --keyword --state` maps to `GET /api/v1/{owner}/{repo}/branches.json` query parameters.
|
||||
- `branch +all` maps to `GET /api/v1/{owner}/{repo}/branches/all.json`.
|
||||
- `branch +set-default --name` maps to `PATCH /api/v1/{owner}/{repo}/branches/update_default_branch.json?name=...`.
|
||||
- `branch +restore --id --name` maps to `POST /api/v1/{owner}/{repo}/branches/restore.json` with `branch_id` and `branch_name`.
|
||||
|
||||
Write operations support `--dry-run` so users and Agents can inspect the exact request before changing branch state.
|
||||
|
||||
## Validation
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
GOPROXY=https://goproxy.cn,direct go test ./shortcuts/branch ./shortcuts
|
||||
go vet ./shortcuts/branch ./shortcuts
|
||||
go run . branch +set-default --help
|
||||
go run . branch +restore --help
|
||||
GOPROXY=https://goproxy.cn,direct go test ./...
|
||||
go vet ./...
|
||||
```
|
||||
|
|
@ -3,6 +3,8 @@ package branch
|
|||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gitlink-org/gitlink-cli/internal/i18n"
|
||||
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
|
||||
|
|
@ -15,9 +17,10 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
Name: "list",
|
||||
Description: tr.T("cmd.branch.list.short"),
|
||||
Flags: []common.Flag{
|
||||
{Name: "keyword", Short: "k", Usage: tr.T("flag.branch.keyword")},
|
||||
{Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"},
|
||||
{Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"},
|
||||
{Name: "keyword", Short: "k", Usage: "Filter branches by keyword"},
|
||||
{Name: "state", Short: "s", Usage: "Branch state: all, deleted, or empty for active branches"},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
|
|
@ -26,9 +29,15 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
q := url.Values{}
|
||||
q.Set("page", ctx.Arg("page"))
|
||||
q.Set("limit", ctx.Arg("limit"))
|
||||
if keyword := ctx.Arg("keyword"); keyword != "" {
|
||||
if keyword := strings.TrimSpace(ctx.Arg("keyword")); keyword != "" {
|
||||
q.Set("keyword", keyword)
|
||||
}
|
||||
if state := strings.TrimSpace(ctx.Arg("state")); state != "" {
|
||||
if err := validateBranchState(state); err != nil {
|
||||
return err
|
||||
}
|
||||
q.Set("state", state)
|
||||
}
|
||||
env, err := ctx.CallAPIWithQuery("GET", "/v1"+ctx.RepoPath()+"/branches", q)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -38,8 +47,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
},
|
||||
{
|
||||
Name: "all",
|
||||
Description: tr.T("cmd.branch.all.short"),
|
||||
Flags: []common.Flag{},
|
||||
Description: "List all branches without pagination",
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
|
|
@ -56,7 +64,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
Description: tr.T("cmd.branch.create.short"),
|
||||
Flags: []common.Flag{
|
||||
{Name: "name", Short: "n", Usage: tr.T("flag.branch.name"), Required: true},
|
||||
{Name: "from", Short: "f", Usage: tr.T("flag.branch.from")},
|
||||
{Name: "from", Short: "f", Usage: tr.T("flag.branch.from"), Default: "master"},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
|
|
@ -65,10 +73,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
name, _ := ctx.RequireArg("name")
|
||||
from := ctx.Arg("from")
|
||||
if from == "" {
|
||||
var err error
|
||||
if from, err = ctx.DefaultBranch(); err != nil {
|
||||
return err
|
||||
}
|
||||
from = "master"
|
||||
}
|
||||
payload := map[string]interface{}{
|
||||
"new_branch_name": name,
|
||||
|
|
@ -102,42 +107,6 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "all",
|
||||
Description: tr.T("cmd.branch.all.short"),
|
||||
Flags: []common.Flag{},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
env, err := ctx.CallAPI("GET", "/v1"+ctx.RepoPath()+"/branches/all", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set-default",
|
||||
Description: tr.T("cmd.branch.set_default.short"),
|
||||
Flags: []common.Flag{
|
||||
{Name: "name", Short: "n", Usage: tr.T("flag.branch.name"), Required: true},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
name, err := ctx.RequireArg("name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env, err := ctx.CallAPI("PATCH", "/v1"+ctx.RepoPath()+"/branches/update_default_branch", map[string]interface{}{"name": name})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "protect",
|
||||
Description: tr.T("cmd.branch.protect.short"),
|
||||
|
|
@ -177,6 +146,25 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set-default",
|
||||
Description: "Set repository default branch",
|
||||
Flags: []common.Flag{
|
||||
{Name: "name", Short: "n", Usage: tr.T("flag.branch.name"), Required: true},
|
||||
{Name: "dry-run", Usage: "Preview the request without changing the default branch", Bool: true, Default: "false"},
|
||||
},
|
||||
Run: runSetDefault,
|
||||
},
|
||||
{
|
||||
Name: "restore",
|
||||
Description: "Restore a deleted branch",
|
||||
Flags: []common.Flag{
|
||||
{Name: "id", Short: "i", Usage: "Deleted branch ID", Required: true},
|
||||
{Name: "name", Short: "n", Usage: tr.T("flag.branch.name"), Required: true},
|
||||
{Name: "dry-run", Usage: "Preview the request without restoring the branch", Bool: true, Default: "false"},
|
||||
},
|
||||
Run: runRestore,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,3 +174,81 @@ func shortcutTranslator(translators ...*i18n.Translator) *i18n.Translator {
|
|||
}
|
||||
return i18n.Default()
|
||||
}
|
||||
|
||||
func runSetDefault(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
name, err := ctx.RequireArg("name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := "/v1" + ctx.RepoPath() + "/branches/update_default_branch"
|
||||
query := url.Values{}
|
||||
query.Set("name", name)
|
||||
if ctx.Arg("dry-run") == "true" {
|
||||
return ctx.OutputData(map[string]interface{}{
|
||||
"dry_run": true,
|
||||
"action": "set_default_branch",
|
||||
"method": "PATCH",
|
||||
"path": path,
|
||||
"query": query.Encode(),
|
||||
})
|
||||
}
|
||||
env, err := ctx.CallAPIWithQuery("PATCH", path, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
}
|
||||
|
||||
func runRestore(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
id, err := parsePositiveInt(ctx.Arg("id"), "id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name, err := ctx.RequireArg("name")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := "/v1" + ctx.RepoPath() + "/branches/restore"
|
||||
body := map[string]interface{}{
|
||||
"branch_id": id,
|
||||
"branch_name": name,
|
||||
}
|
||||
if ctx.Arg("dry-run") == "true" {
|
||||
return ctx.OutputData(map[string]interface{}{
|
||||
"dry_run": true,
|
||||
"action": "restore_branch",
|
||||
"method": "POST",
|
||||
"path": path,
|
||||
"body": body,
|
||||
})
|
||||
}
|
||||
env, err := ctx.CallAPI("POST", path, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
}
|
||||
|
||||
func validateBranchState(state string) error {
|
||||
switch state {
|
||||
case "all", "deleted":
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid --state %q: use all or deleted", state)
|
||||
}
|
||||
}
|
||||
|
||||
func parsePositiveInt(value, name string) (int64, error) {
|
||||
value = strings.TrimSpace(value)
|
||||
parsed, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil || parsed <= 0 {
|
||||
return 0, fmt.Errorf("invalid --%s %q: use a positive integer", name, value)
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,56 @@ func TestBranchList(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBranchListFilters(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/v1/owner/repo/branches.json" {
|
||||
t.Fatalf("unexpected path: %s", r.URL.Path)
|
||||
}
|
||||
if got := r.URL.Query().Get("keyword"); got != "feature" {
|
||||
t.Fatalf("keyword = %q, want feature", got)
|
||||
}
|
||||
if got := r.URL.Query().Get("state"); got != "deleted" {
|
||||
t.Fatalf("state = %q, want deleted", got)
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"total_count": 0, "branches": []interface{}{}})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
err := runShortcut(t, server, "list", map[string]string{
|
||||
"page": "1", "limit": "20", "keyword": "feature", "state": "deleted",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("list with filters failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchListRejectsInvalidState(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("invalid state should not call API, got %s %s", r.Method, r.URL.Path)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
err := runShortcut(t, server, "list", map[string]string{"page": "1", "limit": "20", "state": "open"})
|
||||
if err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchAll(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" || r.URL.Path != "/v1/owner/repo/branches/all.json" {
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
writeJSON(w, []interface{}{map[string]interface{}{"name": "master"}})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
err := runShortcut(t, server, "all", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("all failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// --- create ---
|
||||
|
||||
func TestBranchCreate(t *testing.T) {
|
||||
|
|
@ -161,6 +211,69 @@ func TestBranchUnprotect(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBranchSetDefault(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "PATCH" || r.URL.Path != "/v1/owner/repo/branches/update_default_branch.json" {
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
if got := r.URL.Query().Get("name"); got != "main" {
|
||||
t.Fatalf("name query = %q, want main", got)
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"status": 0, "message": "success"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
if err := runShortcut(t, server, "set-default", map[string]string{"name": "main"}); err != nil {
|
||||
t.Fatalf("set-default failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchSetDefaultDryRunDoesNotCallAPI(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("dry-run should not call API, got %s %s", r.Method, r.URL.Path)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
if err := runShortcut(t, server, "set-default", map[string]string{"name": "main", "dry-run": "true"}); err != nil {
|
||||
t.Fatalf("set-default dry-run failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchRestore(t *testing.T) {
|
||||
var payload map[string]interface{}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" || r.URL.Path != "/v1/owner/repo/branches/restore.json" {
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||
t.Fatalf("decode body: %v", err)
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"status": 0, "message": "success"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
if err := runShortcut(t, server, "restore", map[string]string{"id": "7", "name": "feature/deleted"}); err != nil {
|
||||
t.Fatalf("restore failed: %v", err)
|
||||
}
|
||||
if payload["branch_id"] != float64(7) {
|
||||
t.Fatalf("branch_id = %v, want 7", payload["branch_id"])
|
||||
}
|
||||
if payload["branch_name"] != "feature/deleted" {
|
||||
t.Fatalf("branch_name = %v, want feature/deleted", payload["branch_name"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchRestoreValidation(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("invalid restore should not call API, got %s %s", r.Method, r.URL.Path)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
if err := runShortcut(t, server, "restore", map[string]string{"id": "0", "name": "feature/deleted"}); err == nil {
|
||||
t.Fatal("expected invalid id error")
|
||||
}
|
||||
}
|
||||
|
||||
// --- HTTP error paths ---
|
||||
|
||||
func TestBranchListHTTPError(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: gitlink-branch
|
||||
version: 1.0.0
|
||||
description: "分支管理:创建、查看、删除、保护分支。当用户需要操作 GitLink 分支时触发。"
|
||||
version: 1.1.0
|
||||
description: "分支管理:创建、查看、过滤、删除、保护、设置默认分支、恢复已删除分支。当用户需要操作 GitLink 分支时触发。"
|
||||
metadata:
|
||||
requires:
|
||||
bins: ["gitlink-cli"]
|
||||
|
|
@ -21,10 +21,13 @@ metadata:
|
|||
| Shortcut | 说明 | 操作类型 |
|
||||
|----------|------|----------|
|
||||
| `branch +list` | 列出仓库的所有分支 | Read |
|
||||
| `branch +all` | 无分页列出仓库所有分支 | Read |
|
||||
| `branch +create` | 创建新分支 | ⚠️ Write Operation |
|
||||
| `branch +delete` | 删除分支 | 🔴 Destructive Operation |
|
||||
| `branch +protect` | 设置分支保护规则 | ⚠️ Write Operation |
|
||||
| `branch +unprotect` | 移除分支保护规则 | ⚠️ Write Operation |
|
||||
| `branch +set-default` | 设置默认分支 | ⚠️ Write Operation |
|
||||
| `branch +restore` | 恢复已删除分支 | ⚠️ Write Operation |
|
||||
|
||||
## 参数参考
|
||||
|
||||
|
|
@ -36,6 +39,17 @@ metadata:
|
|||
| `--repo` | 是* | 仓库名称(可从 git remote 自动推断) |
|
||||
| `--page, -p` | 否 | 页码(默认 `1`) |
|
||||
| `--limit, -l` | 否 | 每页条数(默认 `20`) |
|
||||
| `--keyword, -k` | 否 | 分支关键词过滤 |
|
||||
| `--state, -s` | 否 | 分支状态:`all` 或 `deleted` |
|
||||
| `--format` | 否 | 输出格式:`json`/`table`/`yaml` |
|
||||
| `--debug` | 否 | 启用调试输出 |
|
||||
|
||||
### branch +all
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--owner` | 是* | 仓库所有者(可从 git remote 自动推断) |
|
||||
| `--repo` | 是* | 仓库名称(可从 git remote 自动推断) |
|
||||
| `--format` | 否 | 输出格式:`json`/`table`/`yaml` |
|
||||
| `--debug` | 否 | 启用调试输出 |
|
||||
|
||||
|
|
@ -80,6 +94,29 @@ metadata:
|
|||
| `--format` | 否 | 输出格式:`json`/`table`/`yaml` |
|
||||
| `--debug` | 否 | 启用调试输出 |
|
||||
|
||||
### branch +set-default
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--name, -n` | 是 | 要设为默认分支的名称 |
|
||||
| `--dry-run` | 否 | 预览请求,不修改默认分支 |
|
||||
| `--owner` | 是* | 仓库所有者(可从 git remote 自动推断) |
|
||||
| `--repo` | 是* | 仓库名称(可从 git remote 自动推断) |
|
||||
| `--format` | 否 | 输出格式:`json`/`table`/`yaml` |
|
||||
| `--debug` | 否 | 启用调试输出 |
|
||||
|
||||
### branch +restore
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--id, -i` | 是 | 已删除分支的 branch_id |
|
||||
| `--name, -n` | 是 | 要恢复的分支名称 |
|
||||
| `--dry-run` | 否 | 预览请求,不恢复分支 |
|
||||
| `--owner` | 是* | 仓库所有者(可从 git remote 自动推断) |
|
||||
| `--repo` | 是* | 仓库名称(可从 git remote 自动推断) |
|
||||
| `--format` | 否 | 输出格式:`json`/`table`/`yaml` |
|
||||
| `--debug` | 否 | 启用调试输出 |
|
||||
|
||||
> *如果在 GitLink 仓库目录下执行,`--owner` 和 `--repo` 可自动推断。
|
||||
|
||||
## 使用示例
|
||||
|
|
@ -91,6 +128,12 @@ gitlink-cli branch +list
|
|||
# 指定仓库并分页
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus --page 1 --limit 10
|
||||
|
||||
# 搜索分支或查看已删除分支
|
||||
gitlink-cli branch +list --owner Gitlink --repo forgeplus --keyword fix --state deleted
|
||||
|
||||
# 无分页列出所有分支
|
||||
gitlink-cli branch +all --owner Gitlink --repo forgeplus
|
||||
|
||||
# 输出为 JSON
|
||||
gitlink-cli branch +list --format json
|
||||
|
||||
|
|
@ -117,6 +160,14 @@ gitlink-cli branch +protect --name main --owner someone --repo myrepo
|
|||
|
||||
# 移除分支保护(仅简单分支名,含 / 的路径需通过 Web 操作)
|
||||
gitlink-cli branch +unprotect --name main
|
||||
|
||||
# 设置默认分支(先 dry-run 预览)
|
||||
gitlink-cli branch +set-default --name main --dry-run
|
||||
gitlink-cli branch +set-default --name main
|
||||
|
||||
# 恢复已删除分支(先 dry-run 预览)
|
||||
gitlink-cli branch +restore --id 7 --name feature/old --dry-run
|
||||
gitlink-cli branch +restore --id 7 --name feature/old
|
||||
```
|
||||
|
||||
## Workflow 注意事项
|
||||
|
|
@ -157,6 +208,24 @@ gitlink-cli branch +unprotect --name main
|
|||
2. 执行 `branch +unprotect --name <name>`。
|
||||
3. 输出结果。
|
||||
|
||||
### branch +set-default(Write Operation)
|
||||
|
||||
> [!CAUTION]
|
||||
> This is a **Write Operation** — confirm user intent.
|
||||
|
||||
1. 确认用户希望切换默认分支。
|
||||
2. 先执行 `branch +set-default --name <name> --dry-run` 预览。
|
||||
3. 用户确认后执行不带 `--dry-run` 的命令。
|
||||
|
||||
### branch +restore(Write Operation)
|
||||
|
||||
> [!CAUTION]
|
||||
> This is a **Write Operation** — confirm user intent.
|
||||
|
||||
1. 通过 `branch +list --state deleted` 确认 `branch_id` 和分支名。
|
||||
2. 先执行 `branch +restore --id <branch_id> --name <name> --dry-run` 预览。
|
||||
3. 用户确认后执行不带 `--dry-run` 的命令。
|
||||
|
||||
> **注意:** 含 `/` 的分支名(如 `feature/my-branch`)可能无法通过 CLI 解除保护(受限于 API 路由),需通过 Web 页面操作。
|
||||
|
||||
## References
|
||||
|
|
|
|||
Loading…
Reference in New Issue