Merge PR #383: feat(pr): add +commits and +check-merge
# Conflicts: # internal/i18n/locales/en-US.json # internal/i18n/locales/zh-CN.json
This commit is contained in:
commit
ab28113e1d
|
|
@ -389,6 +389,14 @@ gitlink-cli pr +reopen --owner Gitlink --repo forgeplus -i 42
|
|||
# View changed files
|
||||
gitlink-cli pr +files --owner Gitlink --repo forgeplus -i 42
|
||||
|
||||
# List commits of a pull request
|
||||
gitlink-cli pr +commits --owner Gitlink --repo forgeplus -i 42
|
||||
|
||||
# Pre-flight: can a merge request be created between two branches?
|
||||
gitlink-cli pr +check-merge --owner Gitlink --repo forgeplus --head develop --base master
|
||||
# Cross-fork variant
|
||||
gitlink-cli pr +check-merge --owner Gitlink --repo forgeplus --head feat/x --base master --fork-project-id 12345
|
||||
|
||||
# List PR patchset versions
|
||||
gitlink-cli pr +versions --owner Gitlink --repo forgeplus -i 42
|
||||
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@
|
|||
"cmd.org.list.short": "List organizations",
|
||||
"cmd.org.members.short": "List organization members",
|
||||
"cmd.org.short": "Organization operations",
|
||||
"cmd.pr.branches.short": "List pull request source and target branches",
|
||||
"cmd.pr.check_can_merge.short": "Check whether pull request branches can merge",
|
||||
"cmd.pr.check_merge.short": "Pre-flight check whether a merge request can be created between two branches",
|
||||
"cmd.pr.close.short": "Close a pull request",
|
||||
"cmd.pr.comment.short": "Add a comment to a pull request",
|
||||
"cmd.pr.commits.short": "List commits of a pull request",
|
||||
"cmd.pr.create.short": "Create a pull request",
|
||||
"cmd.pr.diff.short": "Show diff for a pull request",
|
||||
"cmd.pr.files.short": "List changed files in a pull request",
|
||||
|
|
@ -79,35 +79,23 @@
|
|||
"cmd.profile.role.short": "Show a user's role positioning",
|
||||
"cmd.profile.short": "User profile and statistics operations",
|
||||
"cmd.release.create.short": "Create a release",
|
||||
"cmd.release.assets.short": "List release assets",
|
||||
"cmd.release.attach.short": "Attach assets to a release",
|
||||
"cmd.release.delete.short": "Delete a release",
|
||||
"cmd.release.detach.short": "Detach assets from a release",
|
||||
"cmd.release.list.short": "List releases",
|
||||
"cmd.release.short": "Release operations",
|
||||
"cmd.release.upload.short": "Upload an asset and attach it to a release",
|
||||
"cmd.release.view.short": "View release details",
|
||||
"cmd.repo.create.short": "Create a new repository",
|
||||
"cmd.repo.delete.short": "Delete a repository",
|
||||
"cmd.repo.fork.short": "Fork a repository",
|
||||
"cmd.repo.info.short": "Show repository details",
|
||||
"cmd.repo.list.short": "List repositories for a user or organization",
|
||||
"cmd.repo.set_units.short": "Set enabled repository navigation units",
|
||||
"cmd.repo.short": "Repository operations",
|
||||
"cmd.repo.transfer.short": "Transfer a repository to another owner",
|
||||
"cmd.repo.transfer_cancel.short": "Cancel a pending repository transfer",
|
||||
"cmd.repo.transfer_orgs.short": "List organizations that can receive this repository",
|
||||
"cmd.repo.tree.short": "List repository files and directories",
|
||||
"cmd.repo.units.short": "List enabled repository navigation units",
|
||||
"cmd.root.long": "Manage repositories, issues, pull requests, releases, CI and workflows on GitLink.",
|
||||
"cmd.root.short": "GitLink CLI - command-line tool for GitLink",
|
||||
"cmd.search.repos.short": "Search repositories",
|
||||
"cmd.search.short": "Search operations",
|
||||
"cmd.search.users.short": "Search users",
|
||||
"cmd.user.add_key.short": "Add an SSH public key to the current user",
|
||||
"cmd.user.delete_key.short": "Delete one of the current user's SSH public keys",
|
||||
"cmd.user.info.short": "Show user profile",
|
||||
"cmd.user.keys.short": "List current user's SSH public keys",
|
||||
"cmd.user.me.short": "Show current authenticated user",
|
||||
"cmd.user.short": "User operations",
|
||||
"cmd.version.short": "Print version information",
|
||||
|
|
@ -195,8 +183,8 @@
|
|||
"flag.pr.assignee_id": "Assignee user ID",
|
||||
"flag.pr.base": "Target branch",
|
||||
"flag.pr.body": "PR description",
|
||||
"flag.pr.check_yes": "Confirm the remote merge readiness check",
|
||||
"flag.pr.file": "Filter diff by file path",
|
||||
"flag.pr.fork_project_id": "Fork project ID for cross-fork merge checks",
|
||||
"flag.pr.head": "Source branch",
|
||||
"flag.pr.id": "PR number",
|
||||
"flag.pr.merge_method": "Merge method: merge, rebase, squash",
|
||||
|
|
@ -227,21 +215,12 @@
|
|||
"flag.repo.description": "Repository description",
|
||||
"flag.repo.name": "Repository name",
|
||||
"flag.repo.private": "Make repository private (true/false)",
|
||||
"flag.repo.target_owner": "Target user or organization login",
|
||||
"flag.repo.transfer_cancel_dry_run": "Preview the cancel request without changing repository transfer state",
|
||||
"flag.repo.transfer_dry_run": "Preview the transfer request without changing repository ownership",
|
||||
"flag.repo.transfer_yes": "Confirm and execute the repository transfer action",
|
||||
"flag.repo.tree.path": "Directory path to list (default: repository root)",
|
||||
"flag.repo.tree.ref": "Branch, tag, or commit ref",
|
||||
"flag.repo.units": "Comma-separated units: code,issues,pulls,devops,versions,wiki,services,resources",
|
||||
"flag.search.keyword": "Search keyword",
|
||||
"flag.sort_by": "Sort field",
|
||||
"flag.sort_direction": "Sort direction: asc, desc",
|
||||
"flag.user": "User login (default: current user)",
|
||||
"flag.user.key.content": "SSH public key content",
|
||||
"flag.user.key.from": "Read SSH public key content from a file",
|
||||
"flag.user.key.id": "SSH key ID",
|
||||
"flag.user.key.title": "SSH key title. Defaults to the filename when --from is used.",
|
||||
"flag.user.login": "User login name",
|
||||
"flag.webhook.active": "Whether the webhook is active: true or false",
|
||||
"flag.webhook.branch_filter": "Branch glob filter for push/create/delete events",
|
||||
|
|
@ -291,19 +270,5 @@
|
|||
"success.config.set": "✓ {key} = {value}",
|
||||
"warning.auth.not_logged_in": "✗ Not logged in",
|
||||
"warning.auth.token_unverified": "✓ Token stored (but cannot verify: {message})",
|
||||
"warning.auth.user_unavailable": "✓ Token stored (user info unavailable)",
|
||||
"cmd.repo.contributors.short": "List repository contributors",
|
||||
"flag.contributors.chart": "Display contributors as ASCII chart (bar, pie, table, all)",
|
||||
"flag.contributors.limit": "Maximum number of contributors to display",
|
||||
"output.contributors.chart.title": "Contributors Overview",
|
||||
"output.contributors.chart.summary": "Total Contributors: {total} | Total Contributions: {count}",
|
||||
"output.contributors.chart.rankings": "Contributor Rankings",
|
||||
"output.contributors.chart.distribution": "Contribution Distribution",
|
||||
"output.contributors.chart.list": "Contributors List",
|
||||
"output.contributors.chart.no_data": "No contributors found",
|
||||
"error.contributors.chart.unsupported_type": "Unsupported chart type: {type} (use: bar, pie, table, or all)",
|
||||
"output.contributors.chart.total_contributions": "Total Contributions: {count}",
|
||||
"output.contributors.chart.table_header": "Rank Name Contributions Type",
|
||||
"output.contributors.chart.type_user": "User",
|
||||
"output.contributors.chart.type_organization": "Organization"
|
||||
"warning.auth.user_unavailable": "✓ Token stored (user info unavailable)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@
|
|||
"cmd.org.list.short": "列出组织",
|
||||
"cmd.org.members.short": "列出组织成员",
|
||||
"cmd.org.short": "组织操作",
|
||||
"cmd.pr.branches.short": "列出拉取请求可用源分支和目标分支",
|
||||
"cmd.pr.check_can_merge.short": "检查拉取请求分支是否可合并",
|
||||
"cmd.pr.check_merge.short": "预检两个分支之间能否创建合并请求",
|
||||
"cmd.pr.close.short": "关闭拉取请求",
|
||||
"cmd.pr.comment.short": "给拉取请求添加评论",
|
||||
"cmd.pr.commits.short": "列出合并请求的提交",
|
||||
"cmd.pr.create.short": "创建拉取请求",
|
||||
"cmd.pr.diff.short": "显示拉取请求 diff",
|
||||
"cmd.pr.files.short": "列出拉取请求中的变更文件",
|
||||
|
|
@ -79,35 +79,23 @@
|
|||
"cmd.profile.role.short": "显示用户角色定位",
|
||||
"cmd.profile.short": "用户画像与统计操作",
|
||||
"cmd.release.create.short": "创建发布",
|
||||
"cmd.release.assets.short": "列出发布资产",
|
||||
"cmd.release.attach.short": "为发布绑定资产",
|
||||
"cmd.release.delete.short": "删除发布",
|
||||
"cmd.release.detach.short": "从发布移除资产",
|
||||
"cmd.release.list.short": "列出发布",
|
||||
"cmd.release.short": "发布操作",
|
||||
"cmd.release.upload.short": "上传文件并绑定到发布",
|
||||
"cmd.release.view.short": "查看发布详情",
|
||||
"cmd.repo.create.short": "创建新仓库",
|
||||
"cmd.repo.delete.short": "删除仓库",
|
||||
"cmd.repo.fork.short": "Fork 仓库",
|
||||
"cmd.repo.info.short": "显示仓库详情",
|
||||
"cmd.repo.list.short": "列出用户或组织的仓库",
|
||||
"cmd.repo.set_units.short": "设置启用的仓库导航模块",
|
||||
"cmd.repo.short": "仓库操作",
|
||||
"cmd.repo.transfer.short": "将仓库转移给其他所有者",
|
||||
"cmd.repo.transfer_cancel.short": "取消待处理的仓库转移",
|
||||
"cmd.repo.transfer_orgs.short": "列出可接收该仓库的组织",
|
||||
"cmd.repo.tree.short": "列出仓库文件和目录",
|
||||
"cmd.repo.units.short": "列出启用的仓库导航模块",
|
||||
"cmd.root.long": "用于管理 GitLink 上的仓库、议题、拉取请求、发布、CI 和工作流。",
|
||||
"cmd.root.short": "GitLink CLI - GitLink 命令行工具",
|
||||
"cmd.search.repos.short": "搜索仓库",
|
||||
"cmd.search.short": "搜索操作",
|
||||
"cmd.search.users.short": "搜索用户",
|
||||
"cmd.user.add_key.short": "为当前用户添加 SSH 公钥",
|
||||
"cmd.user.delete_key.short": "删除当前用户的 SSH 公钥",
|
||||
"cmd.user.info.short": "显示用户资料",
|
||||
"cmd.user.keys.short": "列出当前用户的 SSH 公钥",
|
||||
"cmd.user.me.short": "显示当前认证用户",
|
||||
"cmd.user.short": "用户操作",
|
||||
"cmd.version.short": "打印版本信息",
|
||||
|
|
@ -195,8 +183,8 @@
|
|||
"flag.pr.assignee_id": "指派人用户 ID",
|
||||
"flag.pr.base": "目标分支",
|
||||
"flag.pr.body": "PR 描述",
|
||||
"flag.pr.check_yes": "确认执行远端可合并检查",
|
||||
"flag.pr.file": "按文件路径筛选 diff",
|
||||
"flag.pr.fork_project_id": "跨 fork 合并检查用的 fork 项目 ID",
|
||||
"flag.pr.head": "源分支",
|
||||
"flag.pr.id": "PR 编号",
|
||||
"flag.pr.merge_method": "合并方式:merge、rebase、squash",
|
||||
|
|
@ -227,21 +215,12 @@
|
|||
"flag.repo.description": "仓库描述",
|
||||
"flag.repo.name": "仓库名称",
|
||||
"flag.repo.private": "设为私有仓库(true/false)",
|
||||
"flag.repo.target_owner": "目标用户或组织登录名",
|
||||
"flag.repo.transfer_cancel_dry_run": "预览取消请求,不修改仓库转移状态",
|
||||
"flag.repo.transfer_dry_run": "预览转移请求,不修改仓库所有者",
|
||||
"flag.repo.transfer_yes": "确认并执行仓库转移相关操作",
|
||||
"flag.repo.tree.path": "要列出的目录路径(默认:仓库根目录)",
|
||||
"flag.repo.tree.ref": "分支、标签或提交引用",
|
||||
"flag.repo.units": "逗号分隔的模块:code,issues,pulls,devops,versions,wiki,services,resources",
|
||||
"flag.search.keyword": "搜索关键词",
|
||||
"flag.sort_by": "排序字段",
|
||||
"flag.sort_direction": "排序方向:asc、desc",
|
||||
"flag.user": "用户登录名(默认:当前用户)",
|
||||
"flag.user.key.content": "SSH 公钥内容",
|
||||
"flag.user.key.from": "从文件读取 SSH 公钥内容",
|
||||
"flag.user.key.id": "SSH 公钥 ID",
|
||||
"flag.user.key.title": "SSH 公钥标题。使用 --from 时默认取文件名。",
|
||||
"flag.user.login": "用户登录名",
|
||||
"flag.webhook.active": "Webhook 是否启用:true 或 false",
|
||||
"flag.webhook.branch_filter": "用于 push/create/delete 事件的分支 glob 筛选",
|
||||
|
|
@ -291,19 +270,5 @@
|
|||
"success.config.set": "✓ 已设置 {key} = {value}",
|
||||
"warning.auth.not_logged_in": "✗ 未登录",
|
||||
"warning.auth.token_unverified": "✓ Token 已保存(但无法验证:{message})",
|
||||
"warning.auth.user_unavailable": "✓ Token 已保存(用户信息不可用)",
|
||||
"cmd.repo.contributors.short": "列出仓库贡献者",
|
||||
"flag.contributors.chart": "以 ASCII 图表形式展示贡献者(bar, pie, table, all)",
|
||||
"flag.contributors.limit": "显示的最大贡献者数量",
|
||||
"output.contributors.chart.title": "贡献者概览",
|
||||
"output.contributors.chart.summary": "贡献者总数:{total} | 贡献总数:{count}",
|
||||
"output.contributors.chart.rankings": "贡献者排行榜",
|
||||
"output.contributors.chart.distribution": "贡献分布",
|
||||
"output.contributors.chart.list": "贡献者列表",
|
||||
"output.contributors.chart.no_data": "未找到贡献者",
|
||||
"error.contributors.chart.unsupported_type": "不支持的图表类型:{type}(请使用:bar, pie, table 或 all)",
|
||||
"output.contributors.chart.total_contributions": "贡献总数:{count}",
|
||||
"output.contributors.chart.table_header": "排名 名称 贡献次数 类型",
|
||||
"output.contributors.chart.type_user": "用户",
|
||||
"output.contributors.chart.type_organization": "组织"
|
||||
"warning.auth.user_unavailable": "✓ Token 已保存(用户信息不可用)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package pr
|
|||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gitlink-org/gitlink-cli/internal/i18n"
|
||||
|
|
@ -252,6 +253,57 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "commits",
|
||||
Description: tr.T("cmd.pr.commits.short"),
|
||||
Flags: []common.Flag{
|
||||
{Name: "id", Short: "i", Usage: tr.T("flag.pr.id"), Required: true},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := ctx.RequireArg("id")
|
||||
env, err := ctx.CallAPI("GET", fmt.Sprintf("%s/pulls/%s/commits", ctx.RepoPath(), id), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "check-merge",
|
||||
Description: tr.T("cmd.pr.check_merge.short"),
|
||||
Flags: []common.Flag{
|
||||
{Name: "head", Usage: tr.T("flag.pr.head"), Required: true},
|
||||
{Name: "base", Usage: tr.T("flag.pr.base"), Required: true},
|
||||
{Name: "fork-project-id", Usage: tr.T("flag.pr.fork_project_id")},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
return err
|
||||
}
|
||||
head, _ := ctx.RequireArg("head")
|
||||
base, _ := ctx.RequireArg("base")
|
||||
payload := map[string]interface{}{
|
||||
"head": head,
|
||||
"base": base,
|
||||
}
|
||||
if forkID := ctx.Arg("fork-project-id"); forkID != "" {
|
||||
id, err := strconv.Atoi(forkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("--fork-project-id must be an integer, got %q", forkID)
|
||||
}
|
||||
payload["fork_project_id"] = id
|
||||
payload["is_original"] = true
|
||||
}
|
||||
env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/pulls/check_can_merge", payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Output(env)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "diff",
|
||||
Description: tr.T("cmd.pr.diff.short"),
|
||||
|
|
|
|||
|
|
@ -1258,3 +1258,46 @@ func assertEqual(t *testing.T, got interface{}, want interface{}) {
|
|||
t.Fatalf("got %v (%T), want %v (%T)", got, got, want, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPRCommitsUsesCommitsEndpoint(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" || r.URL.Path != "/owner/repo/pulls/355/commits.json" {
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
writeJSON(t, w, map[string]interface{}{"commits_count": float64(1), "commits": []interface{}{}})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
if err := runPRShortcut(t, server, "commits", map[string]string{"id": "355"}); err != nil {
|
||||
t.Fatalf("commits failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPRCheckMergePostsBranchesAndForkTuple(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 != "/owner/repo/pulls/check_can_merge.json" {
|
||||
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
payload = decodeJSON(t, r)
|
||||
writeJSON(t, w, map[string]interface{}{"status": float64(0), "message": "可以合并"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
err := runPRShortcut(t, server, "check-merge", map[string]string{
|
||||
"head": "feat/x", "base": "master", "fork-project-id": "1549132",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("check-merge failed: %v", err)
|
||||
}
|
||||
assertEqual(t, payload["head"], "feat/x")
|
||||
assertEqual(t, payload["base"], "master")
|
||||
assertEqual(t, payload["fork_project_id"], float64(1549132))
|
||||
assertEqual(t, payload["is_original"], true)
|
||||
|
||||
if err := runPRShortcut(t, server, "check-merge", map[string]string{
|
||||
"head": "a", "base": "b", "fork-project-id": "abc",
|
||||
}); err == nil {
|
||||
t.Fatal("expected error for non-integer --fork-project-id")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue