From cb638062625d9bc3eee12515067fb09e05a08414 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sat, 3 Jul 2021 02:36:15 +0100 Subject: [PATCH] feat(release): add bulk edit command to quickly change multiple GitHub releases --- pkg/cli/release.go | 55 +++++++++++++++++++++++++++++ pkg/release/bulk.go | 84 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 pkg/release/bulk.go diff --git a/pkg/cli/release.go b/pkg/cli/release.go index 7b01074..f73c6b5 100644 --- a/pkg/cli/release.go +++ b/pkg/cli/release.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "os" "path/filepath" @@ -60,6 +61,7 @@ func releaseCmd() *cli2.Command { Subcommands: []*cli2.Command{ releaseCheckCmd(), releasePublishCmd(), + releaseBulkCmd(), }, } } @@ -206,3 +208,56 @@ func releasePublishAction( return release.Publish(c.Context, rlsOpts) } + +func releaseBulkCmd() *cli2.Command { + return &cli2.Command{ + Name: "bulk", + Usage: "bulk modify GitHub releases", + ArgsUsage: "", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "name", + Usage: "regexp pattern matching release names to modify", + }, + &cli2.StringFlag{ + Name: "prerelease", + Usage: "change prerelease flag, must be \"true\" or " + + "\"false\", otherwise prerelease value is not changed", + }, + &cli2.BoolFlag{ + Name: "dry-run", + Usage: "do not perform any changes", + }, + }, + Action: releaseActionWrapper(releaseBulkAction), + } +} + +func releaseBulkAction( + c *cli2.Context, + opts *Options, + rOpts *releaseOptions, +) error { + bulkOpts := &release.BulkOptions{ + Repository: rOpts.Repository, + NamePattern: c.String("name"), + DryRun: c.Bool("dry-run"), + GithubToken: rOpts.GithubToken, + } + + switch c.String("prerelease") { + case "true": + v := true + bulkOpts.Prerelease = &v + case "false": + v := false + bulkOpts.Prerelease = &v + case "": + default: + return errors.New( + "--prerelease by me \"true\" or \"false\" when specified", + ) + } + + return release.Bulk(c.Context, bulkOpts) +} diff --git a/pkg/release/bulk.go b/pkg/release/bulk.go new file mode 100644 index 0000000..4a7150c --- /dev/null +++ b/pkg/release/bulk.go @@ -0,0 +1,84 @@ +package release + +import ( + "context" + "regexp" + + "github.com/google/go-github/v35/github" + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/gh" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" +) + +type BulkOptions struct { + Repository *repository.Repository + NamePattern string + Prerelease *bool + DryRun bool + GithubToken string +} + +func Bulk(ctx context.Context, opts *BulkOptions) error { + logger := hclog.FromContext(ctx).Named("release") + gh := gh.New(ctx, opts.GithubToken) + + nameMatcher, err := regexp.Compile(opts.NamePattern) + if err != nil { + return err + } + + nextPage := 1 + lastPage := 1 + + for nextPage <= lastPage { + releases, resp, err := gh.Repositories.ListReleases( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + &github.ListOptions{ + Page: nextPage, + PerPage: 100, + }, + ) + if err != nil { + return err + } + + nextPage = resp.NextPage + lastPage = resp.LastPage + + for _, r := range releases { + if !nameMatcher.MatchString(r.GetName()) { + continue + } + + logger.Info("match found", "release", r.GetName()) + + var changes []interface{} + if opts.Prerelease != nil && r.GetPrerelease() != *opts.Prerelease { + changes = append(changes, "prerelease", *opts.Prerelease) + r.Prerelease = opts.Prerelease + } + + if len(changes) > 0 { + changes = append( + []interface{}{"release", r.GetName()}, changes..., + ) + logger.Info("modifying", changes...) + if !opts.DryRun { + r, _, err = gh.Repositories.EditRelease( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + r.GetID(), r, + ) + if err != nil { + return err + } + } + } + } + + if nextPage == 0 || lastPage == 0 { + break + } + } + + return nil +}