diff --git a/.custom-gcl.yml b/.custom-gcl.yml new file mode 100644 index 00000000000..d3bf8857d00 --- /dev/null +++ b/.custom-gcl.yml @@ -0,0 +1,4 @@ +version: v1.62.0 +plugins: + - module: "github.com/google/go-github/v68/tools/sliceofpointers" + path: ./tools/sliceofpointers diff --git a/.gitignore b/.gitignore index 8e24389445d..b81979c9430 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ vendor/ # goenv local version. See https://github.com/syndbg/goenv/blob/master/COMMANDS.md#goenv-local for more info. .go-version + +# golangci-lint -v custom generates the following local file: +custom-gcl diff --git a/.golangci.yml b/.golangci.yml index eae5a3bdd6a..fae768c5a57 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -18,12 +18,18 @@ linters: - perfsprint - paralleltest - revive + - sliceofpointers - stylecheck - tparallel - unconvert - unparam - whitespace linters-settings: + custom: + sliceofpointers: + type: module + description: Reports usage of []*string and slices of structs without pointers. + original-url: github.com/google/go-github/v68/tools/sliceofpointers gocritic: disable-all: true enabled-checks: @@ -38,7 +44,7 @@ linters-settings: misspell: locale: US ignore-words: - - "analyses" # returned by the GitHub API + - "analyses" # returned by the GitHub API - "cancelled" # returned by the GitHub API # extra words from https://go.dev//wiki/Spelling extra-words: @@ -102,28 +108,28 @@ issues: path: _test\.go # We need to pass nil Context in order to test DoBare erroring on nil ctx. - - linters: [ staticcheck ] - text: 'SA1012: do not pass a nil Context' + - linters: [staticcheck] + text: "SA1012: do not pass a nil Context" path: _test\.go # We need to use sha1 for validating signatures - - linters: [ gosec ] - text: 'G505: Blocklisted import crypto/sha1: weak cryptographic primitive' + - linters: [gosec] + text: "G505: Blocklisted import crypto/sha1: weak cryptographic primitive" # This is adapted from golangci-lint's default exclusions. It disables linting for error checks on # os.RemoveAll, fmt.Fprint*, fmt.Scanf, and any function ending in "Close". - - linters: [ errcheck ] + - linters: [errcheck] text: Error return value of .(.*Close|fmt\.Fprint.*|fmt\.Scanf|os\.Remove(All)?). is not checked # We don't care about file inclusion via variable in examples or internal tools. - - linters: [ gosec ] - text: 'G304: Potential file inclusion via variable' + - linters: [gosec] + text: "G304: Potential file inclusion via variable" path: '^(example|tools)\/' # We don't run parallel integration tests - - linters: [ paralleltest, tparallel ] - path: '^test/integration' + - linters: [paralleltest, tparallel] + path: "^test/integration" # Because fmt.Sprint(reset.Unix())) is more readable than strconv.FormatInt(reset.Unix(), 10). - - linters: [ perfsprint] - text: 'fmt.Sprint.* can be replaced with faster strconv.FormatInt' + - linters: [perfsprint] + text: "fmt.Sprint.* can be replaced with faster strconv.FormatInt" diff --git a/github/codespaces_secrets_test.go b/github/codespaces_secrets_test.go index 543e0651def..987cfaab612 100644 --- a/github/codespaces_secrets_test.go +++ b/github/codespaces_secrets_test.go @@ -25,7 +25,7 @@ func TestCodespacesService_ListSecrets(t *testing.T) { methodName string } opts := &ListOptions{Page: 2, PerPage: 2} - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -128,7 +128,7 @@ func TestCodespacesService_GetSecret(t *testing.T) { badCall func(context.Context, *Client) (*Secret, *Response, error) methodName string } - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -222,7 +222,7 @@ func TestCodespacesService_CreateOrUpdateSecret(t *testing.T) { badCall func(context.Context, *Client, *EncryptedSecret) (*Response, error) methodName string } - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -318,7 +318,7 @@ func TestCodespacesService_DeleteSecret(t *testing.T) { badCall func(context.Context, *Client) (*Response, error) methodName string } - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -401,7 +401,7 @@ func TestCodespacesService_GetPublicKey(t *testing.T) { methodName string } - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -496,7 +496,7 @@ func TestCodespacesService_ListSelectedReposForSecret(t *testing.T) { methodName string } opts := &ListOptions{Page: 2, PerPage: 2} - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -581,7 +581,7 @@ func TestCodespacesService_SetSelectedReposForSecret(t *testing.T) { methodName string } ids := SelectedRepoIDs{64780797} - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -653,7 +653,7 @@ func TestCodespacesService_AddSelectedReposForSecret(t *testing.T) { methodName string } repo := &Repository{ID: Ptr(int64(1234))} - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { @@ -721,7 +721,7 @@ func TestCodespacesService_RemoveSelectedReposFromSecret(t *testing.T) { methodName string } repo := &Repository{ID: Ptr(int64(1234))} - tests := []test{ + tests := []*test{ { name: "User", handleFunc: func(mux *http.ServeMux) { diff --git a/github/github.go b/github/github.go index d4ba320aa5d..ab74c5b72da 100644 --- a/github/github.go +++ b/github/github.go @@ -1117,7 +1117,8 @@ GitHub API docs: https://docs.github.com/rest/#client-errors type ErrorResponse struct { Response *http.Response `json:"-"` // HTTP response that caused this error Message string `json:"message"` // error message - Errors []Error `json:"errors"` // more detail on individual errors + //nolint:sliceofpointers + Errors []Error `json:"errors"` // more detail on individual errors // Block is only populated on certain types of errors such as code 451. Block *ErrorBlock `json:"block,omitempty"` // Most errors will also include a documentation_url field pointing diff --git a/github/strings_test.go b/github/strings_test.go index 4d53f21aac6..a164cebcac0 100644 --- a/github/strings_test.go +++ b/github/strings_test.go @@ -49,6 +49,7 @@ func TestStringify(t *testing.T) { {Ptr(123), `123`}, {Ptr(false), `false`}, { + //nolint:sliceofpointers []*string{Ptr("a"), Ptr("b")}, `["a" "b"]`, }, diff --git a/scrape/apps.go b/scrape/apps.go index fe99ea84a03..686cf773800 100644 --- a/scrape/apps.go +++ b/scrape/apps.go @@ -46,13 +46,13 @@ func (c *Client) AppRestrictionsEnabled(org string) (bool, error) { // ListOAuthApps lists the reviewed OAuth Applications for the // specified organization (whether approved or denied). -func (c *Client) ListOAuthApps(org string) ([]OAuthApp, error) { +func (c *Client) ListOAuthApps(org string) ([]*OAuthApp, error) { doc, err := c.get("/organizations/%s/settings/oauth_application_policy", org) if err != nil { return nil, err } - var apps []OAuthApp + var apps []*OAuthApp doc.Find(".oauth-application-allowlist ul > li").Each(func(i int, s *goquery.Selection) { var app OAuthApp app.Name = s.Find(".request-info strong").First().Text() @@ -73,7 +73,7 @@ func (c *Client) ListOAuthApps(org string) ([]OAuthApp, error) { } else if r := s.Find(".request-indicator .denied-request"); r.Length() > 0 { app.State = OAuthAppDenied } - apps = append(apps, app) + apps = append(apps, &app) }) return apps, nil diff --git a/scrape/apps_test.go b/scrape/apps_test.go index ae5b191eed8..7e9688e5efb 100644 --- a/scrape/apps_test.go +++ b/scrape/apps_test.go @@ -61,7 +61,7 @@ func Test_ListOAuthApps(t *testing.T) { if err != nil { t.Fatalf("ListOAuthApps(e) returned err: %v", err) } - want := []OAuthApp{ + want := []*OAuthApp{ { ID: 22222, Name: "Coveralls", diff --git a/scrape/forms.go b/scrape/forms.go index 6e01171e155..7beb46cf6e1 100644 --- a/scrape/forms.go +++ b/scrape/forms.go @@ -35,7 +35,7 @@ type htmlForm struct { // // In the future, we might want to allow a custom selector to be passed in to // further restrict what forms will be returned. -func parseForms(node *html.Node) (forms []htmlForm) { +func parseForms(node *html.Node) (forms []*htmlForm) { if node == nil { return nil } @@ -71,7 +71,7 @@ func parseForms(node *html.Node) (forms []htmlForm) { value := s.Text() form.Values.Add(name, value) }) - forms = append(forms, form) + forms = append(forms, &form) }) return forms diff --git a/scrape/forms_test.go b/scrape/forms_test.go index 28c30c6c670..b10f250127d 100644 --- a/scrape/forms_test.go +++ b/scrape/forms_test.go @@ -16,14 +16,14 @@ func Test_ParseForms(t *testing.T) { tests := []struct { description string html string - forms []htmlForm + forms []*htmlForm }{ {"no forms", ``, nil}, - {"empty form", `
`, []htmlForm{{Values: url.Values{}}}}, + {"empty form", ``, []*htmlForm{{Values: url.Values{}}}}, { "single form with one value", ``, - []htmlForm{{Action: "a", Method: "m", Values: url.Values{"n1": {"v1"}}}}, + []*htmlForm{{Action: "a", Method: "m", Values: url.Values{"n1": {"v1"}}}}, }, { "two forms", @@ -31,7 +31,7 @@ func Test_ParseForms(t *testing.T) {