From f229c200e8ed04fe510cbc6e324d951ec458f205 Mon Sep 17 00:00:00 2001 From: Peter Matseykanets Date: Fri, 10 Sep 2021 22:16:42 -0400 Subject: [PATCH] Release 0.7.0 (#19) - Add new flag no-repo to all tools - Fix an issue with the use of an unbuffered channel in `signal.Notify` call - Run builds with Go 1.17 in CI --- .github/workflows/build.yml | 4 +-- cmd/gh-find/README.md | 1 + cmd/gh-find/main.go | 32 +++++++++++------ cmd/gh-go-rdeps/README.md | 1 + cmd/gh-go-rdeps/main.go | 26 +++++++++----- cmd/gh-pr/README.md | 1 + cmd/gh-pr/main.go | 60 +++++++++++++++++++------------- cmd/gh-purge-artifacts/README.md | 1 + cmd/gh-purge-artifacts/main.go | 21 +++++++---- github/repo.go | 19 ++++++---- terminal/terminal.go | 15 ++++---- version/version.go | 2 +- 12 files changed, 115 insertions(+), 68 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf34813..3b063ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ jobs: name: "Build ${{ matrix.go }}" strategy: matrix: - go: ["1.15", "1.16"] + go: ["1.15", "1.16", "1.17"] runs-on: ubuntu-latest env: GO111MODULE: on @@ -40,7 +40,7 @@ jobs: run: go test -vet=off -race -coverprofile=coverage.txt -covermode=atomic ./... - name: Upload code coverage - if: matrix.go == '1.15' + if: matrix.go == '1.16' timeout-minutes: 1 continue-on-error: true run: bash <(curl -s https://codecov.io/bash) diff --git a/cmd/gh-find/README.md b/cmd/gh-find/README.md index 4a1f1df..a329ac3 100644 --- a/cmd/gh-find/README.md +++ b/cmd/gh-find/README.md @@ -41,6 +41,7 @@ Flags: -no-private Don't include private repositories -no-public Don't include public repositories -path= The pattern to match the pathname + -no-repo= The pattern to reject repository names -repo= The pattern to match repository names -size= Limit results based on the file size [+-] -token Prompt for an Access Token diff --git a/cmd/gh-find/main.go b/cmd/gh-find/main.go index b9d3eb4..56ddd21 100644 --- a/cmd/gh-find/main.go +++ b/cmd/gh-find/main.go @@ -51,6 +51,7 @@ Flags: -no-path= The pattern to reject the pathname -no-private Don't include private repositories -no-public Don't include public repositories + -no-repo= The pattern to reject repository names -path= The pattern to match the pathname -repo= The pattern to match repository names -size= Limit results based on the file size [+-] @@ -115,6 +116,7 @@ type config struct { noPrivate bool // Don't include private repositories. noPublic bool // Don't include public repositories. noFork bool // Don't include fork repositories. + noRepoRegexp *regexp.Regexp // The pattern to reject repository names. } type finder struct { @@ -147,10 +149,10 @@ func readConfig() (config, error) { config := config{} var ( - showVersion, showHelp bool - grep, noGrep, repo, fsize string - name, path, noName, noPath stringList - err error + showVersion, showHelp bool + grep, noGrep, repo, noRepo, fsize string + name, path, noName, noPath stringList + err error ) flag.BoolVar(&config.archived, "archived", config.archived, "Include archived repositories") flag.StringVar(&config.branch, "branch", "", "The branch name if different from the default") @@ -170,6 +172,7 @@ func readConfig() (config, error) { flag.Var(&noPath, "no-path", "The pattern to reject the pathname") flag.BoolVar(&config.noPrivate, "no-private", config.noPrivate, "Don't include private repositories") flag.BoolVar(&config.noPublic, "no-public", config.noPublic, "Don't include public repositories") + flag.StringVar(&noRepo, "no-repo", "", "The pattern to reject repository names") flag.Var(&path, "path", "The pattern to match the pathname") flag.StringVar(&repo, "repo", "", "The pattern to match repository names") flag.StringVar(&fsize, "size", "", "Limit results based on the file size [+-]") @@ -241,6 +244,12 @@ func readConfig() (config, error) { } } + if noRepo != "" { + if config.noRepoRegexp, err = regexp.Compile(noRepo); err != nil { + return config, fmt.Errorf("invalid no-repo pattern: %s", err) + } + } + switch t := config.ftype; t { case "", typeFile, typeDir: // Empty or valid. default: @@ -344,13 +353,14 @@ func run(ctx context.Context) error { func (f *finder) find(ctx context.Context) error { repos, err := gh.NewRepoFinder(f.gh).Find(ctx, gh.RepoFilter{ - Owner: f.config.owner, - Repo: f.config.repo, - RepoRegexp: f.config.repoRegexp, - Archived: f.config.archived, - NoPrivate: f.config.noPrivate, - NoPublic: f.config.noPublic, - NoFork: f.config.noFork, + Owner: f.config.owner, + Repo: f.config.repo, + RepoRegexp: f.config.repoRegexp, + Archived: f.config.archived, + NoPrivate: f.config.noPrivate, + NoPublic: f.config.noPublic, + NoFork: f.config.noFork, + NoRepoRegexp: f.config.noRepoRegexp, }) if err != nil { return err diff --git a/cmd/gh-go-rdeps/README.md b/cmd/gh-go-rdeps/README.md index e2465c4..3ff79c0 100644 --- a/cmd/gh-go-rdeps/README.md +++ b/cmd/gh-go-rdeps/README.md @@ -18,6 +18,7 @@ Usage: gh-go-rdeps [flags] Flags: -help Print this information and exit + -no-repo= The pattern to reject repository names -repo The pattern to match repository names -token Prompt for an Access Token -version Print the version and exit diff --git a/cmd/gh-go-rdeps/main.go b/cmd/gh-go-rdeps/main.go index 9873a52..6492d3f 100644 --- a/cmd/gh-go-rdeps/main.go +++ b/cmd/gh-go-rdeps/main.go @@ -30,7 +30,8 @@ Usage: gh-go-rdeps [flags] Flags: -help Print this information and exit - -repo The pattern to match repository names + -no-repo= The pattern to reject repository names + -repo= The pattern to match repository names -token Prompt for an Access Token -version Print the version and exit ` @@ -45,10 +46,11 @@ func main() { } type config struct { - owner string - modpath string - repoRegexp *regexp.Regexp - token bool // Propmt for an access token. + owner string + modpath string + repoRegexp *regexp.Regexp + token bool // Propmt for an access token. + noRepoRegexp *regexp.Regexp // The pattern to reject repository names. } type finder struct { @@ -68,11 +70,12 @@ func readConfig() (config, error) { var ( showVersion, showHelp bool - repo string + repo, noRepo string err error ) flag.BoolVar(&showHelp, "help", showHelp, "Print this information and exit") + flag.StringVar(&noRepo, "no-repo", "", "The pattern to reject repository names") flag.StringVar(&repo, "repo", "", "The pattern to match repository names") flag.BoolVar(&config.token, "token", config.token, "Prompt for Access Token") flag.BoolVar(&showVersion, "version", showVersion, "Print version and exit") @@ -112,6 +115,12 @@ func readConfig() (config, error) { } } + if noRepo != "" { + if config.noRepoRegexp, err = regexp.Compile(noRepo); err != nil { + return config, fmt.Errorf("invalid no-repo pattern: %s", err) + } + } + return config, nil } @@ -146,8 +155,9 @@ func run(ctx context.Context) error { func (f *finder) find(ctx context.Context) error { repos, err := gh.NewRepoFinder(f.gh).Find(ctx, gh.RepoFilter{ - Owner: f.config.owner, - RepoRegexp: f.config.repoRegexp, + Owner: f.config.owner, + RepoRegexp: f.config.repoRegexp, + NoRepoRegexp: f.config.noRepoRegexp, }) if err != nil { return err diff --git a/cmd/gh-pr/README.md b/cmd/gh-pr/README.md index 388f2c2..f14f16d 100644 --- a/cmd/gh-pr/README.md +++ b/cmd/gh-pr/README.md @@ -24,6 +24,7 @@ Flags: -no-fork Don't include fork repositories -no-private Don't include private repositories -no-public Don't include public repositories + -no-repo= The pattern to reject repository names -repo= The pattern to match repository names -review= The GitHub user login to request the PR review from -script= The script to apply changes diff --git a/cmd/gh-pr/main.go b/cmd/gh-pr/main.go index e4199c0..409d26b 100644 --- a/cmd/gh-pr/main.go +++ b/cmd/gh-pr/main.go @@ -38,6 +38,7 @@ Flags: -no-fork Don't include fork repositories -no-private Don't include private repositories -no-public Don't include public repositories + -no-repo= The pattern to reject repository names -repo= The pattern to match repository names -review= The GitHub user login to request the PR review from -script= The script to apply changes @@ -59,20 +60,21 @@ func main() { } type config struct { - owner string - repo string - repoRegexp *regexp.Regexp // The pattern to match respository names. - branch string // The branch name if different from the default. - desc string // The PR description. - reviewers []string // The GitHub user login to request the PR review from. - assignees []string // The GitHub user login to assign the PR to. - script string // The body of the script. - shell string // The shell to use to run the script. - title string // The PR title. - token bool // Propmt for an access token. - noPrivate bool // Don't include private repositories. - noPublic bool // Don't include public repositories. - noFork bool // Don't include fork repositories. + owner string + repo string + repoRegexp *regexp.Regexp // The pattern to match respository names. + branch string // The branch name if different from the default. + desc string // The PR description. + reviewers []string // The GitHub user login to request the PR review from. + assignees []string // The GitHub user login to assign the PR to. + script string // The body of the script. + shell string // The shell to use to run the script. + title string // The PR title. + token bool // Propmt for an access token. + noPrivate bool // Don't include private repositories. + noPublic bool // Don't include public repositories. + noFork bool // Don't include fork repositories. + noRepoRegexp *regexp.Regexp // The pattern to reject repository names. } type prmaker struct { @@ -108,10 +110,10 @@ func readConfig() (config, error) { } var ( - showVersion, showHelp bool - repo, scriptFile string - review, assign stringList - err error + showVersion, showHelp bool + repo, noRepo, scriptFile string + review, assign stringList + err error ) flag.Var(&assign, "assign", "The GitHub user login to assign the PR to") flag.StringVar(&config.branch, "branch", "", "The PR branch name") @@ -120,6 +122,7 @@ func readConfig() (config, error) { flag.BoolVar(&config.noFork, "no-fork", config.noFork, "Don't include fork repositories") flag.BoolVar(&config.noPrivate, "no-private", config.noPrivate, "Don't include private repositories") flag.BoolVar(&config.noPublic, "no-public", config.noPublic, "Don't include public repositories") + flag.StringVar(&noRepo, "no-repo", "", "The pattern to reject repository names") flag.StringVar(&repo, "repo", "", "The pattern to match repository names") flag.Var(&review, "review", "The GitHub user login to request the PR review from") flag.StringVar(&config.script, "script", "", "The script to apply PR changes") @@ -220,6 +223,12 @@ func readConfig() (config, error) { } } + if noRepo != "" { + if config.noRepoRegexp, err = regexp.Compile(noRepo); err != nil { + return config, fmt.Errorf("invalid no-repo pattern: %s", err) + } + } + return config, nil } @@ -266,13 +275,14 @@ func (p *prmaker) create(ctx context.Context) error { }() repos, err := gh.NewRepoFinder(p.gh).Find(ctx, gh.RepoFilter{ - Owner: p.config.owner, - Repo: p.config.repo, - RepoRegexp: p.config.repoRegexp, - Archived: false, - NoPrivate: p.config.noPrivate, - NoPublic: p.config.noPublic, - NoFork: p.config.noFork, + Owner: p.config.owner, + Repo: p.config.repo, + RepoRegexp: p.config.repoRegexp, + Archived: false, + NoPrivate: p.config.noPrivate, + NoPublic: p.config.noPublic, + NoFork: p.config.noFork, + NoRepoRegexp: p.config.noRepoRegexp, }) if err != nil { return err diff --git a/cmd/gh-purge-artifacts/README.md b/cmd/gh-purge-artifacts/README.md index b292d11..2b1859b 100644 --- a/cmd/gh-purge-artifacts/README.md +++ b/cmd/gh-purge-artifacts/README.md @@ -19,6 +19,7 @@ Usage: gh-purge-artifacts [flags] [owner][/repo] Flags: -help Print this information and exit -dry-run Dry run + -no-repo= The pattern to reject repository names -repo The pattern to match repository names -token Prompt for an Access Token -version Print the version and exit diff --git a/cmd/gh-purge-artifacts/main.go b/cmd/gh-purge-artifacts/main.go index 1c7cf3b..a14f553 100644 --- a/cmd/gh-purge-artifacts/main.go +++ b/cmd/gh-purge-artifacts/main.go @@ -28,6 +28,7 @@ Usage: gh-purge-artifacts [flags] [owner][/repo] Flags: -help Print this information and exit -dry-run Dry run + -no-repo= The pattern to reject repository names -repo= The pattern to match repository names -token Prompt for an Access Token -version Print the version and exit @@ -43,11 +44,12 @@ func main() { } type config struct { - owner string - repo string - repoRegexp *regexp.Regexp - dryRun bool - token bool // Propmt for an access token. + owner string + repo string + repoRegexp *regexp.Regexp + dryRun bool + token bool // Propmt for an access token. + noRepoRegexp *regexp.Regexp // The pattern to reject repository names. } type purger struct { @@ -67,11 +69,12 @@ func readConfig() (config, error) { var ( showVersion, showHelp bool - repo string + repo, noRepo string err error ) flag.BoolVar(&config.dryRun, "dry-run", config.dryRun, "Dry run") flag.BoolVar(&showHelp, "help", showHelp, "Print this information and exit") + flag.StringVar(&noRepo, "no-repo", "", "The pattern to reject repository names") flag.StringVar(&repo, "repo", "", "The pattern to match repository names") flag.BoolVar(&config.token, "token", config.token, "Prompt for Access Token") flag.BoolVar(&showVersion, "version", showVersion, "Print version and exit") @@ -111,6 +114,12 @@ func readConfig() (config, error) { } } + if noRepo != "" { + if config.noRepoRegexp, err = regexp.Compile(noRepo); err != nil { + return config, fmt.Errorf("invalid no-repo pattern: %s", err) + } + } + return config, nil } diff --git a/github/repo.go b/github/repo.go index 67df7fb..248ccbe 100644 --- a/github/repo.go +++ b/github/repo.go @@ -20,13 +20,14 @@ func NewRepoFinder(client *github.Client) *RepoFinder { // RepoFilter represents criteria used to filter repositories. type RepoFilter struct { - Owner string // The owner name. Can be a user or an organization. - Repo string // The repository name when in single-repo mode. - RepoRegexp *regexp.Regexp // The pattern to match repository names. - Archived bool // Include archived repositories. - NoPrivate bool // Don't inlucde private repositories. - NoPublic bool // Don't include public repositories. - NoFork bool // Don't include forks. + Owner string // The owner name. Can be a user or an organization. + Repo string // The repository name when in single-repo mode. + RepoRegexp *regexp.Regexp // The pattern to match repository names. + Archived bool // Include archived repositories. + NoPrivate bool // Don't inlucde private repositories. + NoPublic bool // Don't include public repositories. + NoFork bool // Don't include forks. + NoRepoRegexp *regexp.Regexp // The pattern to reject repository names. } // Find repositories using a given filter. @@ -143,6 +144,10 @@ func apply(repos []*github.Repository, filter RepoFilter) []*github.Repository { continue } + if filter.NoRepoRegexp != nil && filter.NoRepoRegexp.MatchString(repo.GetName()) { + continue + } + filtered[n] = repo n++ } diff --git a/terminal/terminal.go b/terminal/terminal.go index 240296b..4768ebf 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -21,16 +21,16 @@ func PasswordPrompt(prompt ...string) (string, error) { // Restore the state in the event of an interrupt. // See: https://groups.google.com/forum/#!topic/golang-nuts/kTVAbtee9UA - c := make(chan os.Signal) - q := make(chan struct{}) - signal.Notify(c, os.Interrupt, os.Interrupt, syscall.SIGTERM) + sig := make(chan os.Signal, 1) + quit := make(chan struct{}) + signal.Notify(sig, os.Interrupt, syscall.SIGTERM) go func() { select { - case <-c: + case <-sig: _ = terminal.Restore(syscall.Stdin, state) fmt.Println() os.Exit(1) - case <-q: + case <-quit: return } }() @@ -47,9 +47,8 @@ func PasswordPrompt(prompt ...string) (string, error) { return "", err } - // Stop looking for ^C on the channel. - signal.Stop(c) - close(q) + signal.Stop(sig) + close(quit) // Return the password as a string. return string(password), nil diff --git a/version/version.go b/version/version.go index f9dce07..3b048ef 100644 --- a/version/version.go +++ b/version/version.go @@ -1,3 +1,3 @@ package version -var Version = "0.6.3" +var Version = "0.7.0"