From 2656cfe8efe5acbf884814ddd775eceb4af38b7a Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 17:08:53 +0900 Subject: [PATCH 1/7] feat!: Check json omitempty tag usage in custom linter --- tools/sliceofpointers/sliceofpointers.go | 51 +++++++++++++++++++ .../testdata/src/has-warnings/main.go | 11 ++++ .../testdata/src/no-warnings/main.go | 24 +++++++++ 3 files changed, 86 insertions(+) diff --git a/tools/sliceofpointers/sliceofpointers.go b/tools/sliceofpointers/sliceofpointers.go index 75b14d068dc..210351461b6 100644 --- a/tools/sliceofpointers/sliceofpointers.go +++ b/tools/sliceofpointers/sliceofpointers.go @@ -12,6 +12,9 @@ package sliceofpointers import ( "go/ast" "go/token" + "reflect" + "slices" + "strings" "github.com/golangci/plugin-module-register/register" "golang.org/x/tools/go/analysis" @@ -55,6 +58,8 @@ func run(pass *analysis.Pass) (any, error) { switch t := n.(type) { case *ast.ArrayType: checkArrayType(t, t.Pos(), pass) + case *ast.StructType: + checkStructType(t, pass) } return true @@ -75,3 +80,49 @@ func checkArrayType(arrType *ast.ArrayType, tokenPos token.Pos, pass *analysis.P } } } + +// allowedQualifiedTypes is a allowlist of qualified types (package.Type) that are allowed +// to use omitempty without pointers because they are reference types or have special semantics. +var allowedQualifiedTypes = [][2]string{ + {"json", "RawMessage"}, // json.RawMessage is []byte, can be nil +} + +func checkStructType(structType *ast.StructType, pass *analysis.Pass) { + if structType.Fields == nil { + return + } + + for _, field := range structType.Fields.List { + if field.Tag == nil { + continue + } + + // Parse struct tag properly using reflect.StructTag + tag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) + if jsonTag := tag.Get("json"); !strings.Contains(jsonTag, "omitempty") { + continue + } + + switch t := field.Type.(type) { + case *ast.Ident: + if t.Name == "any" { + break + } + + pass.Reportf(field.Pos(), "using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted") + case *ast.SelectorExpr: + if x, ok := t.X.(*ast.Ident); ok && slices.Contains(allowedQualifiedTypes, [2]string{x.Name, t.Sel.Name}) { + break + } + + pass.Reportf(field.Pos(), "using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted") + default: + // *ast.StarExpr: pointers (can be nil) + // *ast.ArrayType: slices/arrays (slices can be nil) + // *ast.MapType: maps (can be nil) + // *ast.InterfaceType: interfaces (can be nil) + // All other types: safe by default + break + } + } +} diff --git a/tools/sliceofpointers/testdata/src/has-warnings/main.go b/tools/sliceofpointers/testdata/src/has-warnings/main.go index 84e0d024e4b..2e406ef40e0 100644 --- a/tools/sliceofpointers/testdata/src/has-warnings/main.go +++ b/tools/sliceofpointers/testdata/src/has-warnings/main.go @@ -5,6 +5,8 @@ package main +import "time" + type Example struct { Strings []*string `json:"strings,omitempty"` // want `use \[\]string instead of \[\]\*string` Things []Thing `json:"things,omitempty"` // want `use \[\]\*Thing instead of \[\]Thing` @@ -13,6 +15,15 @@ type Example struct { type Thing struct { } +type OmitemptyExample struct { + Name string `json:"name,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` + Age int `json:"age,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` + Count int64 `json:"count,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` + Active bool `json:"active,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` + Thing Thing `json:"thing,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` + Time time.Time `json:"time,omitempty"` // want `using json:\"omitempty\" tag will cause zero values to be unexpectedly omitted` +} + func main() { slice1 := []*string{} // want `use \[\]string instead of \[\]\*string` _ = slice1 diff --git a/tools/sliceofpointers/testdata/src/no-warnings/main.go b/tools/sliceofpointers/testdata/src/no-warnings/main.go index 529d1d2fdad..72093cfae17 100644 --- a/tools/sliceofpointers/testdata/src/no-warnings/main.go +++ b/tools/sliceofpointers/testdata/src/no-warnings/main.go @@ -5,6 +5,8 @@ package main +import "encoding/json" + type Example struct { Strings []string `json:"strings,omitempty"` // Should not be flagged Things []*Thing `json:"things,omitempty"` // Should not be flagged @@ -13,6 +15,28 @@ type Example struct { type Thing struct { } +type OmitemptyExample struct { + // Fields with omitempty using pointer types - should NOT be flagged + Name *string `json:"name,omitempty"` // Should not be flagged + Age *int `json:"age,omitempty"` // Should not be flagged + Count *int64 `json:"count,omitempty"` // Should not be flagged + Active *bool `json:"active,omitempty"` // Should not be flagged + Thing *Thing `json:"thing,omitempty"` // Should not be flagged + + // Reference types that can be nil - should NOT be flagged + Map map[string]any `json:"map,omitempty"` // Should not be flagged (map can be nil) + RawMessage json.RawMessage `json:"raw_message,omitempty"` // Should not be flagged ([]byte can be nil) + Interface any `json:"interface,omitempty"` // Should not be flagged (interface can be nil) + Slice []string `json:"slice,omitempty"` // Should not be flagged (slice can be nil) + + // Fields without omitempty using value types - should NOT be flagged + Name2 string `json:"name2"` // Should not be flagged + Age2 int `json:"age2"` // Should not be flagged + + // Fields without json tag - should NOT be flagged + Internal string // Should not be flagged +} + func main() { slice1 := []string{} // Should not be flagged _ = slice1 From f7b17967ca589857e19c6d6dd55a2455f9912a20 Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 17:19:44 +0900 Subject: [PATCH 2/7] mark nolint to internal tools --- tools/metadata/metadata.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/metadata/metadata.go b/tools/metadata/metadata.go index 445f31a73d4..9cf1685e212 100644 --- a/tools/metadata/metadata.go +++ b/tools/metadata/metadata.go @@ -29,8 +29,8 @@ import ( ) type operation struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` - DocumentationURL string `yaml:"documentation_url,omitempty" json:"documentation_url,omitempty"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` //nolint:sliceofpointers + DocumentationURL string `yaml:"documentation_url,omitempty" json:"documentation_url,omitempty"` //nolint:sliceofpointers OpenAPIFiles []string `yaml:"openapi_files,omitempty" json:"openapi_files,omitempty"` } From 6c010089a42d1ef53f5f9b456d88f90e859b4740 Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 17:28:01 +0900 Subject: [PATCH 3/7] fix omitempty lint issues --- github/actions_hosted_runners.go | 28 +- github/actions_hosted_runners_test.go | 84 ++--- github/actions_secrets.go | 14 +- github/actions_secrets_test.go | 26 +- github/activity_notifications.go | 6 +- github/activity_notifications_test.go | 2 +- github/dependabot_secrets.go | 19 +- github/dependabot_secrets_test.go | 14 +- .../enterprise_actions_hosted_runners_test.go | 84 ++--- github/enterprise_rules_test.go | 16 +- github/git_tags.go | 8 +- github/git_tags_test.go | 16 +- github/git_trees.go | 10 +- github/git_trees_test.go | 2 +- github/github-accessors.go | 224 +++++++++++++ github/github-accessors_test.go | 296 ++++++++++++++++++ github/github.go | 4 +- github/issues.go | 2 +- github/issues_events.go | 2 +- github/issues_test.go | 4 +- github/meta.go | 2 +- github/meta_test.go | 4 +- github/orgs_rules_test.go | 12 +- github/pulls.go | 18 +- github/pulls_comments.go | 8 +- github/pulls_test.go | 6 +- github/rate_limit.go | 2 +- github/repos.go | 7 +- github/repos_collaborators.go | 2 +- github/repos_collaborators_test.go | 4 +- github/repos_contents.go | 2 +- github/repos_contents_test.go | 8 +- github/repos_forks.go | 6 +- github/repos_forks_test.go | 4 +- github/repos_rules_test.go | 2 +- github/rules.go | 2 +- github/rules_test.go | 8 +- github/teams.go | 2 +- github/teams_members.go | 2 +- github/teams_members_test.go | 10 +- github/teams_test.go | 6 +- 41 files changed, 757 insertions(+), 221 deletions(-) diff --git a/github/actions_hosted_runners.go b/github/actions_hosted_runners.go index 207b755fc30..d7b31ccefd7 100644 --- a/github/actions_hosted_runners.go +++ b/github/actions_hosted_runners.go @@ -92,13 +92,13 @@ type HostedRunnerImage struct { // HostedRunnerRequest specifies body parameters to Hosted Runner configuration. type HostedRunnerRequest struct { - Name string `json:"name,omitempty"` - Image HostedRunnerImage `json:"image,omitempty"` - RunnerGroupID int64 `json:"runner_group_id,omitempty"` - Size string `json:"size,omitempty"` - MaximumRunners int64 `json:"maximum_runners,omitempty"` - EnableStaticIP bool `json:"enable_static_ip,omitempty"` - ImageVersion string `json:"image_version,omitempty"` + Name *string `json:"name,omitempty"` + Image *HostedRunnerImage `json:"image,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + Size *string `json:"size,omitempty"` + MaximumRunners *int64 `json:"maximum_runners,omitempty"` + EnableStaticIP *bool `json:"enable_static_ip,omitempty"` + ImageVersion *string `json:"image_version,omitempty"` } // validateCreateHostedRunnerRequest validates the provided HostedRunnerRequest to ensure @@ -110,19 +110,19 @@ func validateCreateHostedRunnerRequest(request *HostedRunnerRequest) error { if request == nil { return errors.New("request is required for creating a hosted runner") } - if request.Size == "" { + if request.Size == nil { return errors.New("size is required for creating a hosted runner") } - if request.Image == (HostedRunnerImage{}) { + if request.Image == nil { return errors.New("image is required for creating a hosted runner") } - if request.Name == "" { + if request.Name == nil { return errors.New("name is required for creating a hosted runner") } - if request.RunnerGroupID == 0 { + if request.RunnerGroupID == nil { return errors.New("runner group ID is required for creating a hosted runner") } - if request.ImageVersion != "" { + if request.ImageVersion != nil { return errors.New("imageVersion should not be set directly; use the Image struct to specify image details") } return nil @@ -323,10 +323,10 @@ func (s *ActionsService) GetHostedRunner(ctx context.Context, org string, runner // If any of these conditions are violated, an appropriate error message is returned. // Otherwise, nil is returned, indicating the request is valid for an update. func validateUpdateHostedRunnerRequest(request *HostedRunnerRequest) error { - if request.Size != "" { + if request.Size != nil { return errors.New("size cannot be updated, API does not support updating size") } - if request.Image != (HostedRunnerImage{}) { + if request.Image != nil { return errors.New("image struct should not be set directly; use the ImageVersion to specify version details") } return nil diff --git a/github/actions_hosted_runners_test.go b/github/actions_hosted_runners_test.go index 2f5f62ea27d..ece364dbbba 100644 --- a/github/actions_hosted_runners_test.go +++ b/github/actions_hosted_runners_test.go @@ -193,16 +193,16 @@ func TestActionsService_CreateHostedRunner(t *testing.T) { ctx := t.Context() validReq := &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", - MaximumRunners: 50, - EnableStaticIP: false, + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), } hostedRunner, _, err := client.Actions.CreateHostedRunner(ctx, "o", validReq) if err != nil { @@ -256,65 +256,65 @@ func TestActionsService_CreateHostedRunner(t *testing.T) { { name: "Missing Size", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, + RunnerGroupID: Ptr(int64(1)), }, expectedError: "validation failed: size is required for creating a hosted runner", }, { name: "Missing Image", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - RunnerGroupID: 1, - Size: "4-core", + Name: Ptr("My Hosted runner"), + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), }, expectedError: "validation failed: image is required for creating a hosted runner", }, { name: "Missing Name", request: &HostedRunnerRequest{ - Image: HostedRunnerImage{ + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), }, expectedError: "validation failed: name is required for creating a hosted runner", }, { name: "Missing RunnerGroupID", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - Size: "4-core", + Size: Ptr("4-core"), }, expectedError: "validation failed: runner group ID is required for creating a hosted runner", }, { name: "ImageVersion Set Instead of Image Struct", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", - ImageVersion: "1.0.0", - MaximumRunners: 50, - EnableStaticIP: false, + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), + ImageVersion: Ptr("1.0.0"), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), }, expectedError: "validation failed: imageVersion should not be set directly; use the Image struct to specify image details", }, @@ -732,11 +732,11 @@ func TestActionsService_UpdateHostedRunner(t *testing.T) { ctx := t.Context() validReq := HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), } hostedRunner, _, err := client.Actions.UpdateHostedRunner(ctx, "o", 23, validReq) if err != nil { @@ -784,24 +784,24 @@ func TestActionsService_UpdateHostedRunner(t *testing.T) { { name: "Size Set in Update Request", request: HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", - Size: "4-core", // Should cause validation error + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), + Size: Ptr("4-core"), // Should cause validation error }, expectedError: "validation failed: size cannot be updated, API does not support updating size", }, { name: "Image Set in Update Request", request: HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", - Image: HostedRunnerImage{ // Should cause validation error + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), + Image: &HostedRunnerImage{ // Should cause validation error ID: "ubuntu-latest", Source: "github", Version: "latest", diff --git a/github/actions_secrets.go b/github/actions_secrets.go index f03d3fd191d..ba470b3bb89 100644 --- a/github/actions_secrets.go +++ b/github/actions_secrets.go @@ -98,8 +98,8 @@ type Secret struct { Name string `json:"name"` CreatedAt Timestamp `json:"created_at"` UpdatedAt Timestamp `json:"updated_at"` - Visibility string `json:"visibility,omitempty"` - SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` + Visibility *string `json:"visibility,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` } // Secrets represents one item from the ListSecrets response. @@ -225,11 +225,11 @@ type SelectedRepoIDs []int64 // LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) // using the public key retrieved using the GetPublicKey method. type EncryptedSecret struct { - Name string `json:"-"` - KeyID string `json:"key_id"` - EncryptedValue string `json:"encrypted_value"` - Visibility string `json:"visibility,omitempty"` - SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility *string `json:"visibility,omitempty"` + SelectedRepositoryIDs *SelectedRepoIDs `json:"selected_repository_ids,omitempty"` } func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { diff --git a/github/actions_secrets_test.go b/github/actions_secrets_test.go index 7dc499e56fc..5010a9ba791 100644 --- a/github/actions_secrets_test.go +++ b/github/actions_secrets_test.go @@ -404,9 +404,9 @@ func TestActionsService_ListOrgSecrets(t *testing.T) { want := &Secrets{ TotalCount: 3, Secrets: []*Secret{ - {Name: "GIST_ID", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "private"}, - {Name: "DEPLOY_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "all"}, - {Name: "GH_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "selected", SelectedRepositoriesURL: "https://api.github.com/orgs/octo-org/actions/secrets/SUPER_SECRET/repositories"}, + {Name: "GIST_ID", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("private")}, + {Name: "DEPLOY_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("all")}, + {Name: "GH_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("selected"), SelectedRepositoriesURL: Ptr("https://api.github.com/orgs/octo-org/actions/secrets/SUPER_SECRET/repositories")}, }, } if !cmp.Equal(secrets, want) { @@ -447,8 +447,8 @@ func TestActionsService_GetOrgSecret(t *testing.T) { Name: "NAME", CreatedAt: Timestamp{time.Date(2019, time.January, 2, 15, 4, 5, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 2, 15, 4, 5, 0, time.UTC)}, - Visibility: "selected", - SelectedRepositoriesURL: "https://api.github.com/orgs/octo-org/actions/secrets/SUPER_SECRET/repositories", + Visibility: Ptr("selected"), + SelectedRepositoriesURL: Ptr("https://api.github.com/orgs/octo-org/actions/secrets/SUPER_SECRET/repositories"), } if !cmp.Equal(secret, want) { t.Errorf("Actions.GetOrgSecret returned %+v, want %+v", secret, want) @@ -484,8 +484,8 @@ func TestActionsService_CreateOrUpdateOrgSecret(t *testing.T) { Name: "NAME", EncryptedValue: "QIv=", KeyID: "1234", - Visibility: "selected", - SelectedRepositoryIDs: SelectedRepoIDs{1296269, 1269280}, + Visibility: Ptr("selected"), + SelectedRepositoryIDs: &SelectedRepoIDs{1296269, 1269280}, } ctx := t.Context() _, err := client.Actions.CreateOrUpdateOrgSecret(ctx, "o", input) @@ -900,8 +900,8 @@ func TestSecret_Marshal(t *testing.T) { Name: "n", CreatedAt: Timestamp{referenceTime}, UpdatedAt: Timestamp{referenceTime}, - Visibility: "v", - SelectedRepositoriesURL: "s", + Visibility: Ptr("v"), + SelectedRepositoriesURL: Ptr("s"), } want := `{ @@ -926,8 +926,8 @@ func TestSecrets_Marshal(t *testing.T) { Name: "n", CreatedAt: Timestamp{referenceTime}, UpdatedAt: Timestamp{referenceTime}, - Visibility: "v", - SelectedRepositoriesURL: "s", + Visibility: Ptr("v"), + SelectedRepositoriesURL: Ptr("s"), }, }, } @@ -956,8 +956,8 @@ func TestEncryptedSecret_Marshal(t *testing.T) { Name: "n", KeyID: "kid", EncryptedValue: "e", - Visibility: "v", - SelectedRepositoryIDs: []int64{1}, + Visibility: Ptr("v"), + SelectedRepositoryIDs: &SelectedRepoIDs{1}, } want := `{ diff --git a/github/activity_notifications.go b/github/activity_notifications.go index e712323ed43..24d8ef71fbc 100644 --- a/github/activity_notifications.go +++ b/github/activity_notifications.go @@ -101,7 +101,7 @@ func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner } type markReadOptions struct { - LastReadAt Timestamp `json:"last_read_at,omitempty"` + LastReadAt *Timestamp `json:"last_read_at,omitempty"` } // MarkNotificationsRead marks all notifications up to lastRead as read. @@ -111,7 +111,7 @@ type markReadOptions struct { //meta:operation PUT /notifications func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead Timestamp) (*Response, error) { opts := &markReadOptions{ - LastReadAt: lastRead, + LastReadAt: &lastRead, } req, err := s.client.NewRequest("PUT", "notifications", opts) if err != nil { @@ -129,7 +129,7 @@ func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead Ti //meta:operation PUT /repos/{owner}/{repo}/notifications func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead Timestamp) (*Response, error) { opts := &markReadOptions{ - LastReadAt: lastRead, + LastReadAt: &lastRead, } u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) req, err := s.client.NewRequest("PUT", u, opts) diff --git a/github/activity_notifications_test.go b/github/activity_notifications_test.go index 7744f1e6a3d..0c1e9bf5f4a 100644 --- a/github/activity_notifications_test.go +++ b/github/activity_notifications_test.go @@ -411,7 +411,7 @@ func TestMarkReadOptions_Marshal(t *testing.T) { testJSONMarshal(t, &markReadOptions{}, "{}") u := &markReadOptions{ - LastReadAt: Timestamp{referenceTime}, + LastReadAt: &Timestamp{referenceTime}, } want := `{ diff --git a/github/dependabot_secrets.go b/github/dependabot_secrets.go index b4b3e0aa560..d27ae9cb76b 100644 --- a/github/dependabot_secrets.go +++ b/github/dependabot_secrets.go @@ -129,11 +129,11 @@ func (s *DependabotService) GetOrgSecret(ctx context.Context, org, name string) // LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) // using the public key retrieved using the GetPublicKey method. type DependabotEncryptedSecret struct { - Name string `json:"-"` - KeyID string `json:"key_id"` - EncryptedValue string `json:"encrypted_value"` - Visibility string `json:"visibility,omitempty"` - SelectedRepositoryIDs DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids,omitempty"` + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility *string `json:"visibility,omitempty"` + SelectedRepositoryIDs *DependabotSecretsSelectedRepoIDs `json:"selected_repository_ids,omitempty"` } func (s *DependabotService) putSecret(ctx context.Context, url string, eSecret *DependabotEncryptedSecret) (*Response, error) { @@ -169,9 +169,12 @@ func (s *DependabotService) CreateOrUpdateOrgSecret(ctx context.Context, org str return nil, errors.New("dependabot encrypted secret must be provided") } - repoIDs := make([]string, len(eSecret.SelectedRepositoryIDs)) - for i, secret := range eSecret.SelectedRepositoryIDs { - repoIDs[i] = fmt.Sprintf("%v", secret) + var repoIDs []string + if eSecret.SelectedRepositoryIDs != nil { + repoIDs = make([]string, len(*eSecret.SelectedRepositoryIDs)) + for i, secret := range *eSecret.SelectedRepositoryIDs { + repoIDs[i] = fmt.Sprintf("%v", secret) + } } params := struct { *DependabotEncryptedSecret diff --git a/github/dependabot_secrets_test.go b/github/dependabot_secrets_test.go index 69247457a63..99c4f8b14a0 100644 --- a/github/dependabot_secrets_test.go +++ b/github/dependabot_secrets_test.go @@ -283,9 +283,9 @@ func TestDependabotService_ListOrgSecrets(t *testing.T) { want := &Secrets{ TotalCount: 3, Secrets: []*Secret{ - {Name: "GIST_ID", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "private"}, - {Name: "DEPLOY_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "all"}, - {Name: "GH_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: "selected", SelectedRepositoriesURL: "https://api.github.com/orgs/octo-org/dependabot/secrets/SUPER_SECRET/repositories"}, + {Name: "GIST_ID", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("private")}, + {Name: "DEPLOY_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("all")}, + {Name: "GH_TOKEN", CreatedAt: Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, Visibility: Ptr("selected"), SelectedRepositoriesURL: Ptr("https://api.github.com/orgs/octo-org/dependabot/secrets/SUPER_SECRET/repositories")}, }, } if !cmp.Equal(secrets, want) { @@ -326,8 +326,8 @@ func TestDependabotService_GetOrgSecret(t *testing.T) { Name: "NAME", CreatedAt: Timestamp{time.Date(2019, time.January, 2, 15, 4, 5, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 2, 15, 4, 5, 0, time.UTC)}, - Visibility: "selected", - SelectedRepositoriesURL: "https://api.github.com/orgs/octo-org/dependabot/secrets/SUPER_SECRET/repositories", + Visibility: Ptr("selected"), + SelectedRepositoriesURL: Ptr("https://api.github.com/orgs/octo-org/dependabot/secrets/SUPER_SECRET/repositories"), } if !cmp.Equal(secret, want) { t.Errorf("Dependabot.GetOrgSecret returned %+v, want %+v", secret, want) @@ -363,8 +363,8 @@ func TestDependabotService_CreateOrUpdateOrgSecret(t *testing.T) { Name: "NAME", EncryptedValue: "QIv=", KeyID: "1234", - Visibility: "selected", - SelectedRepositoryIDs: DependabotSecretsSelectedRepoIDs{1296269, 1269280}, + Visibility: Ptr("selected"), + SelectedRepositoryIDs: &DependabotSecretsSelectedRepoIDs{1296269, 1269280}, } ctx := t.Context() _, err := client.Dependabot.CreateOrUpdateOrgSecret(ctx, "o", input) diff --git a/github/enterprise_actions_hosted_runners_test.go b/github/enterprise_actions_hosted_runners_test.go index 740e41a5b6f..78c3c00b7b4 100644 --- a/github/enterprise_actions_hosted_runners_test.go +++ b/github/enterprise_actions_hosted_runners_test.go @@ -192,16 +192,16 @@ func TestEnterpriseService_CreateHostedRunner(t *testing.T) { ctx := t.Context() req := &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", - MaximumRunners: 50, - EnableStaticIP: false, + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), } hostedRunner, _, err := client.Enterprise.CreateHostedRunner(ctx, "o", req) if err != nil { @@ -250,65 +250,65 @@ func TestEnterpriseService_CreateHostedRunner(t *testing.T) { { name: "Missing Size", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, + RunnerGroupID: Ptr(int64(1)), }, expectedError: "validation failed: size is required for creating a hosted runner", }, { name: "Missing Image", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - RunnerGroupID: 1, - Size: "4-core", + Name: Ptr("My Hosted runner"), + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), }, expectedError: "validation failed: image is required for creating a hosted runner", }, { name: "Missing Name", request: &HostedRunnerRequest{ - Image: HostedRunnerImage{ + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), }, expectedError: "validation failed: name is required for creating a hosted runner", }, { name: "Missing RunnerGroupID", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - Size: "4-core", + Size: Ptr("4-core"), }, expectedError: "validation failed: runner group ID is required for creating a hosted runner", }, { name: "ImageVersion Set Instead of Image Struct", request: &HostedRunnerRequest{ - Name: "My Hosted runner", - Image: HostedRunnerImage{ + Name: Ptr("My Hosted runner"), + Image: &HostedRunnerImage{ ID: "ubuntu-latest", Source: "github", Version: "latest", }, - RunnerGroupID: 1, - Size: "4-core", - ImageVersion: "1.0.0", - MaximumRunners: 50, - EnableStaticIP: false, + RunnerGroupID: Ptr(int64(1)), + Size: Ptr("4-core"), + ImageVersion: Ptr("1.0.0"), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), }, expectedError: "validation failed: imageVersion should not be set directly; use the Image struct to specify image details", }, @@ -726,11 +726,11 @@ func TestEnterpriseService_UpdateHostedRunner(t *testing.T) { // Test for a valid update without `Size` ctx := t.Context() validReq := HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), } hostedRunner, _, err := client.Enterprise.UpdateHostedRunner(ctx, "o", 23, validReq) if err != nil { @@ -778,24 +778,24 @@ func TestEnterpriseService_UpdateHostedRunner(t *testing.T) { { name: "Size Set in Update Request", request: HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", - Size: "4-core", // Should cause validation error + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), + Size: Ptr("4-core"), // Should cause validation error }, expectedError: "validation failed: size cannot be updated, API does not support updating size", }, { name: "Image Set in Update Request", request: HostedRunnerRequest{ - Name: "My larger runner", - RunnerGroupID: 1, - MaximumRunners: 50, - EnableStaticIP: false, - ImageVersion: "1.0.0", - Image: HostedRunnerImage{ // Should cause validation error + Name: Ptr("My larger runner"), + RunnerGroupID: Ptr(int64(1)), + MaximumRunners: Ptr(int64(50)), + EnableStaticIP: Ptr(false), + ImageVersion: Ptr("1.0.0"), + Image: &HostedRunnerImage{ // Should cause validation error ID: "ubuntu-latest", Source: "github", Version: "latest", diff --git a/github/enterprise_rules_test.go b/github/enterprise_rules_test.go index 4e1bfcd235f..54442ccb283 100644 --- a/github/enterprise_rules_test.go +++ b/github/enterprise_rules_test.go @@ -202,7 +202,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgNameRepoName(t *testing.T) Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -303,7 +303,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgNameRepoName(t *testing.T) Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -592,7 +592,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgNameRepoProperty(t *testin Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -703,7 +703,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgNameRepoProperty(t *testin Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -966,7 +966,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgIdRepoName(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -1066,7 +1066,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgIdRepoName(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -1348,7 +1348,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgIdRepoProperty(t *testing. Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -1458,7 +1458,7 @@ func TestEnterpriseService_CreateRepositoryRuleset_OrgIdRepoProperty(t *testing. Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, diff --git a/github/git_tags.go b/github/git_tags.go index 750b03760c0..5ff01507f75 100644 --- a/github/git_tags.go +++ b/github/git_tags.go @@ -24,10 +24,10 @@ type Tag struct { // CreateTag represents the payload for creating a tag. type CreateTag struct { - Tag string `json:"tag,omitempty"` - Message string `json:"message,omitempty"` - Object string `json:"object,omitempty"` - Type string `json:"type,omitempty"` + Tag *string `json:"tag,omitempty"` + Message *string `json:"message,omitempty"` + Object *string `json:"object,omitempty"` + Type *string `json:"type,omitempty"` Tagger *CommitAuthor `json:"tagger,omitempty"` } diff --git a/github/git_tags_test.go b/github/git_tags_test.go index 36bb5ca0bbe..252ad61ae79 100644 --- a/github/git_tags_test.go +++ b/github/git_tags_test.go @@ -54,10 +54,10 @@ func TestGitService_CreateTag(t *testing.T) { client, mux, _ := setup(t) inputTag := CreateTag{ - Tag: "t", - Object: "s", - Type: "commit", - Message: "test message", + Tag: Ptr("t"), + Object: Ptr("s"), + Type: Ptr("commit"), + Message: Ptr("test message"), } mux.HandleFunc("/repos/o/r/git/tags", func(w http.ResponseWriter, r *http.Request) { @@ -160,10 +160,10 @@ func TestCreateTag_Marshal(t *testing.T) { testJSONMarshal(t, CreateTag{}, "{}") u := CreateTag{ - Tag: "tag", - Message: "msg", - Object: "obj", - Type: "type", + Tag: Ptr("tag"), + Message: Ptr("msg"), + Object: Ptr("obj"), + Type: Ptr("type"), Tagger: &CommitAuthor{ Date: &Timestamp{referenceTime}, Name: Ptr("name"), diff --git a/github/git_trees.go b/github/git_trees.go index 2b701a3c658..ddedea25e1d 100644 --- a/github/git_trees.go +++ b/github/git_trees.go @@ -119,8 +119,8 @@ func (s *GitService) GetTree(ctx context.Context, owner, repo, sha string, recur // createTree represents the body of a CreateTree request. type createTree struct { - BaseTree string `json:"base_tree,omitempty"` - Entries []any `json:"tree"` + BaseTree *string `json:"base_tree,omitempty"` + Entries []any `json:"tree"` } // CreateTree creates a new tree in a repository. If both a tree and a nested @@ -148,8 +148,12 @@ func (s *GitService) CreateTree(ctx context.Context, owner, repo, baseTree strin newEntries = append(newEntries, entry) } + var baseTreePtr *string + if baseTree != "" { + baseTreePtr = &baseTree + } body := &createTree{ - BaseTree: baseTree, + BaseTree: baseTreePtr, Entries: newEntries, } req, err := s.client.NewRequest("POST", u, body) diff --git a/github/git_trees_test.go b/github/git_trees_test.go index 54015739f24..223725d1f6f 100644 --- a/github/git_trees_test.go +++ b/github/git_trees_test.go @@ -439,7 +439,7 @@ func TestCreateTree_Marshal(t *testing.T) { testJSONMarshal(t, &createTree{}, "{}") u := &createTree{ - BaseTree: "bt", + BaseTree: Ptr("bt"), Entries: []any{"e"}, } diff --git a/github/github-accessors.go b/github/github-accessors.go index fca9145b2ec..768301cea90 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -766,6 +766,14 @@ func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { return *a.VerifiablePasswordAuthentication } +// GetTrustDomain returns the TrustDomain field if it's non-nil, zero value otherwise. +func (a *APIMetaArtifactAttestations) GetTrustDomain() string { + if a == nil || a.TrustDomain == nil { + return "" + } + return *a.TrustDomain +} + // GetArtifactAttestations returns the ArtifactAttestations field. func (a *APIMetaDomains) GetArtifactAttestations() *APIMetaArtifactAttestations { if a == nil { @@ -6446,6 +6454,30 @@ func (c *CreateRunnerGroupRequest) GetVisibility() string { return *c.Visibility } +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *CreateTag) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetObject returns the Object field if it's non-nil, zero value otherwise. +func (c *CreateTag) GetObject() string { + if c == nil || c.Object == nil { + return "" + } + return *c.Object +} + +// GetTag returns the Tag field if it's non-nil, zero value otherwise. +func (c *CreateTag) GetTag() string { + if c == nil || c.Tag == nil { + return "" + } + return *c.Tag +} + // GetTagger returns the Tagger field. func (c *CreateTag) GetTagger() *CommitAuthor { if c == nil { @@ -6454,6 +6486,14 @@ func (c *CreateTag) GetTagger() *CommitAuthor { return c.Tagger } +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *CreateTag) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + // GetCanAdminsBypass returns the CanAdminsBypass field if it's non-nil, zero value otherwise. func (c *CreateUpdateEnvironment) GetCanAdminsBypass() bool { if c == nil || c.CanAdminsBypass == nil { @@ -7318,6 +7358,22 @@ func (d *DependabotAlertState) GetDismissedReason() string { return *d.DismissedReason } +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (d *DependabotEncryptedSecret) GetSelectedRepositoryIDs() *DependabotSecretsSelectedRepoIDs { + if d == nil { + return nil + } + return d.SelectedRepositoryIDs +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (d *DependabotEncryptedSecret) GetVisibility() string { + if d == nil || d.Visibility == nil { + return "" + } + return *d.Visibility +} + // GetCVEID returns the CVEID field if it's non-nil, zero value otherwise. func (d *DependabotSecurityAdvisory) GetCVEID() string { if d == nil || d.CVEID == nil { @@ -9038,6 +9094,22 @@ func (e *EditTitle) GetFrom() string { return *e.From } +// GetSelectedRepositoryIDs returns the SelectedRepositoryIDs field. +func (e *EncryptedSecret) GetSelectedRepositoryIDs() *SelectedRepoIDs { + if e == nil { + return nil + } + return e.SelectedRepositoryIDs +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (e *EncryptedSecret) GetVisibility() string { + if e == nil || e.Visibility == nil { + return "" + } + return *e.Visibility +} + // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (e *Enterprise) GetAvatarURL() string { if e == nil || e.AvatarURL == nil { @@ -10926,6 +10998,62 @@ func (h *HostedRunnerPublicIPLimits) GetPublicIPs() *PublicIPUsage { return h.PublicIPs } +// GetEnableStaticIP returns the EnableStaticIP field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetEnableStaticIP() bool { + if h == nil || h.EnableStaticIP == nil { + return false + } + return *h.EnableStaticIP +} + +// GetImage returns the Image field. +func (h *HostedRunnerRequest) GetImage() *HostedRunnerImage { + if h == nil { + return nil + } + return h.Image +} + +// GetImageVersion returns the ImageVersion field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetImageVersion() string { + if h == nil || h.ImageVersion == nil { + return "" + } + return *h.ImageVersion +} + +// GetMaximumRunners returns the MaximumRunners field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetMaximumRunners() int64 { + if h == nil || h.MaximumRunners == nil { + return 0 + } + return *h.MaximumRunners +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetRunnerGroupID() int64 { + if h == nil || h.RunnerGroupID == nil { + return 0 + } + return *h.RunnerGroupID +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (h *HostedRunnerRequest) GetSize() string { + if h == nil || h.Size == nil { + return "" + } + return *h.Size +} + // GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. func (i *IDPGroup) GetGroupDescription() string { if i == nil || i.GroupDescription == nil { @@ -12654,6 +12782,14 @@ func (i *IssueCommentEvent) GetSender() *User { return i.Sender } +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + // GetActor returns the Actor field. func (i *IssueEvent) GetActor() *User { if i == nil { @@ -14190,6 +14326,14 @@ func (l *LockBranch) GetEnabled() bool { return *l.Enabled } +// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. +func (l *LockIssueOptions) GetLockReason() string { + if l == nil || l.LockReason == nil { + return "" + } + return *l.LockReason +} + // GetHostname returns the Hostname field if it's non-nil, zero value otherwise. func (m *MaintenanceOperationStatus) GetHostname() string { if m == nil || m.Hostname == nil { @@ -23238,6 +23382,14 @@ func (r *RepositoryActor) GetUserViewType() string { return *r.UserViewType } +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (r *RepositoryAddCollaboratorOptions) GetPermission() string { + if r == nil || r.Permission == nil { + return "" + } + return *r.Permission +} + // GetRepository returns the Repository field. func (r *RepositoryAttachment) GetRepository() *Repository { if r == nil { @@ -23574,6 +23726,14 @@ func (r *RepositoryContentFileOptions) GetSHA() string { return *r.SHA } +// GetCommit returns the Commit field. +func (r *RepositoryContentResponse) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + // GetContent returns the Content field. func (r *RepositoryContentResponse) GetContent() *RepositoryContent { if r == nil { @@ -23582,6 +23742,30 @@ func (r *RepositoryContentResponse) GetContent() *RepositoryContent { return r.Content } +// GetDefaultBranchOnly returns the DefaultBranchOnly field if it's non-nil, zero value otherwise. +func (r *RepositoryCreateForkOptions) GetDefaultBranchOnly() bool { + if r == nil || r.DefaultBranchOnly == nil { + return false + } + return *r.DefaultBranchOnly +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryCreateForkOptions) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. +func (r *RepositoryCreateForkOptions) GetOrganization() string { + if r == nil || r.Organization == nil { + return "" + } + return *r.Organization +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (r *RepositoryDispatchEvent) GetAction() string { if r == nil || r.Action == nil { @@ -25806,6 +25990,22 @@ func (s *SCIMUserRole) GetType() string { return *s.Type } +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (s *Secret) GetSelectedRepositoriesURL() string { + if s == nil || s.SelectedRepositoriesURL == nil { + return "" + } + return *s.SelectedRepositoriesURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (s *Secret) GetVisibility() string { + if s == nil || s.Visibility == nil { + return "" + } + return *s.Visibility +} + // GetStatus returns the Status field if it's non-nil, zero value otherwise. func (s *SecretScanning) GetStatus() string { if s == nil || s.Status == nil { @@ -27750,6 +27950,22 @@ func (t *TeamAddEvent) GetTeam() *Team { return t.Team } +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (t *TeamAddTeamMembershipOptions) GetRole() string { + if t == nil || t.Role == nil { + return "" + } + return *t.Role +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamAddTeamRepoOptions) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + // GetDescription returns the Description field. func (t *TeamChange) GetDescription() *TeamDescription { if t == nil { @@ -28838,6 +29054,14 @@ func (u *UpdateRef) GetForce() bool { return *u.Force } +// GetUpdateAllowsFetchAndMerge returns the UpdateAllowsFetchAndMerge field if it's non-nil, zero value otherwise. +func (u *UpdateRuleParameters) GetUpdateAllowsFetchAndMerge() bool { + if u == nil || u.UpdateAllowsFetchAndMerge == nil { + return false + } + return *u.UpdateAllowsFetchAndMerge +} + // GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. func (u *UpdateRunnerGroupRequest) GetAllowsPublicRepositories() bool { if u == nil || u.AllowsPublicRepositories == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index ba42d9ba0c9..aac7ccd35c8 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -980,6 +980,17 @@ func TestAPIMeta_GetVerifiablePasswordAuthentication(tt *testing.T) { a.GetVerifiablePasswordAuthentication() } +func TestAPIMetaArtifactAttestations_GetTrustDomain(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &APIMetaArtifactAttestations{TrustDomain: &zeroValue} + a.GetTrustDomain() + a = &APIMetaArtifactAttestations{} + a.GetTrustDomain() + a = nil + a.GetTrustDomain() +} + func TestAPIMetaDomains_GetArtifactAttestations(tt *testing.T) { tt.Parallel() a := &APIMetaDomains{} @@ -8421,6 +8432,39 @@ func TestCreateRunnerGroupRequest_GetVisibility(tt *testing.T) { c.GetVisibility() } +func TestCreateTag_GetMessage(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateTag{Message: &zeroValue} + c.GetMessage() + c = &CreateTag{} + c.GetMessage() + c = nil + c.GetMessage() +} + +func TestCreateTag_GetObject(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateTag{Object: &zeroValue} + c.GetObject() + c = &CreateTag{} + c.GetObject() + c = nil + c.GetObject() +} + +func TestCreateTag_GetTag(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateTag{Tag: &zeroValue} + c.GetTag() + c = &CreateTag{} + c.GetTag() + c = nil + c.GetTag() +} + func TestCreateTag_GetTagger(tt *testing.T) { tt.Parallel() c := &CreateTag{} @@ -8429,6 +8473,17 @@ func TestCreateTag_GetTagger(tt *testing.T) { c.GetTagger() } +func TestCreateTag_GetType(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateTag{Type: &zeroValue} + c.GetType() + c = &CreateTag{} + c.GetType() + c = nil + c.GetType() +} + func TestCreateUpdateEnvironment_GetCanAdminsBypass(tt *testing.T) { tt.Parallel() var zeroValue bool @@ -9527,6 +9582,25 @@ func TestDependabotAlertState_GetDismissedReason(tt *testing.T) { d.GetDismissedReason() } +func TestDependabotEncryptedSecret_GetSelectedRepositoryIDs(tt *testing.T) { + tt.Parallel() + d := &DependabotEncryptedSecret{} + d.GetSelectedRepositoryIDs() + d = nil + d.GetSelectedRepositoryIDs() +} + +func TestDependabotEncryptedSecret_GetVisibility(tt *testing.T) { + tt.Parallel() + var zeroValue string + d := &DependabotEncryptedSecret{Visibility: &zeroValue} + d.GetVisibility() + d = &DependabotEncryptedSecret{} + d.GetVisibility() + d = nil + d.GetVisibility() +} + func TestDependabotSecurityAdvisory_GetCVEID(tt *testing.T) { tt.Parallel() var zeroValue string @@ -11694,6 +11768,25 @@ func TestEditTitle_GetFrom(tt *testing.T) { e.GetFrom() } +func TestEncryptedSecret_GetSelectedRepositoryIDs(tt *testing.T) { + tt.Parallel() + e := &EncryptedSecret{} + e.GetSelectedRepositoryIDs() + e = nil + e.GetSelectedRepositoryIDs() +} + +func TestEncryptedSecret_GetVisibility(tt *testing.T) { + tt.Parallel() + var zeroValue string + e := &EncryptedSecret{Visibility: &zeroValue} + e.GetVisibility() + e = &EncryptedSecret{} + e.GetVisibility() + e = nil + e.GetVisibility() +} + func TestEnterprise_GetAvatarURL(tt *testing.T) { tt.Parallel() var zeroValue string @@ -14173,6 +14266,80 @@ func TestHostedRunnerPublicIPLimits_GetPublicIPs(tt *testing.T) { h.GetPublicIPs() } +func TestHostedRunnerRequest_GetEnableStaticIP(tt *testing.T) { + tt.Parallel() + var zeroValue bool + h := &HostedRunnerRequest{EnableStaticIP: &zeroValue} + h.GetEnableStaticIP() + h = &HostedRunnerRequest{} + h.GetEnableStaticIP() + h = nil + h.GetEnableStaticIP() +} + +func TestHostedRunnerRequest_GetImage(tt *testing.T) { + tt.Parallel() + h := &HostedRunnerRequest{} + h.GetImage() + h = nil + h.GetImage() +} + +func TestHostedRunnerRequest_GetImageVersion(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerRequest{ImageVersion: &zeroValue} + h.GetImageVersion() + h = &HostedRunnerRequest{} + h.GetImageVersion() + h = nil + h.GetImageVersion() +} + +func TestHostedRunnerRequest_GetMaximumRunners(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + h := &HostedRunnerRequest{MaximumRunners: &zeroValue} + h.GetMaximumRunners() + h = &HostedRunnerRequest{} + h.GetMaximumRunners() + h = nil + h.GetMaximumRunners() +} + +func TestHostedRunnerRequest_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerRequest{Name: &zeroValue} + h.GetName() + h = &HostedRunnerRequest{} + h.GetName() + h = nil + h.GetName() +} + +func TestHostedRunnerRequest_GetRunnerGroupID(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + h := &HostedRunnerRequest{RunnerGroupID: &zeroValue} + h.GetRunnerGroupID() + h = &HostedRunnerRequest{} + h.GetRunnerGroupID() + h = nil + h.GetRunnerGroupID() +} + +func TestHostedRunnerRequest_GetSize(tt *testing.T) { + tt.Parallel() + var zeroValue string + h := &HostedRunnerRequest{Size: &zeroValue} + h.GetSize() + h = &HostedRunnerRequest{} + h.GetSize() + h = nil + h.GetSize() +} + func TestIDPGroup_GetGroupDescription(tt *testing.T) { tt.Parallel() var zeroValue string @@ -16423,6 +16590,17 @@ func TestIssueCommentEvent_GetSender(tt *testing.T) { i.GetSender() } +func TestIssueEvent_GetAction(tt *testing.T) { + tt.Parallel() + var zeroValue string + i := &IssueEvent{Action: &zeroValue} + i.GetAction() + i = &IssueEvent{} + i.GetAction() + i = nil + i.GetAction() +} + func TestIssueEvent_GetActor(tt *testing.T) { tt.Parallel() i := &IssueEvent{} @@ -18442,6 +18620,17 @@ func TestLockBranch_GetEnabled(tt *testing.T) { l.GetEnabled() } +func TestLockIssueOptions_GetLockReason(tt *testing.T) { + tt.Parallel() + var zeroValue string + l := &LockIssueOptions{LockReason: &zeroValue} + l.GetLockReason() + l = &LockIssueOptions{} + l.GetLockReason() + l = nil + l.GetLockReason() +} + func TestMaintenanceOperationStatus_GetHostname(tt *testing.T) { tt.Parallel() var zeroValue string @@ -30055,6 +30244,17 @@ func TestRepositoryActor_GetUserViewType(tt *testing.T) { r.GetUserViewType() } +func TestRepositoryAddCollaboratorOptions_GetPermission(tt *testing.T) { + tt.Parallel() + var zeroValue string + r := &RepositoryAddCollaboratorOptions{Permission: &zeroValue} + r.GetPermission() + r = &RepositoryAddCollaboratorOptions{} + r.GetPermission() + r = nil + r.GetPermission() +} + func TestRepositoryAttachment_GetRepository(tt *testing.T) { tt.Parallel() r := &RepositoryAttachment{} @@ -30487,6 +30687,14 @@ func TestRepositoryContentFileOptions_GetSHA(tt *testing.T) { r.GetSHA() } +func TestRepositoryContentResponse_GetCommit(tt *testing.T) { + tt.Parallel() + r := &RepositoryContentResponse{} + r.GetCommit() + r = nil + r.GetCommit() +} + func TestRepositoryContentResponse_GetContent(tt *testing.T) { tt.Parallel() r := &RepositoryContentResponse{} @@ -30495,6 +30703,39 @@ func TestRepositoryContentResponse_GetContent(tt *testing.T) { r.GetContent() } +func TestRepositoryCreateForkOptions_GetDefaultBranchOnly(tt *testing.T) { + tt.Parallel() + var zeroValue bool + r := &RepositoryCreateForkOptions{DefaultBranchOnly: &zeroValue} + r.GetDefaultBranchOnly() + r = &RepositoryCreateForkOptions{} + r.GetDefaultBranchOnly() + r = nil + r.GetDefaultBranchOnly() +} + +func TestRepositoryCreateForkOptions_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + r := &RepositoryCreateForkOptions{Name: &zeroValue} + r.GetName() + r = &RepositoryCreateForkOptions{} + r.GetName() + r = nil + r.GetName() +} + +func TestRepositoryCreateForkOptions_GetOrganization(tt *testing.T) { + tt.Parallel() + var zeroValue string + r := &RepositoryCreateForkOptions{Organization: &zeroValue} + r.GetOrganization() + r = &RepositoryCreateForkOptions{} + r.GetOrganization() + r = nil + r.GetOrganization() +} + func TestRepositoryDispatchEvent_GetAction(tt *testing.T) { tt.Parallel() var zeroValue string @@ -33289,6 +33530,28 @@ func TestSCIMUserRole_GetType(tt *testing.T) { s.GetType() } +func TestSecret_GetSelectedRepositoriesURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + s := &Secret{SelectedRepositoriesURL: &zeroValue} + s.GetSelectedRepositoriesURL() + s = &Secret{} + s.GetSelectedRepositoriesURL() + s = nil + s.GetSelectedRepositoriesURL() +} + +func TestSecret_GetVisibility(tt *testing.T) { + tt.Parallel() + var zeroValue string + s := &Secret{Visibility: &zeroValue} + s.GetVisibility() + s = &Secret{} + s.GetVisibility() + s = nil + s.GetVisibility() +} + func TestSecretScanning_GetStatus(tt *testing.T) { tt.Parallel() var zeroValue string @@ -35737,6 +36000,28 @@ func TestTeamAddEvent_GetTeam(tt *testing.T) { t.GetTeam() } +func TestTeamAddTeamMembershipOptions_GetRole(tt *testing.T) { + tt.Parallel() + var zeroValue string + t := &TeamAddTeamMembershipOptions{Role: &zeroValue} + t.GetRole() + t = &TeamAddTeamMembershipOptions{} + t.GetRole() + t = nil + t.GetRole() +} + +func TestTeamAddTeamRepoOptions_GetPermission(tt *testing.T) { + tt.Parallel() + var zeroValue string + t := &TeamAddTeamRepoOptions{Permission: &zeroValue} + t.GetPermission() + t = &TeamAddTeamRepoOptions{} + t.GetPermission() + t = nil + t.GetPermission() +} + func TestTeamChange_GetDescription(tt *testing.T) { tt.Parallel() t := &TeamChange{} @@ -37143,6 +37428,17 @@ func TestUpdateRef_GetForce(tt *testing.T) { u.GetForce() } +func TestUpdateRuleParameters_GetUpdateAllowsFetchAndMerge(tt *testing.T) { + tt.Parallel() + var zeroValue bool + u := &UpdateRuleParameters{UpdateAllowsFetchAndMerge: &zeroValue} + u.GetUpdateAllowsFetchAndMerge() + u = &UpdateRuleParameters{} + u.GetUpdateAllowsFetchAndMerge() + u = nil + u.GetUpdateAllowsFetchAndMerge() +} + func TestUpdateRunnerGroupRequest_GetAllowsPublicRepositories(tt *testing.T) { tt.Parallel() var zeroValue bool diff --git a/github/github.go b/github/github.go index 5a7488fc7e4..d2d2676995c 100644 --- a/github/github.go +++ b/github/github.go @@ -1156,14 +1156,14 @@ type ErrorResponse struct { // Most errors will also include a documentation_url field pointing // to some content that might help you resolve the error, see // https://docs.github.com/rest/#client-errors - DocumentationURL string `json:"documentation_url,omitempty"` + DocumentationURL string `json:"documentation_url,omitempty"` //nolint:sliceofpointers } // ErrorBlock contains a further explanation for the reason of an error. // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ // for more information. type ErrorBlock struct { - Reason string `json:"reason,omitempty"` + Reason string `json:"reason,omitempty"` //nolint:sliceofpointers CreatedAt *Timestamp `json:"created_at,omitempty"` } diff --git a/github/issues.go b/github/issues.go index 6de04708dc8..209ffeda017 100644 --- a/github/issues.go +++ b/github/issues.go @@ -377,7 +377,7 @@ type LockIssueOptions struct { // LockReason specifies the reason to lock this issue. // Providing a lock reason can help make it clearer to contributors why an issue // was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam". - LockReason string `json:"lock_reason,omitempty"` + LockReason *string `json:"lock_reason,omitempty"` } // Lock an issue's conversation. diff --git a/github/issues_events.go b/github/issues_events.go index 8e234d7e020..19cb1b41fae 100644 --- a/github/issues_events.go +++ b/github/issues_events.go @@ -19,7 +19,7 @@ type IssueEvent struct { Actor *User `json:"actor,omitempty"` // The action corresponding to the event. - Action string `json:"action,omitempty"` + Action *string `json:"action,omitempty"` // Event identifies the actual type of Event that occurred. Possible // values are: diff --git a/github/issues_test.go b/github/issues_test.go index a859fd7c9ec..1f981b7e163 100644 --- a/github/issues_test.go +++ b/github/issues_test.go @@ -443,7 +443,7 @@ func TestIssuesService_LockWithReason(t *testing.T) { w.WriteHeader(http.StatusNoContent) }) - opt := &LockIssueOptions{LockReason: "off-topic"} + opt := &LockIssueOptions{LockReason: Ptr("off-topic")} ctx := t.Context() if _, err := client.Issues.Lock(ctx, "o", "r", 1, opt); err != nil { @@ -494,7 +494,7 @@ func TestLockIssueOptions_Marshal(t *testing.T) { testJSONMarshal(t, &LockIssueOptions{}, "{}") u := &LockIssueOptions{ - LockReason: "lr", + LockReason: Ptr("lr"), } want := `{ diff --git a/github/meta.go b/github/meta.go index 92c4bcff6f9..710d7273908 100644 --- a/github/meta.go +++ b/github/meta.go @@ -91,7 +91,7 @@ type APIMetaDomains struct { // APIMetaArtifactAttestations represents the artifact attestation services domains. type APIMetaArtifactAttestations struct { - TrustDomain string `json:"trust_domain,omitempty"` + TrustDomain *string `json:"trust_domain,omitempty"` Services []string `json:"services,omitempty"` } diff --git a/github/meta_test.go b/github/meta_test.go index 7b0a8c86a8c..cb496041183 100644 --- a/github/meta_test.go +++ b/github/meta_test.go @@ -40,7 +40,7 @@ func TestAPIMeta_Marshal(t *testing.T) { "*.githubusercontent.com", }, ArtifactAttestations: &APIMetaArtifactAttestations{ - TrustDomain: "", + TrustDomain: Ptr(""), Services: []string{ "*.actions.githubusercontent.com", "tuf-repo.github.com", @@ -105,7 +105,7 @@ func TestMetaService_Get(t *testing.T) { "*.githubusercontent.com", }, ArtifactAttestations: &APIMetaArtifactAttestations{ - TrustDomain: "", + TrustDomain: Ptr(""), Services: []string{ "*.actions.githubusercontent.com", "tuf-repo.github.com", diff --git a/github/orgs_rules_test.go b/github/orgs_rules_test.go index 1086aae83f2..79e5d31d5d5 100644 --- a/github/orgs_rules_test.go +++ b/github/orgs_rules_test.go @@ -298,7 +298,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoNames(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -400,7 +400,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoNames(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -663,7 +663,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoProperty(t *testing.T) Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -766,7 +766,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoProperty(t *testing.T) Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -1014,7 +1014,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoIDs(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, @@ -1109,7 +1109,7 @@ func TestOrganizationsService_CreateRepositoryRuleset_RepoIDs(t *testing.T) { Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ - UpdateAllowsFetchAndMerge: true, + UpdateAllowsFetchAndMerge: Ptr(true), }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, diff --git a/github/pulls.go b/github/pulls.go index a490feb5785..f6486024f10 100644 --- a/github/pulls.go +++ b/github/pulls.go @@ -485,9 +485,9 @@ type PullRequestOptions struct { type pullRequestMergeRequest struct { CommitMessage *string `json:"commit_message,omitempty"` - CommitTitle string `json:"commit_title,omitempty"` - MergeMethod string `json:"merge_method,omitempty"` - SHA string `json:"sha,omitempty"` + CommitTitle *string `json:"commit_title,omitempty"` + MergeMethod *string `json:"merge_method,omitempty"` + SHA *string `json:"sha,omitempty"` } // Merge a pull request. @@ -504,9 +504,15 @@ func (s *PullRequestsService) Merge(ctx context.Context, owner, repo string, num pullRequestBody.CommitMessage = &commitMessage } if options != nil { - pullRequestBody.CommitTitle = options.CommitTitle - pullRequestBody.MergeMethod = options.MergeMethod - pullRequestBody.SHA = options.SHA + if options.CommitTitle != "" { + pullRequestBody.CommitTitle = &options.CommitTitle + } + if options.MergeMethod != "" { + pullRequestBody.MergeMethod = &options.MergeMethod + } + if options.SHA != "" { + pullRequestBody.SHA = &options.SHA + } if options.DontDefaultIfBlank && commitMessage == "" { pullRequestBody.CommitMessage = &commitMessage } diff --git a/github/pulls_comments.go b/github/pulls_comments.go index 0c495c5965b..ef49b240b60 100644 --- a/github/pulls_comments.go +++ b/github/pulls_comments.go @@ -163,11 +163,11 @@ func (s *PullRequestsService) CreateComment(ctx context.Context, owner, repo str //meta:operation POST /repos/{owner}/{repo}/pulls/{pull_number}/comments func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { comment := &struct { - Body string `json:"body,omitempty"` - InReplyTo int64 `json:"in_reply_to,omitempty"` + Body *string `json:"body,omitempty"` + InReplyTo *int64 `json:"in_reply_to,omitempty"` }{ - Body: body, - InReplyTo: commentID, + Body: &body, + InReplyTo: &commentID, } u := fmt.Sprintf("repos/%v/%v/pulls/%v/comments", owner, repo, number) req, err := s.client.NewRequest("POST", u, comment) diff --git a/github/pulls_test.go b/github/pulls_test.go index ea724cd5d6e..7261944b0a1 100644 --- a/github/pulls_test.go +++ b/github/pulls_test.go @@ -844,9 +844,9 @@ func TestPullRequestMergeRequest_Marshal(t *testing.T) { u := &pullRequestMergeRequest{ CommitMessage: Ptr("cm"), - CommitTitle: "ct", - MergeMethod: "mm", - SHA: "sha", + CommitTitle: Ptr("ct"), + MergeMethod: Ptr("mm"), + SHA: Ptr("sha"), } want := `{ diff --git a/github/rate_limit.go b/github/rate_limit.go index 6236eba8fbb..df4982b09ae 100644 --- a/github/rate_limit.go +++ b/github/rate_limit.go @@ -27,7 +27,7 @@ type Rate struct { // The rate limit resource that the request counted against. // For more information about the different resources, see REST API endpoints for rate limits. // GitHub API docs: https://docs.github.com/en/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user - Resource string `json:"resource,omitempty"` + Resource string `json:"resource,omitempty"` //nolint:sliceofpointers } func (r Rate) String() string { diff --git a/github/repos.go b/github/repos.go index 5388e8a87e9..9bc23edb4fa 100644 --- a/github/repos.go +++ b/github/repos.go @@ -2417,7 +2417,7 @@ func (s *RepositoriesService) DisablePrivateReporting(ctx context.Context, owner // checkPrivateReporting represents whether private vulnerability reporting is enabled. type checkPrivateReporting struct { - Enabled bool `json:"enabled,omitempty"` + Enabled *bool `json:"enabled,omitempty"` } // IsPrivateReportingEnabled checks if private vulnerability reporting is enabled @@ -2436,7 +2436,10 @@ func (s *RepositoriesService) IsPrivateReportingEnabled(ctx context.Context, own privateReporting := new(checkPrivateReporting) resp, err := s.client.Do(ctx, req, privateReporting) - return privateReporting.Enabled, resp, err + if privateReporting.Enabled != nil { + return *privateReporting.Enabled, resp, err + } + return false, resp, err } // ListRepositoryActivityOptions specifies the optional parameters to the diff --git a/github/repos_collaborators.go b/github/repos_collaborators.go index d6c985359aa..e173253dc35 100644 --- a/github/repos_collaborators.go +++ b/github/repos_collaborators.go @@ -136,7 +136,7 @@ type RepositoryAddCollaboratorOptions struct { // triage - team members can proactively manage issues and pull requests without write access. // // Default value is "push". This option is only valid for organization-owned repositories. - Permission string `json:"permission,omitempty"` + Permission *string `json:"permission,omitempty"` } // AddCollaborator sends an invitation to the specified GitHub user diff --git a/github/repos_collaborators_test.go b/github/repos_collaborators_test.go index f93c415bcc8..70da7856161 100644 --- a/github/repos_collaborators_test.go +++ b/github/repos_collaborators_test.go @@ -264,7 +264,7 @@ func TestRepositoriesService_AddCollaborator(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &RepositoryAddCollaboratorOptions{Permission: "admin"} + opt := &RepositoryAddCollaboratorOptions{Permission: Ptr("admin")} mux.HandleFunc("/repos/o/r/collaborators/u", func(w http.ResponseWriter, r *http.Request) { v := new(RepositoryAddCollaboratorOptions) assertNilError(t, json.NewDecoder(r.Body).Decode(v)) @@ -366,7 +366,7 @@ func TestRepositoryAddCollaboratorOptions_Marshal(t *testing.T) { testJSONMarshal(t, &RepositoryAddCollaboratorOptions{}, "{}") r := &RepositoryAddCollaboratorOptions{ - Permission: "permission", + Permission: Ptr("permission"), } want := `{ diff --git a/github/repos_contents.go b/github/repos_contents.go index 2378cd2330e..ff1da2f3b6e 100644 --- a/github/repos_contents.go +++ b/github/repos_contents.go @@ -48,7 +48,7 @@ type RepositoryContent struct { // RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. type RepositoryContentResponse struct { Content *RepositoryContent `json:"content,omitempty"` - Commit `json:"commit,omitempty"` + Commit *Commit `json:"commit,omitempty"` } // RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. diff --git a/github/repos_contents_test.go b/github/repos_contents_test.go index ed782da8701..faeec85efb8 100644 --- a/github/repos_contents_test.go +++ b/github/repos_contents_test.go @@ -732,7 +732,7 @@ func TestRepositoriesService_CreateFile(t *testing.T) { } want := &RepositoryContentResponse{ Content: &RepositoryContent{Name: Ptr("p")}, - Commit: Commit{ + Commit: &Commit{ Message: Ptr("m"), SHA: Ptr("f5f369044773ff9c6383c087466d12adb6fa0828"), }, @@ -788,7 +788,7 @@ func TestRepositoriesService_UpdateFile(t *testing.T) { } want := &RepositoryContentResponse{ Content: &RepositoryContent{Name: Ptr("p")}, - Commit: Commit{ + Commit: &Commit{ Message: Ptr("m"), SHA: Ptr("f5f369044773ff9c6383c087466d12adb6fa0828"), }, @@ -840,7 +840,7 @@ func TestRepositoriesService_DeleteFile(t *testing.T) { } want := &RepositoryContentResponse{ Content: nil, - Commit: Commit{ + Commit: &Commit{ Message: Ptr("m"), SHA: Ptr("f5f369044773ff9c6383c087466d12adb6fa0828"), }, @@ -1084,7 +1084,7 @@ func TestRepositoryContentResponse_Marshal(t *testing.T) { DownloadURL: Ptr("durl"), SubmoduleGitURL: Ptr("smgurl"), }, - Commit: Commit{ + Commit: &Commit{ SHA: Ptr("s"), Author: &CommitAuthor{ Date: &Timestamp{referenceTime}, diff --git a/github/repos_forks.go b/github/repos_forks.go index 268233c37e0..2f0861c91a1 100644 --- a/github/repos_forks.go +++ b/github/repos_forks.go @@ -55,9 +55,9 @@ func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, // RepositoriesService.CreateFork method. type RepositoryCreateForkOptions struct { // The organization to fork the repository into. - Organization string `json:"organization,omitempty"` - Name string `json:"name,omitempty"` - DefaultBranchOnly bool `json:"default_branch_only,omitempty"` + Organization *string `json:"organization,omitempty"` + Name *string `json:"name,omitempty"` + DefaultBranchOnly *bool `json:"default_branch_only,omitempty"` } // CreateFork creates a fork of the specified repository. diff --git a/github/repos_forks_test.go b/github/repos_forks_test.go index bf67c7dc704..2287bcada25 100644 --- a/github/repos_forks_test.go +++ b/github/repos_forks_test.go @@ -77,7 +77,7 @@ func TestRepositoriesService_CreateFork(t *testing.T) { fmt.Fprint(w, `{"id":1}`) }) - opt := &RepositoryCreateForkOptions{Organization: "o", Name: "n", DefaultBranchOnly: true} + opt := &RepositoryCreateForkOptions{Organization: Ptr("o"), Name: Ptr("n"), DefaultBranchOnly: Ptr(true)} ctx := t.Context() repo, _, err := client.Repositories.CreateFork(ctx, "o", "r", opt) if err != nil { @@ -116,7 +116,7 @@ func TestRepositoriesService_CreateFork_deferred(t *testing.T) { fmt.Fprint(w, `{"id":1}`) }) - opt := &RepositoryCreateForkOptions{Organization: "o", Name: "n", DefaultBranchOnly: true} + opt := &RepositoryCreateForkOptions{Organization: Ptr("o"), Name: Ptr("n"), DefaultBranchOnly: Ptr(true)} ctx := t.Context() repo, _, err := client.Repositories.CreateFork(ctx, "o", "r", opt) if !errors.As(err, new(*AcceptedError)) { diff --git a/github/repos_rules_test.go b/github/repos_rules_test.go index 4b93d0bf14e..cf70260f8ba 100644 --- a/github/repos_rules_test.go +++ b/github/repos_rules_test.go @@ -46,7 +46,7 @@ func TestRepositoriesService_GetRulesForBranch(t *testing.T) { want := &BranchRules{ Creation: []*BranchRuleMetadata{{RulesetSourceType: RulesetSourceTypeRepository, RulesetSource: "google/a", RulesetID: 42069}}, - Update: []*UpdateBranchRule{{BranchRuleMetadata: BranchRuleMetadata{RulesetSourceType: RulesetSourceTypeOrganization, RulesetSource: "google", RulesetID: 42069}, Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: true}}}, + Update: []*UpdateBranchRule{{BranchRuleMetadata: BranchRuleMetadata{RulesetSourceType: RulesetSourceTypeOrganization, RulesetSource: "google", RulesetID: 42069}, Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: Ptr(true)}}}, } if !cmp.Equal(rules, want) { diff --git a/github/rules.go b/github/rules.go index 7b474f00e68..2469e30e570 100644 --- a/github/rules.go +++ b/github/rules.go @@ -395,7 +395,7 @@ type EmptyRuleParameters struct{} // UpdateRuleParameters represents the update rule parameters. type UpdateRuleParameters struct { - UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge,omitempty"` + UpdateAllowsFetchAndMerge *bool `json:"update_allows_fetch_and_merge,omitempty"` } // MergeQueueRuleParameters represents the merge_queue rule parameters. diff --git a/github/rules_test.go b/github/rules_test.go index 34a9f213ecd..4ad2b76736a 100644 --- a/github/rules_test.go +++ b/github/rules_test.go @@ -129,7 +129,7 @@ func TestRulesetRules(t *testing.T) { "all_rules_with_all_params", &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, - Update: &UpdateRuleParameters{UpdateAllowsFetchAndMerge: true}, + Update: &UpdateRuleParameters{UpdateAllowsFetchAndMerge: Ptr(true)}, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, MergeQueue: &MergeQueueRuleParameters{ @@ -321,7 +321,7 @@ func TestBranchRules(t *testing.T) { RulesetSource: "test/test", RulesetID: 1, }, - Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: true}, + Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: Ptr(true)}, }, }, }, @@ -344,7 +344,7 @@ func TestBranchRules(t *testing.T) { RulesetSource: "test/test", RulesetID: 1, }, - Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: true}, + Parameters: UpdateRuleParameters{UpdateAllowsFetchAndMerge: Ptr(true)}, }, }, Deletion: []*BranchRuleMetadata{ @@ -672,7 +672,7 @@ func TestRepositoryRule(t *testing.T) { "update_params_set", &RepositoryRule{ Type: RulesetRuleTypeUpdate, - Parameters: &UpdateRuleParameters{UpdateAllowsFetchAndMerge: true}, + Parameters: &UpdateRuleParameters{UpdateAllowsFetchAndMerge: Ptr(true)}, }, `{"type":"update","parameters":{"update_allows_fetch_and_merge":true}}`, }, diff --git a/github/teams.go b/github/teams.go index 2214dfe30d8..c3f6c573dbb 100644 --- a/github/teams.go +++ b/github/teams.go @@ -510,7 +510,7 @@ type TeamAddTeamRepoOptions struct { // triage - team members can proactively manage issues and pull requests without write access. // // If not specified, the team's permission attribute will be used. - Permission string `json:"permission,omitempty"` + Permission *string `json:"permission,omitempty"` } // AddTeamRepoByID adds a repository to be managed by the specified team given the team ID. diff --git a/github/teams_members.go b/github/teams_members.go index 059d993a3e6..ae4f1126d38 100644 --- a/github/teams_members.go +++ b/github/teams_members.go @@ -129,7 +129,7 @@ type TeamAddTeamMembershipOptions struct { // maintainer, and edit the team’s name and description // // Default value is "member". - Role string `json:"role,omitempty"` + Role *string `json:"role,omitempty"` } // AddTeamMembershipByID adds or invites a user to a team, given a specified diff --git a/github/teams_members_test.go b/github/teams_members_test.go index 38e2d54e054..4d989ea6d1b 100644 --- a/github/teams_members_test.go +++ b/github/teams_members_test.go @@ -328,7 +328,7 @@ func TestTeamsService__AddTeamMembershipByID(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamMembershipOptions{Role: "maintainer"} + opt := &TeamAddTeamMembershipOptions{Role: Ptr("maintainer")} mux.HandleFunc("/organizations/1/team/2/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamMembershipOptions) @@ -372,7 +372,7 @@ func TestTeamsService__AddTeamMembershipByID_notFound(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamMembershipOptions{Role: "maintainer"} + opt := &TeamAddTeamMembershipOptions{Role: Ptr("maintainer")} mux.HandleFunc("/organizations/1/team/2/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamMembershipOptions) @@ -417,7 +417,7 @@ func TestTeamsService__AddTeamMembershipBySlug(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamMembershipOptions{Role: "maintainer"} + opt := &TeamAddTeamMembershipOptions{Role: Ptr("maintainer")} mux.HandleFunc("/orgs/o/teams/s/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamMembershipOptions) @@ -461,7 +461,7 @@ func TestTeamsService__AddTeamMembershipBySlug_notFound(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamMembershipOptions{Role: "maintainer"} + opt := &TeamAddTeamMembershipOptions{Role: Ptr("maintainer")} mux.HandleFunc("/orgs/o/teams/s/memberships/u", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamMembershipOptions) @@ -794,7 +794,7 @@ func TestTeamAddTeamMembershipOptions_Marshal(t *testing.T) { testJSONMarshal(t, &TeamAddTeamMembershipOptions{}, "{}") u := &TeamAddTeamMembershipOptions{ - Role: "role", + Role: Ptr("role"), } want := `{ diff --git a/github/teams_test.go b/github/teams_test.go index 735d86c3a57..64e340e1efb 100644 --- a/github/teams_test.go +++ b/github/teams_test.go @@ -788,7 +788,7 @@ func TestTeamsService_AddTeamRepoByID(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamRepoOptions{Permission: "admin"} + opt := &TeamAddTeamRepoOptions{Permission: Ptr("admin")} mux.HandleFunc("/organizations/1/team/1/repos/owner/repo", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamRepoOptions) @@ -823,7 +823,7 @@ func TestTeamsService_AddTeamRepoBySlug(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - opt := &TeamAddTeamRepoOptions{Permission: "admin"} + opt := &TeamAddTeamRepoOptions{Permission: Ptr("admin")} mux.HandleFunc("/orgs/org/teams/slug/repos/owner/repo", func(w http.ResponseWriter, r *http.Request) { v := new(TeamAddTeamRepoOptions) @@ -2325,7 +2325,7 @@ func TestTeamAddTeamRepoOptions_Marshal(t *testing.T) { testJSONMarshal(t, &TeamAddTeamRepoOptions{}, "{}") u := &TeamAddTeamRepoOptions{ - Permission: "a", + Permission: Ptr("a"), } want := `{ From f052cd8d9f40304d9e2f1316967baac8807f3dcd Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 21:37:18 +0900 Subject: [PATCH 4/7] refactor: Rename sliceofpointers linter to gogithub and update references --- .custom-gcl.yml | 4 +-- .golangci.yml | 8 ++--- github/github.go | 8 +++-- github/rate_limit.go | 3 +- github/strings_test.go | 2 +- tools/{sliceofpointers => gogithub}/go.mod | 2 +- tools/{sliceofpointers => gogithub}/go.sum | 0 .../gogithub.go} | 35 +++++++++---------- .../gogithub_test.go} | 2 +- .../testdata/src/has-warnings/main.go | 0 .../testdata/src/no-warnings/main.go | 0 tools/metadata/metadata.go | 6 ++-- 12 files changed, 37 insertions(+), 33 deletions(-) rename tools/{sliceofpointers => gogithub}/go.mod (86%) rename tools/{sliceofpointers => gogithub}/go.sum (100%) rename tools/{sliceofpointers/sliceofpointers.go => gogithub/gogithub.go} (75%) rename tools/{sliceofpointers/sliceofpointers_test.go => gogithub/gogithub_test.go} (95%) rename tools/{sliceofpointers => gogithub}/testdata/src/has-warnings/main.go (100%) rename tools/{sliceofpointers => gogithub}/testdata/src/no-warnings/main.go (100%) diff --git a/.custom-gcl.yml b/.custom-gcl.yml index 2aa94b1bb08..363fddeff75 100644 --- a/.custom-gcl.yml +++ b/.custom-gcl.yml @@ -1,6 +1,6 @@ version: v2.2.2 plugins: - - module: "github.com/google/go-github/v75/tools/sliceofpointers" - path: ./tools/sliceofpointers + - module: "github.com/google/go-github/v75/tools/gogithub" + path: ./tools/gogithub - module: "github.com/google/go-github/v75/tools/fmtpercentv" path: ./tools/fmtpercentv diff --git a/.golangci.yml b/.golangci.yml index 673b9cd7cea..8f9a87a9f86 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,7 +22,7 @@ linters: - paralleltest - perfsprint - revive - - sliceofpointers + - gogithub - staticcheck - tparallel - unconvert @@ -143,10 +143,10 @@ linters: type: module description: Reports usage of %d or %s in format strings. original-url: github.com/google/go-github/v75/tools/fmtpercentv - sliceofpointers: + gogithub: type: module - description: Reports usage of []*string and slices of structs without pointers. - original-url: github.com/google/go-github/v75/tools/sliceofpointers + description: Custom linter for this project. + original-url: github.com/google/go-github/v75/tools/gogithub exclusions: rules: - linters: diff --git a/github/github.go b/github/github.go index d2d2676995c..74b487359c7 100644 --- a/github/github.go +++ b/github/github.go @@ -1149,21 +1149,23 @@ 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 - //nolint:sliceofpointers + //nolint:gogithub 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 // to some content that might help you resolve the error, see // https://docs.github.com/rest/#client-errors - DocumentationURL string `json:"documentation_url,omitempty"` //nolint:sliceofpointers + //nolint:gogithub + DocumentationURL string `json:"documentation_url,omitempty"` } // ErrorBlock contains a further explanation for the reason of an error. // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ // for more information. type ErrorBlock struct { - Reason string `json:"reason,omitempty"` //nolint:sliceofpointers + //nolint:gogithub + Reason string `json:"reason,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` } diff --git a/github/rate_limit.go b/github/rate_limit.go index df4982b09ae..0e597d4610b 100644 --- a/github/rate_limit.go +++ b/github/rate_limit.go @@ -27,7 +27,8 @@ type Rate struct { // The rate limit resource that the request counted against. // For more information about the different resources, see REST API endpoints for rate limits. // GitHub API docs: https://docs.github.com/en/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user - Resource string `json:"resource,omitempty"` //nolint:sliceofpointers + //nolint:gogithub + Resource string `json:"resource,omitempty"` } func (r Rate) String() string { diff --git a/github/strings_test.go b/github/strings_test.go index accd8529362..047c0cb0b5a 100644 --- a/github/strings_test.go +++ b/github/strings_test.go @@ -49,7 +49,7 @@ func TestStringify(t *testing.T) { {Ptr(123), `123`}, {Ptr(false), `false`}, { - //nolint:sliceofpointers + //nolint:gogithub []*string{Ptr("a"), Ptr("b")}, `["a" "b"]`, }, diff --git a/tools/sliceofpointers/go.mod b/tools/gogithub/go.mod similarity index 86% rename from tools/sliceofpointers/go.mod rename to tools/gogithub/go.mod index 8c927fb4d2b..7a06903bdf3 100644 --- a/tools/sliceofpointers/go.mod +++ b/tools/gogithub/go.mod @@ -1,4 +1,4 @@ -module tools/sliceofpointers +module tools/gogithub go 1.24.0 diff --git a/tools/sliceofpointers/go.sum b/tools/gogithub/go.sum similarity index 100% rename from tools/sliceofpointers/go.sum rename to tools/gogithub/go.sum diff --git a/tools/sliceofpointers/sliceofpointers.go b/tools/gogithub/gogithub.go similarity index 75% rename from tools/sliceofpointers/sliceofpointers.go rename to tools/gogithub/gogithub.go index 210351461b6..a628a3e0a9e 100644 --- a/tools/sliceofpointers/sliceofpointers.go +++ b/tools/gogithub/gogithub.go @@ -1,13 +1,12 @@ -// Copyright 2025 The go-github AUTHORS. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +/* +Package gogithub is a custom linter to be used by golangci-lint. -// Package sliceofpointers is a custom linter to be used by -// golangci-lint to find instances of `[]*string` and -// slices of structs without pointers and report them. -// See: https://github.com/google/go-github/issues/180 -package sliceofpointers +It finds: + + 1. instances of `[]*string` and slices of structs without pointers and report them. (See https://github.com/google/go-github/issues/180) + 2. struct fields with `json:"omitempty"` tags that are not pointers, slices, maps, or interfaces. +*/ +package gogithub import ( "go/ast" @@ -21,30 +20,30 @@ import ( ) func init() { - register.Plugin("sliceofpointers", New) + register.Plugin("gogithub", New) } -// SliceOfPointersPlugin is a custom linter plugin for golangci-lint. -type SliceOfPointersPlugin struct{} +// GoGithubPlugin is a custom linter plugin for golangci-lint. +type GoGithubPlugin struct{} // New returns an analysis.Analyzer to use with golangci-lint. func New(_ any) (register.LinterPlugin, error) { - return &SliceOfPointersPlugin{}, nil + return &GoGithubPlugin{}, nil } -// BuildAnalyzers builds the analyzers for the SliceOfPointersPlugin. -func (f *SliceOfPointersPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) { +// BuildAnalyzers builds the analyzers for the GoGithubPlugin. +func (f *GoGithubPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) { return []*analysis.Analyzer{ { - Name: "sliceofpointers", + Name: "gogithub", Doc: "Reports usage of []*string and slices of structs without pointers.", Run: run, }, }, nil } -// GetLoadMode returns the load mode for the SliceOfPointersPlugin. -func (f *SliceOfPointersPlugin) GetLoadMode() string { +// GetLoadMode returns the load mode for the GoGithubPlugin. +func (f *GoGithubPlugin) GetLoadMode() string { return register.LoadModeSyntax } diff --git a/tools/sliceofpointers/sliceofpointers_test.go b/tools/gogithub/gogithub_test.go similarity index 95% rename from tools/sliceofpointers/sliceofpointers_test.go rename to tools/gogithub/gogithub_test.go index 8fb0787f022..1983af07623 100644 --- a/tools/sliceofpointers/sliceofpointers_test.go +++ b/tools/gogithub/gogithub_test.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sliceofpointers +package gogithub import ( "testing" diff --git a/tools/sliceofpointers/testdata/src/has-warnings/main.go b/tools/gogithub/testdata/src/has-warnings/main.go similarity index 100% rename from tools/sliceofpointers/testdata/src/has-warnings/main.go rename to tools/gogithub/testdata/src/has-warnings/main.go diff --git a/tools/sliceofpointers/testdata/src/no-warnings/main.go b/tools/gogithub/testdata/src/no-warnings/main.go similarity index 100% rename from tools/sliceofpointers/testdata/src/no-warnings/main.go rename to tools/gogithub/testdata/src/no-warnings/main.go diff --git a/tools/metadata/metadata.go b/tools/metadata/metadata.go index 9cf1685e212..4bd231483a8 100644 --- a/tools/metadata/metadata.go +++ b/tools/metadata/metadata.go @@ -29,8 +29,10 @@ import ( ) type operation struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` //nolint:sliceofpointers - DocumentationURL string `yaml:"documentation_url,omitempty" json:"documentation_url,omitempty"` //nolint:sliceofpointers + //nolint:gogithub + Name string `yaml:"name,omitempty" json:"name,omitempty"` + //nolint:gogithub + DocumentationURL string `yaml:"documentation_url,omitempty" json:"documentation_url,omitempty"` OpenAPIFiles []string `yaml:"openapi_files,omitempty" json:"openapi_files,omitempty"` } From 1cec393c16ad263b6575c091be02099a5056d3db Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 21:42:51 +0900 Subject: [PATCH 5/7] copyright --- tools/gogithub/gogithub.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/gogithub/gogithub.go b/tools/gogithub/gogithub.go index a628a3e0a9e..40f55d81ef2 100644 --- a/tools/gogithub/gogithub.go +++ b/tools/gogithub/gogithub.go @@ -1,3 +1,8 @@ +// Copyright 2025 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + /* Package gogithub is a custom linter to be used by golangci-lint. From e8329a2ad2e7ceb0e678b10e02a2c784b6f99b87 Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 22:03:24 +0900 Subject: [PATCH 6/7] make required field to value type --- github/repos.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/github/repos.go b/github/repos.go index 9bc23edb4fa..ba6e14aa5d2 100644 --- a/github/repos.go +++ b/github/repos.go @@ -2417,7 +2417,7 @@ func (s *RepositoriesService) DisablePrivateReporting(ctx context.Context, owner // checkPrivateReporting represents whether private vulnerability reporting is enabled. type checkPrivateReporting struct { - Enabled *bool `json:"enabled,omitempty"` + Enabled bool `json:"enabled"` } // IsPrivateReportingEnabled checks if private vulnerability reporting is enabled @@ -2436,10 +2436,7 @@ func (s *RepositoriesService) IsPrivateReportingEnabled(ctx context.Context, own privateReporting := new(checkPrivateReporting) resp, err := s.client.Do(ctx, req, privateReporting) - if privateReporting.Enabled != nil { - return *privateReporting.Enabled, resp, err - } - return false, resp, err + return privateReporting.Enabled, resp, err } // ListRepositoryActivityOptions specifies the optional parameters to the From bab5e6dd6d9e6d337efba0114c0eb74c1b05e86b Mon Sep 17 00:00:00 2001 From: zyfy29 Date: Tue, 14 Oct 2025 23:51:28 +0900 Subject: [PATCH 7/7] fix field types in project service --- github/github-accessors.go | 28 ++++++--------- github/github-accessors_test.go | 35 +++++++------------ github/projects.go | 26 +++++++------- github/projects_test.go | 61 ++++++++++++--------------------- 4 files changed, 58 insertions(+), 92 deletions(-) diff --git a/github/github-accessors.go b/github/github-accessors.go index 2cdd98e80ba..38cfb7a3300 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -19198,28 +19198,20 @@ func (p *ProjectV2Event) GetSender() *User { return p.Sender } -// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectV2Field) GetCreatedAt() Timestamp { - if p == nil || p.CreatedAt == nil { - return Timestamp{} - } - return *p.CreatedAt -} - -// GetID returns the ID field if it's non-nil, zero value otherwise. -func (p *ProjectV2Field) GetID() int64 { - if p == nil || p.ID == nil { - return 0 +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectV2Field) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" } - return *p.ID + return *p.NodeID } -// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. -func (p *ProjectV2Field) GetUpdatedAt() Timestamp { - if p == nil || p.UpdatedAt == nil { - return Timestamp{} +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectV2Field) GetURL() string { + if p == nil || p.URL == nil { + return "" } - return *p.UpdatedAt + return *p.URL } // GetArchivedAt returns the ArchivedAt field if it's non-nil, zero value otherwise. diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index b5bd91bf4e9..8884152ab18 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -24929,37 +24929,26 @@ func TestProjectV2Event_GetSender(tt *testing.T) { p.GetSender() } -func TestProjectV2Field_GetCreatedAt(tt *testing.T) { +func TestProjectV2Field_GetNodeID(tt *testing.T) { tt.Parallel() - var zeroValue Timestamp - p := &ProjectV2Field{CreatedAt: &zeroValue} - p.GetCreatedAt() - p = &ProjectV2Field{} - p.GetCreatedAt() - p = nil - p.GetCreatedAt() -} - -func TestProjectV2Field_GetID(tt *testing.T) { - tt.Parallel() - var zeroValue int64 - p := &ProjectV2Field{ID: &zeroValue} - p.GetID() + var zeroValue string + p := &ProjectV2Field{NodeID: &zeroValue} + p.GetNodeID() p = &ProjectV2Field{} - p.GetID() + p.GetNodeID() p = nil - p.GetID() + p.GetNodeID() } -func TestProjectV2Field_GetUpdatedAt(tt *testing.T) { +func TestProjectV2Field_GetURL(tt *testing.T) { tt.Parallel() - var zeroValue Timestamp - p := &ProjectV2Field{UpdatedAt: &zeroValue} - p.GetUpdatedAt() + var zeroValue string + p := &ProjectV2Field{URL: &zeroValue} + p.GetURL() p = &ProjectV2Field{} - p.GetUpdatedAt() + p.GetURL() p = nil - p.GetUpdatedAt() + p.GetURL() } func TestProjectV2Item_GetArchivedAt(tt *testing.T) { diff --git a/github/projects.go b/github/projects.go index 9f562fee865..b0d00767e33 100644 --- a/github/projects.go +++ b/github/projects.go @@ -8,6 +8,7 @@ package github import ( "context" "fmt" + "time" ) // ProjectsService handles communication with the project V2 @@ -79,13 +80,13 @@ type ListProjectsOptions struct { // // GitHub API docs: https://docs.github.com/rest/projects/fields type ProjectV2FieldOption struct { - ID string `json:"id,omitempty"` + ID string `json:"id"` // The display name of the option. - Name string `json:"name,omitempty"` + Name string `json:"name"` // The color associated with this option (e.g., "blue", "red"). - Color string `json:"color,omitempty"` + Color string `json:"color"` // An optional description for this option. - Description string `json:"description,omitempty"` + Description string `json:"description"` } // ProjectV2Field represents a field in a GitHub Projects V2 project. @@ -93,14 +94,15 @@ type ProjectV2FieldOption struct { // // GitHub API docs: https://docs.github.com/rest/projects/fields type ProjectV2Field struct { - ID *int64 `json:"id,omitempty"` - NodeID string `json:"node_id,omitempty"` - Name string `json:"name,omitempty"` - DataType string `json:"dataType,omitempty"` - URL string `json:"url,omitempty"` - Options []*any `json:"options,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ID int64 `json:"id"` + NodeID *string `json:"node_id,omitempty"` + Name string `json:"name"` + DataType string `json:"data_type"` + URL *string `json:"url,omitempty"` + ProjectURL string `json:"project_url"` + Options []*ProjectV2FieldOption `json:"options,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } // ListProjectsForOrg lists Projects V2 for an organization. diff --git a/github/projects_test.go b/github/projects_test.go index a5f71c0d675..ec754630399 100644 --- a/github/projects_test.go +++ b/github/projects_test.go @@ -278,7 +278,8 @@ func TestProjectsService_ListProjectFieldsForOrg(t *testing.T) { "id": 1, "node_id": "node_1", "name": "Status", - "dataType": "single_select", + "data_type": "single_select", + "project_url": "https://api.github.com/projects/1", "url": "https://api.github.com/projects/1/fields/field1", "options": [ { @@ -300,7 +301,8 @@ func TestProjectsService_ListProjectFieldsForOrg(t *testing.T) { "id": 2, "node_id": "node_2", "name": "Priority", - "dataType": "text", + "data_type": "text", + "project_url": "https://api.github.com/projects/1", "url": "https://api.github.com/projects/1/fields/field2", "created_at": "2011-01-02T15:04:05Z", "updated_at": "2012-01-02T15:04:05Z" @@ -320,35 +322,21 @@ func TestProjectsService_ListProjectFieldsForOrg(t *testing.T) { } field1 := fields[0] - if field1.ID == nil || *field1.ID != 1 || field1.Name != "Status" || field1.DataType != "single_select" { + if field1.ID != 1 || field1.Name != "Status" || field1.DataType != "single_select" { t.Errorf("First field: got ID=%v, Name=%v, DataType=%v; want 1, Status, single_select", field1.ID, field1.Name, field1.DataType) } if len(field1.Options) != 2 { t.Errorf("First field options: got %v, want 2", len(field1.Options)) } else { - getName := func(o *any) string { - if o == nil || *o == nil { - return "" - } - switch v := (*o).(type) { - case map[string]any: - if n, ok := v["name"].(string); ok { - return n - } - default: - // fall back to fmt for debug; reflection can be added if needed. - } - return "" - } - name0, name1 := getName(field1.Options[0]), getName(field1.Options[1]) - if name0 != "Todo" || name1 != "In Progress" { + name0, name1 := field1.Options[0].Name, field1.Options[1].Name + if field1.Options[0].Name != "Todo" || field1.Options[1].Name != "In Progress" { t.Errorf("First field option names: got %q, %q; want Todo, In Progress", name0, name1) } } // Validate second field (without options) field2 := fields[1] - if field2.ID == nil || *field2.ID != 2 || field2.Name != "Priority" || field2.DataType != "text" { + if field2.ID != 2 || field2.Name != "Priority" || field2.DataType != "text" { t.Errorf("Second field: got ID=%v, Name=%v, DataType=%v; want 2, Priority, text", field2.ID, field2.Name, field2.DataType) } if len(field2.Options) != 0 { @@ -406,7 +394,7 @@ func TestProjectsService_ListProjectFieldsForOrg_pagination(t *testing.T) { if err != nil { t.Fatalf("first page error: %v", err) } - if len(first) != 1 || first[0].ID == nil || *first[0].ID != 1 { + if len(first) != 1 || first[0].ID != 1 { t.Fatalf("unexpected first page %+v", first) } if resp.After != "cursor2" { @@ -418,7 +406,7 @@ func TestProjectsService_ListProjectFieldsForOrg_pagination(t *testing.T) { if err != nil { t.Fatalf("second page error: %v", err) } - if len(second) != 1 || second[0].ID == nil || *second[0].ID != 2 { + if len(second) != 1 || second[0].ID != 2 { t.Fatalf("unexpected second page %+v", second) } if resp2.Before != "cursor2" { @@ -456,32 +444,27 @@ func TestProjectV2Field_Marshal(t *testing.T) { testJSONMarshal(t, &ProjectV2Field{}, "{}") // empty struct testJSONMarshal(t, &ProjectV2FieldOption{}, "{}") // option struct still individually testable - type optStruct struct { - Color string `json:"color,omitempty"` - Description string `json:"description,omitempty"` - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - } - optVal := &optStruct{Color: "blue", Description: "Tasks to be done", ID: "option1", Name: "Todo"} - var optAny any = optVal + optVal := &ProjectV2FieldOption{Color: "blue", Description: "Tasks to be done", ID: "option1", Name: "Todo"} field := &ProjectV2Field{ - ID: Ptr(int64(1)), - NodeID: "node_1", - Name: "Status", - DataType: "single_select", - URL: "https://api.github.com/projects/1/fields/field1", - Options: []*any{&optAny}, - CreatedAt: &Timestamp{referenceTime}, - UpdatedAt: &Timestamp{referenceTime}, + ID: 1, + NodeID: Ptr("node_1"), + Name: "Status", + DataType: "single_select", + URL: Ptr("https://api.github.com/projects/1/fields/field1"), + ProjectURL: "https://api.github.com/projects/1", + Options: []*ProjectV2FieldOption{optVal}, + CreatedAt: referenceTime, + UpdatedAt: referenceTime, } want := `{ "id": 1, "node_id": "node_1", "name": "Status", - "dataType": "single_select", + "data_type": "single_select", "url": "https://api.github.com/projects/1/fields/field1", + "project_url": "https://api.github.com/projects/1", "options": [ { "id": "option1",