fix: branch/pr/release default-branch awareness (drop hardcoded master)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
fcde26823b
commit
2dd580c208
|
|
@ -16,3 +16,10 @@
|
|||
|
||||
- `go test ./shortcuts/repo/`(默认 ref 断言改为「不携带 ref 参数」)
|
||||
- 生产 gitlink.org.cn 实测:默认分支为 `main` 与 `master` 的仓库均正常列出根目录。
|
||||
|
||||
## 追加:branch/pr/release 同类问题一并修复
|
||||
|
||||
- 新增 `RuntimeContext.DefaultBranch()`:读取仓库详情的 `default_branch`(缺失时回退 master)
|
||||
- `branch +create --from` / `pr +create --base` 未指定时回退到仓库默认分支(不再硬编码 master)
|
||||
- `release +create --target` 未指定时省略 `target_commitish`(平台自动落默认分支)
|
||||
- 生产实测(默认分支为 main 的仓库):`repo +tree` / `branch +create` / `release +create` 均成功
|
||||
|
|
|
|||
|
|
@ -37,7 +37,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"), Default: "master"},
|
||||
{Name: "from", Short: "f", Usage: tr.T("flag.branch.from")},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
|
|
@ -46,7 +46,10 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
name, _ := ctx.RequireArg("name")
|
||||
from := ctx.Arg("from")
|
||||
if from == "" {
|
||||
from = "master"
|
||||
var err error
|
||||
if from, err = ctx.DefaultBranch(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
payload := map[string]interface{}{
|
||||
"new_branch_name": name,
|
||||
|
|
|
|||
|
|
@ -81,12 +81,23 @@ func TestBranchCreate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBranchCreateDefaultFrom(t *testing.T) {
|
||||
// When 'from' is not set, it defaults to "master"
|
||||
// When 'from' is not set, it falls back to the repository default branch.
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/v1/owner/repo/branches.json" {
|
||||
switch r.URL.Path {
|
||||
case "/owner/repo.json":
|
||||
writeJSON(w, map[string]interface{}{"default_branch": "main"})
|
||||
case "/v1/owner/repo/branches.json":
|
||||
var payload map[string]interface{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||
t.Fatalf("decode payload: %v", err)
|
||||
}
|
||||
if payload["old_branch_name"] != "main" {
|
||||
t.Fatalf("expected old_branch_name to be default branch main, got %v", payload["old_branch_name"])
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"name": "feature-y"})
|
||||
default:
|
||||
t.Fatalf("unexpected path: %s", r.URL.Path)
|
||||
}
|
||||
writeJSON(w, map[string]interface{}{"name": "feature-y"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,20 @@ func (ctx *RuntimeContext) OutputData(data interface{}) error {
|
|||
return output.Print(output.SuccessEnvelope(data, nil), ctx.Format)
|
||||
}
|
||||
|
||||
// DefaultBranch fetches the repository's default branch, falling back to "master".
|
||||
func (ctx *RuntimeContext) DefaultBranch() (string, error) {
|
||||
env, err := ctx.CallAPI("GET", ctx.RepoPath(), nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if data, ok := env.Data.(map[string]interface{}); ok {
|
||||
if branch, ok := data["default_branch"].(string); ok && branch != "" {
|
||||
return branch, nil
|
||||
}
|
||||
}
|
||||
return "master", nil
|
||||
}
|
||||
|
||||
// RepoPath returns the API path prefix for the current owner/repo.
|
||||
func (ctx *RuntimeContext) RepoPath() string {
|
||||
return fmt.Sprintf("/%s/%s", ctx.Owner, ctx.Repo)
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
{Name: "title", Short: "t", Usage: tr.T("flag.pr.title"), Required: true},
|
||||
{Name: "body", Short: "b", Usage: tr.T("flag.pr.body")},
|
||||
{Name: "head", Usage: tr.T("flag.pr.head"), Required: true},
|
||||
{Name: "base", Usage: tr.T("flag.pr.base"), Default: "master"},
|
||||
{Name: "base", Usage: tr.T("flag.pr.base")},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
|
|
@ -106,7 +106,10 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
head, _ := ctx.RequireArg("head")
|
||||
base := ctx.Arg("base")
|
||||
if base == "" {
|
||||
base = "master"
|
||||
var err error
|
||||
if base, err = ctx.DefaultBranch(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
payload := map[string]interface{}{
|
||||
"title": title,
|
||||
|
|
|
|||
|
|
@ -209,6 +209,10 @@ func TestPRCreate(t *testing.T) {
|
|||
func TestPRCreateNoBody(t *testing.T) {
|
||||
var payload map[string]interface{}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/owner/repo.json" {
|
||||
writeJSON(t, w, map[string]interface{}{"default_branch": "main"})
|
||||
return
|
||||
}
|
||||
payload = decodeJSON(t, r)
|
||||
writeJSON(t, w, map[string]interface{}{"id": float64(43), "title": "feat: nob"})
|
||||
}))
|
||||
|
|
@ -224,6 +228,9 @@ func TestPRCreateNoBody(t *testing.T) {
|
|||
if _, ok := payload["body"]; ok {
|
||||
t.Fatal("body should not be in payload when not provided")
|
||||
}
|
||||
if payload["base"] != "main" {
|
||||
t.Fatalf("expected base to fall back to default branch main, got %v", payload["base"])
|
||||
}
|
||||
}
|
||||
|
||||
// --- view ---
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
|
|||
{Name: "tag", Short: "t", Usage: tr.T("flag.release.tag"), Required: true},
|
||||
{Name: "name", Short: "n", Usage: tr.T("flag.release.name"), Required: true},
|
||||
{Name: "body", Short: "b", Usage: tr.T("flag.release.body")},
|
||||
{Name: "target", Usage: tr.T("flag.release.target"), Default: "master"},
|
||||
{Name: "target", Usage: tr.T("flag.release.target")},
|
||||
{Name: "prerelease", Usage: tr.T("flag.release.prerelease"), Default: "false"},
|
||||
{Name: "draft", Usage: "Mark as draft (true/false)", Default: "false"},
|
||||
{Name: "attachment-ids", Usage: "Comma-separated attachment IDs"},
|
||||
|
|
|
|||
Loading…
Reference in New Issue