Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.18.0'
go-version: '1.25.3'
- run: bash scripts/gogetcookie.sh
- run: make build
6 changes: 3 additions & 3 deletions .github/workflows/depscheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ jobs:
depscheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.18.0'
go-version: '1.25.3'
- run: bash scripts/gogetcookie.sh
- run: make depscheck
10 changes: 5 additions & 5 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
golint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.18.0'
- uses: golangci/golangci-lint-action@v2
go-version-file: ./.go-version
- uses: golangci/golangci-lint-action@v7
with:
version: 'v1.64.6'
version: 'v2.4.0'
args: -v
1 change: 1 addition & 0 deletions .go-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.25.3
118 changes: 57 additions & 61 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,70 +1,66 @@
version: "2"

run:
deadline: 10m10s
timeout: 60m
modules-download-mode: vendor
go: 1.17 # 1.18 disabled some linters as they don't support generics yet, as such lock to 1.17 until they do

issues:
max-per-linter: 0
max-issues-per-linter: 0
max-same-issues: 0

linters:
disable-all: true
enable:
- asasalint
- asciicheck
- bidichk
- containedctx
- contextcheck
- decorder
- durationcheck
- errcheck
- errchkjson
- errname
- errorlint
- exhaustive
- gocritic
- gofmt
- gofumpt
- goimports
- gosec
- gosimple
- govet
- govet
- ineffassign
- makezero
- misspell
- nakedret
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- prealloc
- predeclared
- revive
- staticcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- wastedassign
- whitespace
#- paralleltest
# - wsl #linter configuration is still quite not flexible enough for my liking, leaving disabled for now
- asasalint # check for pass []any as any in variadic func(...any)
- asciicheck # ensure code does not contain non-ASCII identifiers
- bidichk # checks for dangerous unicode character sequences
- bodyclose # checks whether HTTP response bodies are closed
- copyloopvar #Detects range loop variables that are overwritten in the loop body
- decorder # check declaration order and count of types, constants, variables and functions.
- durationcheck # check for common mistakes when working with time.Duration
- dupword # check for duplicated words in comments
- errcheck # checking for unchecked errors
- errorlint #Errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme used in the github.com/pkg/errors package.
- exhaustive # checks switch statements over enums for missing cases
- gocritic # linter for Go source code that specializes in simplifying code
- govet # reports suspicious constructs. It is roughly the same as 'go vet' (replaced vet and vetshadow)
- gosec # Gosec is a security linter for Go source code
- ineffassign # detects when assignments to existing variables are not used
- misspell # finds commonly misspelled English words.
- nilerr # Finds code that returns nil after it checks that the error is not nil.
- nakedret # Checks that functions with naked returns are not longer than a maximum size
- prealloc # finds slice declarations that could potentially be pre-allocated.
- predeclared # find code that shadows one of Go's predeclared identifiers.
- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative.
- paralleltest # detects missing usage of t.Parallel() method in your Go test.
- reassign # checks that package variables are not reassigned.
- tagalign # checks struct tags that do not align with the specified column in struct definitions.
- tparallel # Tparallel detects inappropriate usage of t.Parallel() method in your Go test codes.
- staticcheck # checks rules from staticcheck. It's not the same thing as the staticcheck binary.
- testableexamples #checks Go examples are testable
- unused # checks Go code for unused constants, variables, functions and types.
- unconvert # checks for unnecessary type conversions.
- unparam # reports unused function parameters.
- wastedassign # finds wasted assignment statements
- whitespace # checks for unnecessary newlines at the start and end of functions, if, for, etc. (
settings:
errcheck:
exclude-functions:
- io.Close
nakedret:
max-func-lines: 30
misspell:
locale: "UK"
ignore-rules:
- "color"
- "organization"
- "recognized"
tagalign:
sort: true
predeclared:
ignore: ["new","min","max"] # should we use newer, minimum, and maximum instead?

linters-settings:
errcheck:
exclude-functions: io:Close
misspell:
locale: uk
nlreturn:
block-size: 4
wsl:
allow-assign-and-anything: true
allow-separated-leading-comment: true
allow-trailing-comment: true
allow-cuddle-declarations: true
allow-multiline-assign: true
force-case-trailing-whitespace: 1
enforce-err-cuddling: true
formatters:
enable:
- gofmt # checks whether code was gofmt-ed
- gofumpt # checks whether code was gofumpt-ed, a stricter gofmt
- goimports # check import statements are formatted according to the 'goimport' command
31 changes: 17 additions & 14 deletions cli/cmds.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package cli

import (
"errors"
"fmt"
"sort"
"strconv"
"strings"

Expand All @@ -18,7 +18,7 @@ func ValidateParams(params []string) func(cmd *cobra.Command, args []string) err
return func(_ *cobra.Command, _ []string) error {
for _, p := range params {
if viper.GetString(p) == "" {
return fmt.Errorf(p + " parameter can't be empty")
return errors.New(p + " parameter can't be empty")
}
}

Expand Down Expand Up @@ -94,18 +94,18 @@ Complete documentation is available at https://github.com/katbyte/tctest`,
cmd.SilenceUsage = true

// parse list of prs
numbers := []int{}
prTitles := make(map[int]string)
for _, pr := range strings.Split(prs, ",") {
pri, err := strconv.Atoi(pr)
if err != nil {
c.Printf("<red>ERROR:</> parsing PRs: unable to convert '%s' into an integer: %v\n", pr, err)
continue
}

numbers = append(numbers, pri)
prTitles[pri] = "" // title unknown when passed via command line
}

return GetFlags().GetAndRunPrsTests(numbers, testRegExParam)
return GetFlags().GetAndRunPrsTests(prTitles, testRegExParam)
},
})

Expand All @@ -127,18 +127,22 @@ Complete documentation is available at https://github.com/katbyte/tctest`,
f := GetFlags()
r := f.NewRepo()

c.Printf("Filters:\n")
filters, err := f.GetFilters()
if err != nil {
return fmt.Errorf("error creating filters: %w", err)
}

// get all pull requests
c.Printf("Retrieving all prs for <white>%s</>/<cyan>%s</>...", r.Owner, r.Name)
prs, err := r.GetAllPullRequests("open") // todo should this return a list not map? probably
if err != nil {
c.Printf("\n\n <red>ERROR!!</> %s\n", err)
return nil
}
c.Printf(" found <yellow>%d</>. Filters:\n", len(*prs))

filters := f.GetFilters()
c.Printf(" found <yellow>%d</>\n", len(*prs))

var numbers []int
prTitles := make(map[int]string)
fmt.Println("Filtering:")
for _, pr := range *prs {
c.Printf(" #<cyan>%d</> <gray>(%s></>\n", pr.GetNumber(), pr.GetHTMLURL())
Expand All @@ -153,16 +157,15 @@ Complete documentation is available at https://github.com/katbyte/tctest`,
}

if passed {
numbers = append(numbers, pr.GetNumber())
prTitles[pr.GetNumber()] = pr.GetTitle()
}

fmt.Println()
}

sort.Ints(numbers)
c.Printf("testing <yellow>%d</> prs\n\n", len(numbers))
c.Printf("testing <yellow>%d</> prs\n\n", len(prTitles))

return GetFlags().GetAndRunPrsTests(numbers, testRegExParam)
return GetFlags().GetAndRunPrsTests(prTitles, testRegExParam)
},
})

Expand All @@ -181,7 +184,7 @@ Complete documentation is available at https://github.com/katbyte/tctest`,

cmd.SilenceUsage = true

_, err = GetFlags().GetPrTests(pr)
_, err = GetFlags().GetPrTests(pr, "")

return err
},
Expand Down
4 changes: 4 additions & 0 deletions cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type FlagsGitHubPrFilter struct {
LabelsOr []string
LabelsAnd []string
Milestone string
TitleRegex string
Drafts bool
CreationTime time.Duration
UpdatedTime time.Duration
Expand Down Expand Up @@ -70,6 +71,7 @@ func configureFlags(root *cobra.Command) error {
pflags.StringVarP(&flags.GH.FilterPRs.Milestone, "f-milestone", "m", "", "filter out PRs that have or do no have a milestone, ie 'this-milstone' or '-not-this-milestone'")
pflags.DurationVarP(&flags.GH.FilterPRs.CreationTime, "f-created-time", "", time.Nanosecond, "filter out PRs that where not created within this duration")
pflags.DurationVarP(&flags.GH.FilterPRs.UpdatedTime, "f-updated-time", "", time.Nanosecond, "filter out PRs that where not created within this duration")
pflags.StringVarP(&flags.GH.FilterPRs.TitleRegex, "f-title-regex", "", "", "filter PRs by title using case-insensitive regex (e.g. 'test' matches titles containing 'test', 'fix.*bug' matches 'fix' followed by 'bug')")
pflags.BoolVarP(&flags.GH.FilterPRs.Drafts, "f-drafts", "d", false, "filter out any PRs that are in draft more")

pflags.StringVarP(&flags.TC.ServerURL, "server", "s", "", "the TeamCity server's url")
Expand Down Expand Up @@ -107,6 +109,7 @@ func configureFlags(root *cobra.Command) error {
"f-labels-any": "",
"f-created-time": "",
"f-updated-time": "",
"f-title-regex": "",
"latest": "TCTEST_LATESTBUILD",
"skip-queue": "TCTEST_SKIP_QUEUE",
"open": "TCTEST_OPEN_BROWSER",
Expand Down Expand Up @@ -153,6 +156,7 @@ func GetFlags() FlagData {
LabelsOr: viper.GetStringSlice("f-labels-any"),
LabelsAnd: viper.GetStringSlice("f-labels-all"),
Milestone: viper.GetString("f-milestone"),
TitleRegex: viper.GetString("f-title-regex"),
CreationTime: viper.GetDuration("f-created-time"),
UpdatedTime: viper.GetDuration("f-updated-time"),
Drafts: viper.GetBool("f-draft"),
Expand Down
43 changes: 41 additions & 2 deletions cli/gh-pr-filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"regexp"
"strings"
"time"

Expand All @@ -14,7 +15,7 @@ type Filter struct {
PR func(github.PullRequest) (bool, error) // todo shjould this return an error?
}

func (f FlagData) GetFilters() []Filter {
func (f FlagData) GetFilters() ([]Filter, error) {
var filters []Filter

// should these return errors
Expand Down Expand Up @@ -42,9 +43,17 @@ func (f FlagData) GetFilters() []Filter {
filters = append(filters, *f)
}

titleFilter, err := GetFilterForTitleRegex(f.GH.FilterPRs.TitleRegex)
if err != nil {
return nil, err
}
if titleFilter != nil {
filters = append(filters, *titleFilter)
}

fmt.Println()

return filters
return filters, nil
}

func GetFilterForAuthors(authors []string) *Filter {
Expand Down Expand Up @@ -233,3 +242,33 @@ func GetFilterForLabels(labels []string, and bool) *Filter {
},
}
}

func GetFilterForTitleRegex(pattern string) (*Filter, error) {
if pattern == "" {
return nil, nil
}

// Make the pattern case-insensitive by adding (?i) prefix
caseInsensitivePattern := "(?i)" + pattern
re, err := regexp.Compile(caseInsensitivePattern)
if err != nil {
return nil, fmt.Errorf("invalid title regex pattern '%s': %w", pattern, err)
}

c.Printf(" title regex: <magenta>%s</> (case-insensitive)\n", pattern)

return &Filter{
Name: "title-regex",
PR: func(pr github.PullRequest) (bool, error) {
title := pr.GetTitle()

if re.MatchString(title) {
c.Printf(" title: <green>%s</>\n", title)
return true, nil
}

c.Printf(" title: <red>%s</>\n", title)
return false, nil
},
}, nil
}
Loading