From cdc926ac449674624fa9d60402e020364c50a7b0 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 15:45:10 +0000 Subject: [PATCH 01/12] Add Contributed backport command This PR provides a contributed backport command to help create backports for Gitea. It represents a significant improvement on my previously described shell-script. It can be installed using `go install contrib/backport/backport.go`. Signed-off-by: Andrew Thornton --- CONTRIBUTING.md | 20 +- contrib/backport/README | 41 ++++ contrib/backport/backport.go | 443 +++++++++++++++++++++++++++++++++++ 3 files changed, 486 insertions(+), 18 deletions(-) create mode 100644 contrib/backport/README create mode 100644 contrib/backport/backport.go diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbf2a331dd48..5621ab6e2e35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -267,26 +267,10 @@ with the rest of the summary matching the original PR. Similarly for frontports --- -The below is a script that may be helpful in creating backports. YMMV. +A command to help create backports can be found in `contrib/backport` and can be installed using: ```bash -#!/bin/sh -PR="$1" -SHA="$2" -VERSION="$3" - -if [ -z "$SHA" ]; then - SHA=$(gh api /repos/go-gitea/gitea/pulls/$PR -q '.merge_commit_sha') -fi - -if [ -z "$VERSION" ]; then - VERSION="v1.16" -fi - -echo git checkout origin/release/"$VERSION" -b backport-$PR-$VERSION -git checkout origin/release/"$VERSION" -b backport-$PR-$VERSION -git cherry-pick $SHA && git commit --amend && git push zeripath backport-$PR-$VERSION && xdg-open https://github.com/go-gitea/gitea/compare/release/"$VERSION"...zeripath:backport-$PR-$VERSION - +go install contrib/backport/backport.go ``` ## Developer Certificate of Origin (DCO) diff --git a/contrib/backport/README b/contrib/backport/README new file mode 100644 index 000000000000..9e11249a9dad --- /dev/null +++ b/contrib/backport/README @@ -0,0 +1,41 @@ +`backport` +========== + +`backport` is a command to help create backports of PRs. It backports a +provided PR from main on to a released version. + +It will create a backport branch, cherry-pick the PR's merge commit, adjust +the commit message and then push this back up to your fork's remote. + +The default version will read from `docs/config.yml`. You can override this +using the option `--version`. + +The upstream branches will be fetched, using the remote `origin`. This can +be overrided using `--upstream`, and fetching can be avoided using +`--no-fetch`. + +By default the branch created will be called `backport-$PR-$VERSION`. Yoi +can override this using the option `--backport-branch`. This branch will +be created from `--release-branch` which is `$(UPSTREAM)/release/$(VERSION)` +by default. + +The merge-commit as determined by the github API will be used as the SHA to +cherry-pick. You can override this using `--cherry-pick`. + +The commit will be amended to add the `Backport` header. `--no-amend` can +be set to stop this. + +If cherry-pick is successful the backported branch will be pushed up to your +fork using your remote. These will be determined using `git remote -v`. You +can set your fork name using `--fork-user` and your remote name using +`--remote`. You can avoid pushing using `--no-push`. + +If the push is successful, `xdg-open` will be called to open a backport url. +You can stop this using `--no-xdg-open`. + +Installation +============ + +```bash +go install contrib/backport/backport.go +``` diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go new file mode 100644 index 000000000000..d05f814465b6 --- /dev/null +++ b/contrib/backport/backport.go @@ -0,0 +1,443 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package main + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + "os/exec" + "os/signal" + "path" + "strconv" + "strings" + "syscall" + + "github.com/google/go-github/v45/github" + "github.com/urfave/cli" + "gopkg.in/yaml.v2" +) + +const defaultVersion = "v1.18" + +func main() { + app := cli.NewApp() + app.Name = "backport" + app.Usage = "Backport provided PR-number on to the current or previous released version" + app.Description = `Backport will look-up the PR in Gitea's git log and attempt to cherry-pick it on the current version` + app.ArgsUsage = "" + + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "version", + Usage: "Version branch to backport on to", + }, + cli.StringFlag{ + Name: "upstream", + Value: "origin", + Usage: "Upstream remote for the Gitea upstream", + }, + cli.StringFlag{ + Name: "release-branch", + Value: "", + Usage: "Release branch to backport on. Will default to /release/", + }, + cli.StringFlag{ + Name: "cherry-pick", + Usage: "SHA to cherry-pick as backport", + }, + cli.StringFlag{ + Name: "backport-branch", + Usage: "backport branch to backport on to (default: backport--", + }, + cli.StringFlag{ + Name: "remote", + Value: "", + Usage: "Remote for your fork of the Gitea upstream", + }, + cli.StringFlag{ + Name: "fork-user", + Value: "", + Usage: "Forked user name on Github", + }, + cli.BoolFlag{ + Name: "no-fetch", + Usage: "set this flag to prevent fetch of remote branches", + }, + cli.BoolFlag{ + Name: "no-amend", + Usage: "set this flag to prevent amend of the commit", + }, + cli.BoolFlag{ + Name: "no-push", + Usage: "set this flag to prevent push", + }, + cli.BoolFlag{ + Name: "no-xdg-open", + Usage: "set this flag to prevent xdg-open", + }, + } + cli.AppHelpTemplate = `NAME: + {{.Name}} - {{.Usage}} +USAGE: + {{.HelpName}} {{if .VisibleFlags}}[options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if len .Authors}} +AUTHOR: + {{range .Authors}}{{ . }}{{end}} + {{end}}{{if .Commands}} +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + + app.Action = runBackport + + if err := app.Run(os.Args); err != nil { + fmt.Fprintf(os.Stderr, "Unable to backport: %v\n", err) + } +} + +func runBackport(c *cli.Context) error { + ctx, cancel := installSignals() + defer cancel() + + version := c.String("version") + if version == "" { + version = readVersion() + } + if version == "" { + version = defaultVersion + } + + upstream := c.String("upstream") + if upstream == "" { + upstream = "origin" + } + + forkUser := c.String("fork-user") + remote := c.String("remote") + if remote == "" && !c.Bool("--no-push") { + var err error + remote, forkUser, err = determineRemote(ctx, forkUser) + if err != nil { + return err + } + } + + releaseBranch := c.String("release-branch") + if releaseBranch == "" { + releaseBranch = path.Join(upstream, "release", version) + } + + args := c.Args() + if len(args) == 0 { + return fmt.Errorf("no PR number provided\nProvide a PR number to backport") + } else if len(args) != 1 { + return fmt.Errorf("multiple PRs provided %v\nOnly a single PR can be backported at a time", args) + } + + pr := args[0] + + backportBranch := c.String("backport-branch") + if backportBranch == "" { + backportBranch = "backport-" + pr + "-" + version + } + + fmt.Printf("* Backporting %s to %s as %s\n", pr, releaseBranch, backportBranch) + + sha := c.String("cherry-pick") + if sha == "" { + var err error + sha, err = determineSHAforPR(ctx, pr) + if err != nil { + return err + } + } + if sha == "" { + return fmt.Errorf("unable to determine sha for cherry-pick of %s", pr) + } + + if !c.Bool("no-fetch") { + if err := fetchRemoteAndMain(ctx, upstream, releaseBranch); err != nil { + return err + } + } + + if err := checkoutBackportBranch(ctx, backportBranch, releaseBranch); err != nil { + return err + } + + if err := cherrypick(ctx, sha); err != nil { + return err + } + + if !c.Bool("no-amend") { + if err := amendCommit(ctx, pr); err != nil { + return err + } + } + + if !c.Bool("no-push") { + url := "https://github.com/go-gitea/gitea/compare/" + version + "..." + forkUser + ":" + backportBranch + + if err := gitPushUp(ctx, remote, backportBranch); err != nil { + return err + } + + if !c.Bool("no-xdg-open") { + if err := xdgOpen(ctx, url); err != nil { + return err + } + } else { + fmt.Printf("* Navigate to %s to open PR\n", url) + } + } + return nil +} + +func xdgOpen(ctx context.Context, url string) error { + fmt.Printf("* `xdg-open %s`\n", url) + out, err := exec.CommandContext(ctx, "xdg-open", url).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to xdg-open to %s: %w", url, err) + } + return nil +} + +func gitPushUp(ctx context.Context, remote, backportBranch string) error { + fmt.Printf("* `git push -u %s %s`\n", remote, backportBranch) + out, err := exec.CommandContext(ctx, "git", "push", "-u", remote, backportBranch).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to push up to %s: %w", remote, err) + } + return nil +} + +func amendCommit(ctx context.Context, pr string) error { + fmt.Printf("* Amending commit to prepend `Backport #%s` to body\n", pr) + out, err := exec.CommandContext(ctx, "git", "log", "-1", "--pretty=format:%B").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to get last log message: %w", err) + } + + parts := strings.SplitN(string(out), "\n", 2) + + if len(parts) != 2 { + return fmt.Errorf("unable to interpret log message:\n%s", string(out)) + } + subject, body := parts[0], parts[1] + if !strings.HasSuffix(subject, " (#"+pr+")") { + subject = subject + " (#" + pr + ")" + } + + out, err = exec.CommandContext(ctx, "git", "commit", "--amend", "-m", subject+"\n\nBackport #"+pr+"\n"+body).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to amend last log message: %w", err) + } + return nil +} + +func cherrypick(ctx context.Context, sha string) error { + // Check if a CHERRY_PICK_HEAD exists + _, err := exec.CommandContext(ctx, "git", "rev-list", "-1", "CHERRY_PICK_HEAD").Output() + if err == nil { + // Assume that we are in the middle of cherry-pick - continue it + fmt.Println("* Attempting git cherry-pick --continue") + out, err := exec.CommandContext(ctx, "git", "cherry-pick", "--continue").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "git cherry-pick --continue failed:\n%s\n", string(out)) + return fmt.Errorf("unable to continue cherry-pick: %w", err) + } + return nil + } + + fmt.Printf("* Attempting git cherry-pick %s\n", sha) + out, err := exec.CommandContext(ctx, "git", "cherry-pick", sha).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "git cherry-pick %s failed:\n%s\n", sha, string(out)) + return fmt.Errorf("git cherry-pick %s failed: %w", sha, err) + } + return nil +} + +func checkoutBackportBranch(ctx context.Context, backportBranch, releaseBranch string) error { + cmd := exec.CommandContext(ctx, "git", "branch", "--show-current") + out, err := cmd.Output() + if err != nil { + return fmt.Errorf("unable to check current branch %w", err) + } + + currentBranch := strings.TrimSpace(string(out)) + if currentBranch == backportBranch { + fmt.Printf("* Current branch is %s - not checking out\n", currentBranch) + return nil + } + + cmd = exec.CommandContext(ctx, "git", "rev-list", "-1", backportBranch) + if _, err := cmd.Output(); err == nil { + fmt.Printf("* Branch %s already exists. Checking it out...\n", backportBranch) + cmd = exec.CommandContext(ctx, "git", "checkout", "-f", backportBranch) + return cmd.Run() + } + + fmt.Printf("* `git checkout -b %s %s`\n", backportBranch, releaseBranch) + cmd = exec.CommandContext(ctx, "git", "checkout", "-b", backportBranch, releaseBranch) + return cmd.Run() +} + +func fetchRemoteAndMain(ctx context.Context, remote, releaseBranch string) error { + fmt.Printf("* `git fetch %s main`\n", remote) + out, err := exec.CommandContext(ctx, "git", "fetch", remote, "main").Output() + if err != nil { + fmt.Println(string(out)) + return fmt.Errorf("unable to fetch %s from %s: %w", "main", remote, err) + } + fmt.Println(string(out)) + + remoteBranch := strings.TrimPrefix(releaseBranch, remote+"/") + fmt.Printf("* `git fetch %s %s`\n", remote, remoteBranch) + out, err = exec.CommandContext(ctx, "git", "fetch", remote, remoteBranch).Output() + if err != nil { + fmt.Println(string(out)) + return fmt.Errorf("unable to fetch %s from %s: %w", releaseBranch, remote, err) + } + fmt.Println(string(out)) + + return nil +} + +func determineRemote(ctx context.Context, forkUser string) (string, string, error) { + out, err := exec.CommandContext(ctx, "git", "remote", "-v").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out)) + return "", "", fmt.Errorf("unable to determine forked remote: %w", err) + } + lines := strings.Split(string(out), "\n") + for _, line := range lines { + fields := strings.Split(line, "\t") + name, remote := fields[0], fields[1] + // only look at pushers + if !strings.HasSuffix(remote, " (push)") { + continue + } + // only look at github.com pushes + if !strings.Contains(remote, "github.com") { + continue + } + // ignore go-gitea/gitea + if strings.Contains(remote, "go-gitea/gitea") { + continue + } + if !strings.Contains(remote, forkUser) { + continue + } + if strings.HasPrefix(remote, "git@github.com:") { + forkUser = strings.TrimPrefix(remote, "git@github.com:") + } else if strings.HasPrefix(remote, "https://github.com/") { + forkUser = strings.TrimPrefix(remote, "https://github.com/") + } else if strings.HasPrefix(remote, "https://www.github.com/") { + forkUser = strings.TrimPrefix(remote, "https://www.github.com/") + } else if forkUser == "" { + return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote) + } + idx := strings.Index(forkUser, "/") + if idx >= 0 { + forkUser = forkUser[:idx] + } + return name, forkUser, nil + } + return "", "", fmt.Errorf("unable to find appropriate remote in:\n%s", string(out)) +} + +func readVersion() string { + bs, err := os.ReadFile("docs/config.yaml") + if err != nil { + if err == os.ErrNotExist { + log.Println("`docs/config.yaml` not present") + return "" + } + fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err) + return "" + } + + type params struct { + Version string + } + type docConfig struct { + Params params + } + dc := &docConfig{} + if err := yaml.Unmarshal(bs, dc); err != nil { + fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err) + return "" + } + + if dc.Params.Version == "" { + fmt.Fprintf(os.Stderr, "No version in `docs/config.yaml`") + return "" + } + + version := dc.Params.Version + if version[0] != 'v' { + version = "v" + version + } + + split := strings.SplitN(version, ".", 3) + + return strings.Join(split[:2], ".") +} + +func determineSHAforPR(ctx context.Context, prStr string) (string, error) { + prNum, err := strconv.Atoi(prStr) + if err != nil { + return "", err + } + + client := github.NewClient(http.DefaultClient) + + pr, _, err := client.PullRequests.Get(ctx, "go-gitea", "gitea", prNum) + if err != nil { + return "", err + } + + if pr.Merged == nil || !*pr.Merged { + return "", fmt.Errorf("PR #%d is not yet merged - cannot determine sha to backport", prNum) + } + + if pr.MergeCommitSHA != nil { + return *pr.MergeCommitSHA, nil + } + + return "", nil +} + +func installSignals() (context.Context, context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + // install notify + signalChannel := make(chan os.Signal, 1) + + signal.Notify( + signalChannel, + syscall.SIGINT, + syscall.SIGTERM, + ) + select { + case <-signalChannel: + case <-ctx.Done(): + } + cancel() + signal.Reset() + }() + + return ctx, cancel +} + +// git push zeripath backport-$PR-$VERSION && xdg-open https://github.com/go-gitea/gitea/compare/release/"$VERSION"...zeripath:backport-$PR-$VERSION From c562dca5e2c31cf2315174f66ac0450761e3838a Mon Sep 17 00:00:00 2001 From: zeripath Date: Sat, 28 Jan 2023 15:51:23 +0000 Subject: [PATCH 02/12] Update contrib/backport/README Co-authored-by: Yarden Shoham --- contrib/backport/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/backport/README b/contrib/backport/README index 9e11249a9dad..42de5298ddc2 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -14,7 +14,7 @@ The upstream branches will be fetched, using the remote `origin`. This can be overrided using `--upstream`, and fetching can be avoided using `--no-fetch`. -By default the branch created will be called `backport-$PR-$VERSION`. Yoi +By default the branch created will be called `backport-$PR-$VERSION`. You can override this using the option `--backport-branch`. This branch will be created from `--release-branch` which is `$(UPSTREAM)/release/$(VERSION)` by default. From a3918518fbcf26878956b5d394699216c587cc27 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 16:11:48 +0000 Subject: [PATCH 03/12] fix bug Signed-off-by: Andrew Thornton --- contrib/backport/backport.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index d05f814465b6..3898d6505f55 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -181,7 +181,9 @@ func runBackport(c *cli.Context) error { } if !c.Bool("no-push") { - url := "https://github.com/go-gitea/gitea/compare/" + version + "..." + forkUser + ":" + backportBranch + upstreamReleaseBranch := strings.TrimPrefix(releaseBranch, upstream+"/") + + url := "https://github.com/go-gitea/gitea/compare/release/" + upstreamReleaseBranch + "..." + forkUser + ":" + backportBranch if err := gitPushUp(ctx, remote, backportBranch); err != nil { return err @@ -246,8 +248,7 @@ func amendCommit(ctx context.Context, pr string) error { func cherrypick(ctx context.Context, sha string) error { // Check if a CHERRY_PICK_HEAD exists - _, err := exec.CommandContext(ctx, "git", "rev-list", "-1", "CHERRY_PICK_HEAD").Output() - if err == nil { + if _, err := os.Stat(".git/CHERRY_PICK_HEAD"); err == nil { // Assume that we are in the middle of cherry-pick - continue it fmt.Println("* Attempting git cherry-pick --continue") out, err := exec.CommandContext(ctx, "git", "cherry-pick", "--continue").Output() @@ -268,28 +269,25 @@ func cherrypick(ctx context.Context, sha string) error { } func checkoutBackportBranch(ctx context.Context, backportBranch, releaseBranch string) error { - cmd := exec.CommandContext(ctx, "git", "branch", "--show-current") - out, err := cmd.Output() + out, err := exec.CommandContext(ctx, "git", "branch", "--show-current").Output() if err != nil { return fmt.Errorf("unable to check current branch %w", err) } currentBranch := strings.TrimSpace(string(out)) + fmt.Printf("* Current branch is %s\n", currentBranch) if currentBranch == backportBranch { fmt.Printf("* Current branch is %s - not checking out\n", currentBranch) return nil } - cmd = exec.CommandContext(ctx, "git", "rev-list", "-1", backportBranch) - if _, err := cmd.Output(); err == nil { + if _, err := exec.CommandContext(ctx, "git", "rev-list", "-1", backportBranch).Output(); err == nil { fmt.Printf("* Branch %s already exists. Checking it out...\n", backportBranch) - cmd = exec.CommandContext(ctx, "git", "checkout", "-f", backportBranch) - return cmd.Run() + return exec.CommandContext(ctx, "git", "checkout", "-f", backportBranch).Run() } fmt.Printf("* `git checkout -b %s %s`\n", backportBranch, releaseBranch) - cmd = exec.CommandContext(ctx, "git", "checkout", "-b", backportBranch, releaseBranch) - return cmd.Run() + return exec.CommandContext(ctx, "git", "checkout", "-b", backportBranch, releaseBranch).Run() } func fetchRemoteAndMain(ctx context.Context, remote, releaseBranch string) error { @@ -439,5 +437,3 @@ func installSignals() (context.Context, context.CancelFunc) { return ctx, cancel } - -// git push zeripath backport-$PR-$VERSION && xdg-open https://github.com/go-gitea/gitea/compare/release/"$VERSION"...zeripath:backport-$PR-$VERSION From 76083f37111b1bb8e8e63005b295a47ffe7d4285 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 16:20:04 +0000 Subject: [PATCH 04/12] local-remote releasebranches Signed-off-by: Andrew Thornton --- contrib/backport/backport.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 3898d6505f55..4543c307d5b6 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -43,7 +43,7 @@ func main() { cli.StringFlag{ Name: "release-branch", Value: "", - Usage: "Release branch to backport on. Will default to /release/", + Usage: "Release branch to backport on. Will default to release/", }, cli.StringFlag{ Name: "cherry-pick", @@ -51,7 +51,7 @@ func main() { }, cli.StringFlag{ Name: "backport-branch", - Usage: "backport branch to backport on to (default: backport--", + Usage: "Backport branch to backport on to (default: backport--", }, cli.StringFlag{ Name: "remote", @@ -65,19 +65,19 @@ func main() { }, cli.BoolFlag{ Name: "no-fetch", - Usage: "set this flag to prevent fetch of remote branches", + Usage: "Set this flag to prevent fetch of remote branches", }, cli.BoolFlag{ Name: "no-amend", - Usage: "set this flag to prevent amend of the commit", + Usage: "Set this flag to prevent amend of the commit", }, cli.BoolFlag{ Name: "no-push", - Usage: "set this flag to prevent push", + Usage: "Set this flag to prevent push", }, cli.BoolFlag{ Name: "no-xdg-open", - Usage: "set this flag to prevent xdg-open", + Usage: "Set this flag to prevent xdg-open", }, } cli.AppHelpTemplate = `NAME: @@ -129,9 +129,11 @@ func runBackport(c *cli.Context) error { releaseBranch := c.String("release-branch") if releaseBranch == "" { - releaseBranch = path.Join(upstream, "release", version) + releaseBranch = path.Join("release", version) } + localReleaseBranch := path.Join(upstream, releaseBranch) + args := c.Args() if len(args) == 0 { return fmt.Errorf("no PR number provided\nProvide a PR number to backport") @@ -146,7 +148,7 @@ func runBackport(c *cli.Context) error { backportBranch = "backport-" + pr + "-" + version } - fmt.Printf("* Backporting %s to %s as %s\n", pr, releaseBranch, backportBranch) + fmt.Printf("* Backporting %s to %s as %s\n", pr, localReleaseBranch, backportBranch) sha := c.String("cherry-pick") if sha == "" { @@ -166,7 +168,7 @@ func runBackport(c *cli.Context) error { } } - if err := checkoutBackportBranch(ctx, backportBranch, releaseBranch); err != nil { + if err := checkoutBackportBranch(ctx, backportBranch, localReleaseBranch); err != nil { return err } @@ -181,9 +183,7 @@ func runBackport(c *cli.Context) error { } if !c.Bool("no-push") { - upstreamReleaseBranch := strings.TrimPrefix(releaseBranch, upstream+"/") - - url := "https://github.com/go-gitea/gitea/compare/release/" + upstreamReleaseBranch + "..." + forkUser + ":" + backportBranch + url := "https://github.com/go-gitea/gitea/compare/" + releaseBranch + "..." + forkUser + ":" + backportBranch if err := gitPushUp(ctx, remote, backportBranch); err != nil { return err @@ -299,9 +299,8 @@ func fetchRemoteAndMain(ctx context.Context, remote, releaseBranch string) error } fmt.Println(string(out)) - remoteBranch := strings.TrimPrefix(releaseBranch, remote+"/") - fmt.Printf("* `git fetch %s %s`\n", remote, remoteBranch) - out, err = exec.CommandContext(ctx, "git", "fetch", remote, remoteBranch).Output() + fmt.Printf("* `git fetch %s %s`\n", remote, releaseBranch) + out, err = exec.CommandContext(ctx, "git", "fetch", remote, releaseBranch).Output() if err != nil { fmt.Println(string(out)) return fmt.Errorf("unable to fetch %s from %s: %w", releaseBranch, remote, err) From 279495643e74a87273d05cdc6feccd88fe103923 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 16:21:23 +0000 Subject: [PATCH 05/12] clarify variable names Signed-off-by: Andrew Thornton --- contrib/backport/backport.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 4543c307d5b6..701b499fb483 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -127,12 +127,12 @@ func runBackport(c *cli.Context) error { } } - releaseBranch := c.String("release-branch") - if releaseBranch == "" { - releaseBranch = path.Join("release", version) + upstreamReleaseBranch := c.String("release-branch") + if upstreamReleaseBranch == "" { + upstreamReleaseBranch = path.Join("release", version) } - localReleaseBranch := path.Join(upstream, releaseBranch) + localReleaseBranch := path.Join(upstream, upstreamReleaseBranch) args := c.Args() if len(args) == 0 { @@ -163,7 +163,7 @@ func runBackport(c *cli.Context) error { } if !c.Bool("no-fetch") { - if err := fetchRemoteAndMain(ctx, upstream, releaseBranch); err != nil { + if err := fetchRemoteAndMain(ctx, upstream, upstreamReleaseBranch); err != nil { return err } } @@ -183,7 +183,7 @@ func runBackport(c *cli.Context) error { } if !c.Bool("no-push") { - url := "https://github.com/go-gitea/gitea/compare/" + releaseBranch + "..." + forkUser + ":" + backportBranch + url := "https://github.com/go-gitea/gitea/compare/" + upstreamReleaseBranch + "..." + forkUser + ":" + backportBranch if err := gitPushUp(ctx, remote, backportBranch); err != nil { return err From 800c1e0787e09a6576cd570308f9b2ddeec7cd14 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 17:57:44 +0000 Subject: [PATCH 06/12] use-yaml.v3 Signed-off-by: Andrew Thornton --- contrib/backport/backport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 701b499fb483..f8215a89f6bc 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -18,7 +18,7 @@ import ( "github.com/google/go-github/v45/github" "github.com/urfave/cli" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) const defaultVersion = "v1.18" From f58b9b994d4f5ed6e76972b315beea994fbe6978 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 18:05:12 +0000 Subject: [PATCH 07/12] minor adjustments Signed-off-by: Andrew Thornton --- contrib/backport/backport.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index f8215a89f6bc..9a89f7ab8196 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -21,7 +21,7 @@ import ( "gopkg.in/yaml.v3" ) -const defaultVersion = "v1.18" +const defaultVersion = "v1.18" // to backport to func main() { app := cli.NewApp() @@ -69,7 +69,7 @@ func main() { }, cli.BoolFlag{ Name: "no-amend", - Usage: "Set this flag to prevent amend of the commit", + Usage: "Set this flag to prevent automatic amendment of the commit message", }, cli.BoolFlag{ Name: "no-push", From 99d6bc0fee33deb9e3cf03bb5b4eeb46758f3c43 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 18:07:27 +0000 Subject: [PATCH 08/12] more minor changes Signed-off-by: Andrew Thornton --- CONTRIBUTING.md | 2 +- contrib/backport/backport.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5621ab6e2e35..7a23448e0ab5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -267,7 +267,7 @@ with the rest of the summary matching the original PR. Similarly for frontports --- -A command to help create backports can be found in `contrib/backport` and can be installed using: +A command to help create backports can be found in `contrib/backport` and can be installed (from inside the gitea repo root directory) using: ```bash go install contrib/backport/backport.go diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 9a89f7ab8196..060876c46dae 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -73,11 +73,11 @@ func main() { }, cli.BoolFlag{ Name: "no-push", - Usage: "Set this flag to prevent push", + Usage: "Set this flag to prevent pushing the backport up to your fork", }, cli.BoolFlag{ Name: "no-xdg-open", - Usage: "Set this flag to prevent xdg-open", + Usage: "Set this flag to not use xdg-open to open the PR URL", }, } cli.AppHelpTemplate = `NAME: From e03872b714d74ae73db8bac56069ce2833f67464 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 18:10:47 +0000 Subject: [PATCH 09/12] clarify release branch Signed-off-by: Andrew Thornton --- contrib/backport/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/backport/README b/contrib/backport/README index 42de5298ddc2..d432e90bf788 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -16,8 +16,8 @@ be overrided using `--upstream`, and fetching can be avoided using By default the branch created will be called `backport-$PR-$VERSION`. You can override this using the option `--backport-branch`. This branch will -be created from `--release-branch` which is `$(UPSTREAM)/release/$(VERSION)` -by default. +be created from `--release-branch` which is `release/$(VERSION)` +by default which will be pulled from `$(UPSTREAM)`. The merge-commit as determined by the github API will be used as the SHA to cherry-pick. You can override this using `--cherry-pick`. From 1800dacdab3e417d4665fec7a1d1cf827f5719b0 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 18:17:34 +0000 Subject: [PATCH 10/12] more readme changes Signed-off-by: Andrew Thornton --- contrib/backport/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/backport/README b/contrib/backport/README index d432e90bf788..e7b3841ddd87 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -17,13 +17,13 @@ be overrided using `--upstream`, and fetching can be avoided using By default the branch created will be called `backport-$PR-$VERSION`. You can override this using the option `--backport-branch`. This branch will be created from `--release-branch` which is `release/$(VERSION)` -by default which will be pulled from `$(UPSTREAM)`. +by default and will be pulled from `$(UPSTREAM)`. The merge-commit as determined by the github API will be used as the SHA to cherry-pick. You can override this using `--cherry-pick`. -The commit will be amended to add the `Backport` header. `--no-amend` can -be set to stop this. +The commit meesage will be amended to add the `Backport` header. `--no-amend` +can be set to stop this from happening. If cherry-pick is successful the backported branch will be pushed up to your fork using your remote. These will be determined using `git remote -v`. You From f4bd4ba71cbffa02ddfa96b9b40f28ca7715e3a9 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 28 Jan 2023 18:23:50 +0000 Subject: [PATCH 11/12] no-amend-message instead Signed-off-by: Andrew Thornton --- contrib/backport/README | 4 ++-- contrib/backport/backport.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/backport/README b/contrib/backport/README index e7b3841ddd87..8fb62d19f422 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -22,8 +22,8 @@ by default and will be pulled from `$(UPSTREAM)`. The merge-commit as determined by the github API will be used as the SHA to cherry-pick. You can override this using `--cherry-pick`. -The commit meesage will be amended to add the `Backport` header. `--no-amend` -can be set to stop this from happening. +The commit meesage will be amended to add the `Backport` header. +`--no-amend-message` can be set to stop this from happening. If cherry-pick is successful the backported branch will be pushed up to your fork using your remote. These will be determined using `git remote -v`. You diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 060876c46dae..c35bf9e30f67 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -68,7 +68,7 @@ func main() { Usage: "Set this flag to prevent fetch of remote branches", }, cli.BoolFlag{ - Name: "no-amend", + Name: "no-amend-message", Usage: "Set this flag to prevent automatic amendment of the commit message", }, cli.BoolFlag{ @@ -176,7 +176,7 @@ func runBackport(c *cli.Context) error { return err } - if !c.Bool("no-amend") { + if !c.Bool("no-amend-message") { if err := amendCommit(ctx, pr); err != nil { return err } From 26f77482e3d9739749521dbecba227a1c05174f7 Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 31 Jan 2023 20:22:59 +0000 Subject: [PATCH 12/12] Update contrib/backport/README --- contrib/backport/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/backport/README b/contrib/backport/README index 8fb62d19f422..1e84c1bb9743 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -22,7 +22,7 @@ by default and will be pulled from `$(UPSTREAM)`. The merge-commit as determined by the github API will be used as the SHA to cherry-pick. You can override this using `--cherry-pick`. -The commit meesage will be amended to add the `Backport` header. +The commit message will be amended to add the `Backport` header. `--no-amend-message` can be set to stop this from happening. If cherry-pick is successful the backported branch will be pushed up to your