From 86ce1bed45aeedb3934e4c42f2616736d2e28dbc Mon Sep 17 00:00:00 2001 From: jolheiser Date: Tue, 30 Aug 2022 13:58:49 -0500 Subject: [PATCH] Add backport open list, change args to flags for back/frontport Signed-off-by: jolheiser --- cmd/backport.go | 36 ++++++++++++++++++++++++++---------- cmd/branch.go | 22 ++++++++++++---------- cmd/cmd.go | 26 ++++++++++++++++++++++++++ cmd/frontport.go | 29 +++++++++++++++++------------ go.mod | 1 + go.sum | 2 ++ 6 files changed, 84 insertions(+), 32 deletions(-) diff --git a/cmd/backport.go b/cmd/backport.go index 7314fc6..e97b8ce 100644 --- a/cmd/backport.go +++ b/cmd/backport.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "errors" "flag" "fmt" "strings" @@ -13,18 +12,30 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" "github.com/peterbourgon/ff/v3/ffcli" "github.com/rs/zerolog/log" + "github.com/skratchdot/open-golang/open" ) var ( - backportFS = flag.NewFlagSet("backport", flag.ContinueOnError) - Backport = &ffcli.Command{ + backportFS = flag.NewFlagSet("backport", flag.ContinueOnError) + backportFromFlag = backportFS.String("from", "", "Release to backport from (ex: `main`, default: main)") + backportToFlag = backportFS.String("to", "", "Release to backport to (ex: `1.17`, default: )") + backportListFlag = backportFS.Bool("list", false, "Open repository to see needed backports") + Backport = &ffcli.Command{ Name: "backport", FlagSet: backportFS, - ShortUsage: "backport ", + ShortUsage: "backport --from [release=main] --to [release=latest]", ShortHelp: "backport cherry-picks a and applies it to a clean branch based on ", - Exec: func(ctx context.Context, args []string) error { - if len(args) < 1 { - return errors.New("backport requires one argument") + Exec: func(ctx context.Context, _ []string) error { + to := *backportToFlag + if to == "" { + to = latestRelease() + } + + if *backportListFlag { + if err := open.Run(fmt.Sprintf("https://github.com/go-gitea/gitea/pulls?q=is%%3Apr+-label%%3Abackport%%2Fdone+label%%3Abackport%%2Fv1.%s+is%%3Amerged", to)); err != nil { + return err + } + return nil } fetch(ctx) @@ -33,8 +44,13 @@ var ( log.Fatal().Msg("working tree is dirty") } + from := *backportFromFlag + if from == "" { + from = "main" + } + commits, err := repo().Log(&git.LogOptions{ - From: head("main"), + From: head(from), }) if err != nil { return err @@ -61,8 +77,8 @@ var ( hash := optMap[resp] branch := fmt.Sprintf("backport-%s", hash) - base := fmt.Sprintf("upstream/release/v%s", args[0]) - if err := Branch.ParseAndRun(ctx, []string{branch, base}); err != nil { + base := fmt.Sprintf("upstream/release/v1.%s", to) + if err := Branch.ParseAndRun(ctx, []string{"--base", base, branch}); err != nil { return err } diff --git a/cmd/branch.go b/cmd/branch.go index 773273b..655e812 100644 --- a/cmd/branch.go +++ b/cmd/branch.go @@ -10,28 +10,30 @@ import ( ) var ( - branchFS = flag.NewFlagSet("branch", flag.ContinueOnError) - branchNoFetch = branchFS.Bool("no-fetch", false, "Skip fetching") - Branch = &ffcli.Command{ + branchFS = flag.NewFlagSet("branch", flag.ContinueOnError) + branchNoFetchFlag = branchFS.Bool("no-fetch", false, "Skip fetching") + branchBaseFlag = branchFS.String("base", "main", "Ref to base from") + Branch = &ffcli.Command{ Name: "branch", FlagSet: branchFS, - ShortUsage: "branch [base=main]", - ShortHelp: "branch creates a new branch called based on [base]", + ShortUsage: "branch --base [ref=main] ", + ShortHelp: "branch creates a new branch called based on ", Exec: func(ctx context.Context, args []string) error { if len(args) < 1 { - return errors.New("branch requires at least one argument") + return errors.New("branch requires one argument") } - name, base := args[0], "upstream/main" - if len(args) > 1 { - base = args[1] + name := args[0] + base := *branchBaseFlag + if base == "" { + base = "upstream/main" } if !isClean() { log.Fatal().Msg("working tree is dirty") } - if !*branchNoFetch { + if !*branchNoFetchFlag { fetch(ctx) } diff --git a/cmd/cmd.go b/cmd/cmd.go index bed8f6d..2d34eeb 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -4,6 +4,8 @@ import ( "context" "os" "os/exec" + "regexp" + "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -58,3 +60,27 @@ func head(name string) plumbing.Hash { } return ref.Hash() } + +var releaseRe = regexp.MustCompile(`release/v1\.(\d+)`) + +func latestRelease() string { + cmd := exec.Command("git", "ls-remote", "upstream", "release/*") + out, err := cmd.Output() + if err != nil { + log.Fatal().Err(err).Msg("could not get latest release") + } + matches := releaseRe.FindAllStringSubmatch(string(out), -1) + + var latest string + for _, match := range matches { + m := match[1] + if len(m) < 3 { + m = strings.Repeat("0", 3-len(m)) + m + } + if m > latest { + latest = m + } + } + + return strings.TrimLeft(latest, "0") +} diff --git a/cmd/frontport.go b/cmd/frontport.go index 48f2c4c..557e3f8 100644 --- a/cmd/frontport.go +++ b/cmd/frontport.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "errors" "flag" "fmt" "strings" @@ -16,19 +15,21 @@ import ( ) var ( - frontportFS = flag.NewFlagSet("frontport", flag.ContinueOnError) - Frontport = &ffcli.Command{ + frontportFS = flag.NewFlagSet("frontport", flag.ContinueOnError) + frontportFromFlag = frontportFS.String("from", "", "Release to frontport from (ex: `1.17`, default: )") + frontportToFlag = frontportFS.String("to", "", "Release to frontport to (ex: `main`, default: `main`)") + Frontport = &ffcli.Command{ Name: "frontport", FlagSet: frontportFS, - ShortUsage: "frontport [release=main]", + ShortUsage: "frontport --from [release=latest] --to [release=main]", ShortHelp: "frontport cherry-picks a and applies it to a clean branch based on ", - Exec: func(ctx context.Context, args []string) error { - if len(args) < 1 { - return errors.New("frontport requires at least one argument") + Exec: func(ctx context.Context, _ []string) error { + from := *frontportFromFlag + if from == "" { + from = latestRelease() } - from := args[0] if !strings.HasPrefix(from, "release") { - from = fmt.Sprintf("release/v%s", args[0]) + from = fmt.Sprintf("release/v%s", from) } fetch(ctx) @@ -65,9 +66,13 @@ var ( hash := optMap[resp] branch := fmt.Sprintf("frontport-%s", hash) - base := "upstream/main" - if len(args) > 1 { - base = fmt.Sprintf("upstream/release/v%s", args[1]) + + base := *frontportToFlag + if base == "" { + base = "upstream/main" + } + if !strings.HasPrefix(base, "upstream") { + base = fmt.Sprintf("upstream/release/v1.%s", base) } if err := Branch.ParseAndRun(ctx, []string{branch, base}); err != nil { return err diff --git a/go.mod b/go.mod index e6837a1..b188058 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-git/go-git/v5 v5.4.2 github.com/peterbourgon/ff/v3 v3.3.0 github.com/rs/zerolog v1.27.0 + github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 ) require ( diff --git a/go.sum b/go.sum index 3be4c49..465340f 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Q github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=