diff --git a/README.md b/README.md index bc1c31ee432..6effaf7cf9b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # go-github # [![go-github release (latest SemVer)](https://img.shields.io/github/v/release/google/go-github?sort=semver)](https://github.com/google/go-github/releases) -[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/google/go-github/v35/github) +[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/google/go-github/v37/github) [![Test Status](https://github.com/google/go-github/workflows/tests/badge.svg)](https://github.com/google/go-github/actions?query=workflow%3Atests) [![Test Coverage](https://codecov.io/gh/google/go-github/branch/master/graph/badge.svg)](https://codecov.io/gh/google/go-github) [![Discuss at go-github@googlegroups.com](https://img.shields.io/badge/discuss-go--github%40googlegroups.com-blue.svg)](https://groups.google.com/group/go-github) @@ -24,7 +24,7 @@ If you're interested in using the [GraphQL API v4][], the recommended library is go-github is compatible with modern Go releases in module mode, with Go installed: ```bash -go get github.com/google/go-github/v35 +go get github.com/google/go-github/v37 ``` will resolve and add the package to the current development module, along with its dependencies. @@ -32,7 +32,7 @@ will resolve and add the package to the current development module, along with i Alternatively the same can be achieved if you use import in a package: ```go -import "github.com/google/go-github/v35/github" +import "github.com/google/go-github/v37/github" ``` and run `go get` without parameters. @@ -40,13 +40,13 @@ and run `go get` without parameters. Finally, to use the top-of-trunk version of this repo, use the following command: ```bash -go get github.com/google/go-github/v35@master +go get github.com/google/go-github/v37@master ``` ## Usage ## ```go -import "github.com/google/go-github/v35/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) +import "github.com/google/go-github/v37/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/github" // with go modules disabled ``` @@ -246,7 +246,7 @@ For complete usage of go-github, see the full [package docs][]. [oauth2]: https://github.com/golang/oauth2 [oauth2 docs]: https://godoc.org/golang.org/x/oauth2 [personal API token]: https://github.com/blog/1509-personal-api-tokens -[package docs]: https://pkg.go.dev/github.com/google/go-github/v35/github +[package docs]: https://pkg.go.dev/github.com/google/go-github/v37/github [GraphQL API v4]: https://developer.github.com/v4/ [shurcooL/githubv4]: https://github.com/shurcooL/githubv4 diff --git a/example/appengine/app.go b/example/appengine/app.go index 588a2a07414..75c9052873b 100644 --- a/example/appengine/app.go +++ b/example/appengine/app.go @@ -12,7 +12,7 @@ import ( "net/http" "os" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" "google.golang.org/appengine" "google.golang.org/appengine/log" diff --git a/example/basicauth/main.go b/example/basicauth/main.go index 3c7efc82a1f..09ab1180881 100644 --- a/example/basicauth/main.go +++ b/example/basicauth/main.go @@ -22,7 +22,7 @@ import ( "strings" "syscall" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/crypto/ssh/terminal" ) diff --git a/example/commitpr/main.go b/example/commitpr/main.go index 604f4f58584..33572f200e0 100644 --- a/example/commitpr/main.go +++ b/example/commitpr/main.go @@ -31,7 +31,7 @@ import ( "strings" "time" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/example/migrations/main.go b/example/migrations/main.go index 230cff25a75..42218b7a33d 100644 --- a/example/migrations/main.go +++ b/example/migrations/main.go @@ -12,7 +12,7 @@ import ( "context" "fmt" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/example/newrepo/main.go b/example/newrepo/main.go index 239ccfb7769..6190467f2b9 100644 --- a/example/newrepo/main.go +++ b/example/newrepo/main.go @@ -16,7 +16,7 @@ import ( "log" "os" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/example/newreposecret/go.mod b/example/newreposecret/go.mod index 50d854c612f..5f3e7027f64 100644 --- a/example/newreposecret/go.mod +++ b/example/newreposecret/go.mod @@ -4,7 +4,7 @@ go 1.15 require ( github.com/GoKillers/libsodium-go v0.0.0-20171022220152-dd733721c3cb - github.com/google/go-github/v35 v35.0.0 + github.com/google/go-github/v37 v37.0.0 golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/example/newreposecret/main.go b/example/newreposecret/main.go index 928e4532f51..08d5fc9203c 100644 --- a/example/newreposecret/main.go +++ b/example/newreposecret/main.go @@ -34,7 +34,7 @@ import ( "os" sodium "github.com/GoKillers/libsodium-go/cryptobox" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/example/simple/main.go b/example/simple/main.go index ee0d5751507..2b3d8732bf6 100644 --- a/example/simple/main.go +++ b/example/simple/main.go @@ -12,7 +12,7 @@ import ( "context" "fmt" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) // Fetch all the public organizations' membership of a user. diff --git a/example/tokenauth/main.go b/example/tokenauth/main.go index 922707c5fde..7f172965f3b 100644 --- a/example/tokenauth/main.go +++ b/example/tokenauth/main.go @@ -14,7 +14,7 @@ import ( "log" "syscall" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/crypto/ssh/terminal" "golang.org/x/oauth2" ) diff --git a/example/topics/main.go b/example/topics/main.go index 7011b6e35fd..0c0787f4407 100644 --- a/example/topics/main.go +++ b/example/topics/main.go @@ -12,7 +12,7 @@ import ( "context" "fmt" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) // Fetch and lists all the public topics associated with the specified GitHub topic diff --git a/github/actions_artifacts_test.go b/github/actions_artifacts_test.go index 7344d4cf608..e526e059714 100644 --- a/github/actions_artifacts_test.go +++ b/github/actions_artifacts_test.go @@ -7,6 +7,7 @@ package github import ( "context" + "errors" "fmt" "net/http" "net/url" @@ -294,6 +295,15 @@ func TestActionsSerivice_DownloadArtifact(t *testing.T) { _, _, err = client.Actions.DownloadArtifact(ctx, "\n", "\n", -1, true) return err }) + + // Add custom round tripper + client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { + return nil, errors.New("failed to download artifact") + }) + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.DownloadArtifact(ctx, "o", "r", 1, true) + return err + }) } func TestActionsService_DownloadArtifact_invalidOwner(t *testing.T) { @@ -419,3 +429,67 @@ func TestActionsService_DeleteArtifact_notFound(t *testing.T) { t.Errorf("Actions.DeleteArtifact return status %d, want %d", got, want) } } + +func TestArtifact_Marshal(t *testing.T) { + testJSONMarshal(t, &Artifact{}, "{}") + + u := &Artifact{ + ID: Int64(1), + NodeID: String("nid"), + Name: String("n"), + SizeInBytes: Int64(1), + ArchiveDownloadURL: String("a"), + Expired: Bool(false), + CreatedAt: &Timestamp{referenceTime}, + ExpiresAt: &Timestamp{referenceTime}, + } + + want := `{ + "id": 1, + "node_id": "nid", + "name": "n", + "size_in_bytes": 1, + "archive_download_url": "a", + "expired": false, + "created_at": ` + referenceTimeStr + `, + "expires_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} + +func TestArtifactList_Marshal(t *testing.T) { + testJSONMarshal(t, &ArtifactList{}, "{}") + + u := &ArtifactList{ + TotalCount: Int64(1), + Artifacts: []*Artifact{ + { + ID: Int64(1), + NodeID: String("nid"), + Name: String("n"), + SizeInBytes: Int64(1), + ArchiveDownloadURL: String("a"), + Expired: Bool(false), + CreatedAt: &Timestamp{referenceTime}, + ExpiresAt: &Timestamp{referenceTime}, + }, + }, + } + + want := `{ + "total_count": 1, + "artifacts": [{ + "id": 1, + "node_id": "nid", + "name": "n", + "size_in_bytes": 1, + "archive_download_url": "a", + "expired": false, + "created_at": ` + referenceTimeStr + `, + "expires_at": ` + referenceTimeStr + ` + }] + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/actions_runner_groups_test.go b/github/actions_runner_groups_test.go index ca24ae93868..27489ad99bd 100644 --- a/github/actions_runner_groups_test.go +++ b/github/actions_runner_groups_test.go @@ -472,3 +472,131 @@ func TestActionsService_RemoveRunnerGroupRunners(t *testing.T) { return client.Actions.RemoveRunnerGroupRunners(ctx, "o", 2, 42) }) } + +func TestRunnerGroup_Marshal(t *testing.T) { + testJSONMarshal(t, &RunnerGroup{}, "{}") + + u := &RunnerGroup{ + ID: Int64(1), + Name: String("n"), + Visibility: String("v"), + Default: Bool(true), + SelectedRepositoriesURL: String("s"), + RunnersURL: String("r"), + Inherited: Bool(true), + AllowsPublicRepositories: Bool(true), + } + + want := `{ + "id": 1, + "name": "n", + "visibility": "v", + "default": true, + "selected_repositories_url": "s", + "runners_url": "r", + "inherited": true, + "allows_public_repositories": true + }` + + testJSONMarshal(t, u, want) +} + +func TestRunnerGroups_Marshal(t *testing.T) { + testJSONMarshal(t, &RunnerGroups{}, "{}") + + u := &RunnerGroups{ + TotalCount: int(1), + RunnerGroups: []*RunnerGroup{ + { + ID: Int64(1), + Name: String("n"), + Visibility: String("v"), + Default: Bool(true), + SelectedRepositoriesURL: String("s"), + RunnersURL: String("r"), + Inherited: Bool(true), + AllowsPublicRepositories: Bool(true), + }, + }, + } + + want := `{ + "total_count": 1, + "runner_groups": [{ + "id": 1, + "name": "n", + "visibility": "v", + "default": true, + "selected_repositories_url": "s", + "runners_url": "r", + "inherited": true, + "allows_public_repositories": true + }] + }` + + testJSONMarshal(t, u, want) +} + +func TestCreateRunnerGroupRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &CreateRunnerGroupRequest{}, "{}") + + u := &CreateRunnerGroupRequest{ + Name: String("n"), + Visibility: String("v"), + SelectedRepositoryIDs: []int64{1}, + Runners: []int64{1}, + } + + want := `{ + "name": "n", + "visibility": "v", + "selected_repository_ids": [1], + "runners": [1] + }` + + testJSONMarshal(t, u, want) +} + +func TestUpdateRunnerGroupRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &UpdateRunnerGroupRequest{}, "{}") + + u := &UpdateRunnerGroupRequest{ + Name: String("n"), + Visibility: String("v"), + } + + want := `{ + "name": "n", + "visibility": "v" + }` + + testJSONMarshal(t, u, want) +} + +func TestSetRepoAccessRunnerGroupRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &SetRepoAccessRunnerGroupRequest{}, "{}") + + u := &SetRepoAccessRunnerGroupRequest{ + SelectedRepositoryIDs: []int64{1}, + } + + want := `{ + "selected_repository_ids": [1] + }` + + testJSONMarshal(t, u, want) +} + +func TestSetRunnerGroupRunnersRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &SetRunnerGroupRunnersRequest{}, "{}") + + u := &SetRunnerGroupRunnersRequest{ + Runners: []int64{1}, + } + + want := `{ + "runners": [1] + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/actions_runners_test.go b/github/actions_runners_test.go index a3e3b28e82e..a997f627f89 100644 --- a/github/actions_runners_test.go +++ b/github/actions_runners_test.go @@ -500,3 +500,187 @@ func TestActionsService_RemoveOrganizationRunner(t *testing.T) { return client.Actions.RemoveOrganizationRunner(ctx, "o", 21) }) } + +func TestRunnerApplicationDownload_Marshal(t *testing.T) { + testJSONMarshal(t, &RunnerApplicationDownload{}, "{}") + + u := &RunnerApplicationDownload{ + OS: String("o"), + Architecture: String("a"), + DownloadURL: String("d"), + Filename: String("f"), + TempDownloadToken: String("t"), + SHA256Checksum: String("s"), + } + + want := `{ + "os": "o", + "architecture": "a", + "download_url": "d", + "filename": "f", + "temp_download_token": "t", + "sha256_checksum": "s" + }` + + testJSONMarshal(t, u, want) +} + +func TestActionsEnabledOnOrgRepos_Marshal(t *testing.T) { + testJSONMarshal(t, &ActionsEnabledOnOrgRepos{}, "{}") + + u := &ActionsEnabledOnOrgRepos{ + TotalCount: 1, + Repositories: []*Repository{ + { + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + } + + want := `{ + "total_count": 1, + "repositories": [ + { + "id": 1, + "url": "u", + "name": "n" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestRegistrationToken_Marshal(t *testing.T) { + testJSONMarshal(t, &RegistrationToken{}, "{}") + + u := &RegistrationToken{ + Token: String("t"), + ExpiresAt: &Timestamp{referenceTime}, + } + + want := `{ + "token": "t", + "expires_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} + +func TestRunnerLabels_Marshal(t *testing.T) { + testJSONMarshal(t, &RunnerLabels{}, "{}") + + u := &RunnerLabels{ + ID: Int64(1), + Name: String("n"), + Type: String("t"), + } + + want := `{ + "id": 1, + "name": "n", + "type": "t" + }` + + testJSONMarshal(t, u, want) +} + +func TestRunner_Marshal(t *testing.T) { + testJSONMarshal(t, &Runner{}, "{}") + + u := &Runner{ + ID: Int64(1), + Name: String("n"), + OS: String("o"), + Status: String("s"), + Busy: Bool(false), + Labels: []*RunnerLabels{ + { + ID: Int64(1), + Name: String("n"), + Type: String("t"), + }, + }, + } + + want := `{ + "id": 1, + "name": "n", + "os": "o", + "status": "s", + "busy": false, + "labels": [ + { + "id": 1, + "name": "n", + "type": "t" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestRunners_Marshal(t *testing.T) { + testJSONMarshal(t, &Runners{}, "{}") + + u := &Runners{ + TotalCount: 1, + Runners: []*Runner{ + { + ID: Int64(1), + Name: String("n"), + OS: String("o"), + Status: String("s"), + Busy: Bool(false), + Labels: []*RunnerLabels{ + { + ID: Int64(1), + Name: String("n"), + Type: String("t"), + }, + }, + }, + }, + } + + want := `{ + "total_count": 1, + "runners": [ + { + "id": 1, + "name": "n", + "os": "o", + "status": "s", + "busy": false, + "labels": [ + { + "id": 1, + "name": "n", + "type": "t" + } + ] + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestRemoveToken_Marshal(t *testing.T) { + testJSONMarshal(t, &RemoveToken{}, "{}") + + u := &RemoveToken{ + Token: String("t"), + ExpiresAt: &Timestamp{referenceTime}, + } + + want := `{ + "token": "t", + "expires_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/actions_workflow_jobs_test.go b/github/actions_workflow_jobs_test.go index 4062cc5b275..49315a03ba4 100644 --- a/github/actions_workflow_jobs_test.go +++ b/github/actions_workflow_jobs_test.go @@ -7,6 +7,7 @@ package github import ( "context" + "errors" "fmt" "net/http" "net/url" @@ -154,6 +155,15 @@ func TestActionsService_GetWorkflowJobLogs(t *testing.T) { _, _, err = client.Actions.GetWorkflowJobLogs(ctx, "\n", "\n", 399444496, true) return err }) + + // Add custom round tripper + client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { + return nil, errors.New("failed to get workflow logs") + }) + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Actions.GetWorkflowJobLogs(ctx, "o", "r", 399444496, true) + return err + }) } func TestActionsService_GetWorkflowJobLogs_StatusMovedPermanently_dontFollowRedirects(t *testing.T) { diff --git a/github/actions_workflow_runs_test.go b/github/actions_workflow_runs_test.go index b01c594c0ed..14274d53929 100644 --- a/github/actions_workflow_runs_test.go +++ b/github/actions_workflow_runs_test.go @@ -412,3 +412,431 @@ func TestActionsService_GetWorkflowRunUsageByID(t *testing.T) { return resp, err }) } + +func TestWorkflowRun_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowRun{}, "{}") + + u := &WorkflowRun{ + ID: Int64(1), + Name: String("n"), + NodeID: String("nid"), + HeadBranch: String("hb"), + HeadSHA: String("hs"), + RunNumber: Int(1), + Event: String("e"), + Status: String("s"), + Conclusion: String("c"), + WorkflowID: Int64(1), + URL: String("u"), + HTMLURL: String("h"), + PullRequests: []*PullRequest{ + { + URL: String("u"), + ID: Int64(1), + Number: Int(1), + Head: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("s"), + Name: String("n"), + }, + }, + Base: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + }, + }, + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + JobsURL: String("j"), + LogsURL: String("l"), + CheckSuiteURL: String("c"), + ArtifactsURL: String("a"), + CancelURL: String("c"), + RerunURL: String("r"), + HeadCommit: &HeadCommit{ + Message: String("m"), + Author: &CommitAuthor{ + Name: String("n"), + Email: String("e"), + Login: String("l"), + }, + URL: String("u"), + Distinct: Bool(false), + SHA: String("s"), + ID: String("i"), + TreeID: String("tid"), + Timestamp: &Timestamp{referenceTime}, + Committer: &CommitAuthor{ + Name: String("n"), + Email: String("e"), + Login: String("l"), + }, + }, + WorkflowURL: String("w"), + Repository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + HeadRepository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + } + + want := `{ + "id": 1, + "name": "n", + "node_id": "nid", + "head_branch": "hb", + "head_sha": "hs", + "run_number": 1, + "event": "e", + "status": "s", + "conclusion": "c", + "workflow_id": 1, + "url": "u", + "html_url": "h", + "pull_requests": [ + { + "id":1, + "number":1, + "url":"u", + "head":{ + "ref":"r", + "sha":"s", + "repo": { + "id":1, + "name":"n", + "url":"s" + } + }, + "base": { + "ref":"r", + "sha":"s", + "repo": { + "id":1, + "name":"n", + "url":"u" + } + } + } + ], + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "jobs_url": "j", + "logs_url": "l", + "check_suite_url": "c", + "artifacts_url": "a", + "cancel_url": "c", + "rerun_url": "r", + "head_commit": { + "message": "m", + "author": { + "name": "n", + "email": "e", + "username": "l" + }, + "url": "u", + "distinct": false, + "sha": "s", + "id": "i", + "tree_id": "tid", + "timestamp": ` + referenceTimeStr + `, + "committer": { + "name": "n", + "email": "e", + "username": "l" + } + }, + "workflow_url": "w", + "repository": { + "id": 1, + "url": "u", + "name": "n" + }, + "head_repository": { + "id": 1, + "url": "u", + "name": "n" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowRuns_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowRuns{}, "{}") + + u := &WorkflowRuns{ + TotalCount: Int(1), + WorkflowRuns: []*WorkflowRun{ + { + ID: Int64(1), + Name: String("n"), + NodeID: String("nid"), + HeadBranch: String("hb"), + HeadSHA: String("hs"), + RunNumber: Int(1), + Event: String("e"), + Status: String("s"), + Conclusion: String("c"), + WorkflowID: Int64(1), + URL: String("u"), + HTMLURL: String("h"), + PullRequests: []*PullRequest{ + { + URL: String("u"), + ID: Int64(1), + Number: Int(1), + Head: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("s"), + Name: String("n"), + }, + }, + Base: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + }, + }, + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + JobsURL: String("j"), + LogsURL: String("l"), + CheckSuiteURL: String("c"), + ArtifactsURL: String("a"), + CancelURL: String("c"), + RerunURL: String("r"), + HeadCommit: &HeadCommit{ + Message: String("m"), + Author: &CommitAuthor{ + Name: String("n"), + Email: String("e"), + Login: String("l"), + }, + URL: String("u"), + Distinct: Bool(false), + SHA: String("s"), + ID: String("i"), + TreeID: String("tid"), + Timestamp: &Timestamp{referenceTime}, + Committer: &CommitAuthor{ + Name: String("n"), + Email: String("e"), + Login: String("l"), + }, + }, + WorkflowURL: String("w"), + Repository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + HeadRepository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + }, + } + + want := `{ + "total_count": 1, + "workflow_runs": [ + { + "id": 1, + "name": "n", + "node_id": "nid", + "head_branch": "hb", + "head_sha": "hs", + "run_number": 1, + "event": "e", + "status": "s", + "conclusion": "c", + "workflow_id": 1, + "url": "u", + "html_url": "h", + "pull_requests": [ + { + "id":1, + "number":1, + "url":"u", + "head":{ + "ref":"r", + "sha":"s", + "repo": { + "id":1, + "name":"n", + "url":"s" + } + }, + "base": { + "ref":"r", + "sha":"s", + "repo": { + "id":1, + "name":"n", + "url":"u" + } + } + } + ], + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "jobs_url": "j", + "logs_url": "l", + "check_suite_url": "c", + "artifacts_url": "a", + "cancel_url": "c", + "rerun_url": "r", + "head_commit": { + "message": "m", + "author": { + "name": "n", + "email": "e", + "username": "l" + }, + "url": "u", + "distinct": false, + "sha": "s", + "id": "i", + "tree_id": "tid", + "timestamp": ` + referenceTimeStr + `, + "committer": { + "name": "n", + "email": "e", + "username": "l" + } + }, + "workflow_url": "w", + "repository": { + "id": 1, + "url": "u", + "name": "n" + }, + "head_repository": { + "id": 1, + "url": "u", + "name": "n" + } + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowRunBill_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowRunBill{}, "{}") + + u := &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + } + + want := `{ + "total_ms": 1, + "jobs": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowRunEnvironment_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowRunEnvironment{}, "{}") + + u := &WorkflowRunEnvironment{ + Ubuntu: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + MacOS: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + Windows: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + } + + want := `{ + "UBUNTU": { + "total_ms": 1, + "jobs": 1 + }, + "MACOS": { + "total_ms": 1, + "jobs": 1 + }, + "WINDOWS": { + "total_ms": 1, + "jobs": 1 + } + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowRunUsage_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowRunUsage{}, "{}") + + u := &WorkflowRunUsage{ + Billable: &WorkflowRunEnvironment{ + Ubuntu: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + MacOS: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + Windows: &WorkflowRunBill{ + TotalMS: Int64(1), + Jobs: Int(1), + }, + }, + RunDurationMS: Int64(1), + } + + want := `{ + "billable": { + "UBUNTU": { + "total_ms": 1, + "jobs": 1 + }, + "MACOS": { + "total_ms": 1, + "jobs": 1 + }, + "WINDOWS": { + "total_ms": 1, + "jobs": 1 + } + }, + "run_duration_ms": 1 + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/actions_workflows_test.go b/github/actions_workflows_test.go index 45a161b6587..60a9d91b371 100644 --- a/github/actions_workflows_test.go +++ b/github/actions_workflows_test.go @@ -458,3 +458,174 @@ func TestActionsService_DisableWorkflowByFileName(t *testing.T) { return client.Actions.DisableWorkflowByFileName(ctx, "o", "r", "main.yml") }) } + +func TestWorkflow_Marshal(t *testing.T) { + testJSONMarshal(t, &Workflow{}, "{}") + + u := &Workflow{ + ID: Int64(1), + NodeID: String("nid"), + Name: String("n"), + Path: String("p"), + State: String("s"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + URL: String("u"), + HTMLURL: String("h"), + BadgeURL: String("b"), + } + + want := `{ + "id": 1, + "node_id": "nid", + "name": "n", + "path": "p", + "state": "s", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "url": "u", + "html_url": "h", + "badge_url": "b" + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflows_Marshal(t *testing.T) { + testJSONMarshal(t, &Workflows{}, "{}") + + u := &Workflows{ + TotalCount: Int(1), + Workflows: []*Workflow{ + { + ID: Int64(1), + NodeID: String("nid"), + Name: String("n"), + Path: String("p"), + State: String("s"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + URL: String("u"), + HTMLURL: String("h"), + BadgeURL: String("b"), + }, + }, + } + + want := `{ + "total_count": 1, + "workflows": [{ + "id": 1, + "node_id": "nid", + "name": "n", + "path": "p", + "state": "s", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "url": "u", + "html_url": "h", + "badge_url": "b" + }] + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowBill_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowBill{}, "{}") + + u := &WorkflowBill{ + TotalMS: Int64(1), + } + + want := `{ + "total_ms": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowEnvironment_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowEnvironment{}, "{}") + + u := &WorkflowEnvironment{ + Ubuntu: &WorkflowBill{ + TotalMS: Int64(1), + }, + MacOS: &WorkflowBill{ + TotalMS: Int64(1), + }, + Windows: &WorkflowBill{ + TotalMS: Int64(1), + }, + } + + want := `{ + "UBUNTU": { + "total_ms": 1 + }, + "MACOS": { + "total_ms": 1 + }, + "WINDOWS": { + "total_ms": 1 + } + }` + + testJSONMarshal(t, u, want) +} + +func TestWorkflowUsage_Marshal(t *testing.T) { + testJSONMarshal(t, &WorkflowUsage{}, "{}") + + u := &WorkflowUsage{ + Billable: &WorkflowEnvironment{ + Ubuntu: &WorkflowBill{ + TotalMS: Int64(1), + }, + MacOS: &WorkflowBill{ + TotalMS: Int64(1), + }, + Windows: &WorkflowBill{ + TotalMS: Int64(1), + }, + }, + } + + want := `{ + "billable": { + "UBUNTU": { + "total_ms": 1 + }, + "MACOS": { + "total_ms": 1 + }, + "WINDOWS": { + "total_ms": 1 + } + } + }` + + testJSONMarshal(t, u, want) +} + +func TestCreateWorkflowDispatchEventRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &CreateWorkflowDispatchEventRequest{}, "{}") + + inputs := make(map[string]interface{}, 0) + inputs["key"] = "value" + + u := &CreateWorkflowDispatchEventRequest{ + Ref: "r", + Inputs: inputs, + } + + want := `{ + "ref": "r", + "inputs": { + "key": "value" + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/activity.go b/github/activity.go index 4310564bac1..e683afb99b9 100644 --- a/github/activity.go +++ b/github/activity.go @@ -21,22 +21,25 @@ type FeedLink struct { // Feeds represents timeline resources in Atom format. type Feeds struct { - TimelineURL *string `json:"timeline_url,omitempty"` - UserURL *string `json:"user_url,omitempty"` - CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` - CurrentUserURL *string `json:"current_user_url,omitempty"` - CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` - CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` - CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` - Links *struct { - Timeline *FeedLink `json:"timeline,omitempty"` - User *FeedLink `json:"user,omitempty"` - CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` - CurrentUser *FeedLink `json:"current_user,omitempty"` - CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` - CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` - CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` - } `json:"_links,omitempty"` + TimelineURL *string `json:"timeline_url,omitempty"` + UserURL *string `json:"user_url,omitempty"` + CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` + CurrentUserURL *string `json:"current_user_url,omitempty"` + CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` + CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` + CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` + Links *FeedLinks `json:"_links,omitempty"` +} + +// FeedLinks represents the links in a Feed. +type FeedLinks struct { + Timeline *FeedLink `json:"timeline,omitempty"` + User *FeedLink `json:"user,omitempty"` + CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` + CurrentUser *FeedLink `json:"current_user,omitempty"` + CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` + CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` + CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` } // ListFeeds lists all the feeds available to the authenticated user. diff --git a/github/activity_notifications_test.go b/github/activity_notifications_test.go index bce2136a3b9..f46a12f474f 100644 --- a/github/activity_notifications_test.go +++ b/github/activity_notifications_test.go @@ -312,3 +312,83 @@ func TestActivityService_DeleteThreadSubscription(t *testing.T) { return client.Activity.DeleteThreadSubscription(ctx, "1") }) } + +func TestNotification_Marshal(t *testing.T) { + testJSONMarshal(t, &Notification{}, "{}") + + u := &Notification{ + ID: String("id"), + Repository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + Subject: &NotificationSubject{ + Title: String("t"), + URL: String("u"), + LatestCommentURL: String("l"), + Type: String("t"), + }, + Reason: String("r"), + Unread: Bool(true), + UpdatedAt: &referenceTime, + LastReadAt: &referenceTime, + URL: String("u"), + } + + want := `{ + "id": "id", + "repository": { + "id": 1, + "url": "u", + "name": "n" + }, + "subject": { + "title": "t", + "url": "u", + "latest_comment_url": "l", + "type": "t" + }, + "reason": "r", + "unread": true, + "updated_at": ` + referenceTimeStr + `, + "last_read_at": ` + referenceTimeStr + `, + "url": "u" + }` + + testJSONMarshal(t, u, want) +} + +func TestNotificationSubject_Marshal(t *testing.T) { + testJSONMarshal(t, &NotificationSubject{}, "{}") + + u := &NotificationSubject{ + Title: String("t"), + URL: String("u"), + LatestCommentURL: String("l"), + Type: String("t"), + } + + want := `{ + "title": "t", + "url": "u", + "latest_comment_url": "l", + "type": "t" + }` + + testJSONMarshal(t, u, want) +} + +func TestMarkReadOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &markReadOptions{}, "{}") + + u := &markReadOptions{ + LastReadAt: referenceTime, + } + + want := `{ + "last_read_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/activity_star_test.go b/github/activity_star_test.go index 7e7a4a8ed8b..122c399366d 100644 --- a/github/activity_star_test.go +++ b/github/activity_star_test.go @@ -285,3 +285,81 @@ func TestActivityService_Unstar_invalidID(t *testing.T) { _, err := client.Activity.Unstar(ctx, "%", "%") testURLParseError(t, err) } + +func TestStarredRepository_Marshal(t *testing.T) { + testJSONMarshal(t, &StarredRepository{}, "{}") + + u := &StarredRepository{ + StarredAt: &Timestamp{referenceTime}, + Repository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + } + + want := `{ + "starred_at": ` + referenceTimeStr + `, + "repo": { + "id": 1, + "url": "u", + "name": "n" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestStargazer_Marshal(t *testing.T) { + testJSONMarshal(t, &Stargazer{}, "{}") + + u := &Stargazer{ + StarredAt: &Timestamp{referenceTime}, + User: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + } + + want := `{ + "starred_at": ` + referenceTimeStr + `, + "user": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/activity_test.go b/github/activity_test.go index c73f4795190..ef7cf32fca5 100644 --- a/github/activity_test.go +++ b/github/activity_test.go @@ -97,15 +97,7 @@ var wantFeeds = &Feeds{ CurrentUserOrganizationURLs: []string{ "https://github.com/organizations/github/defunkt.private.atom?token=abc123", }, - Links: &struct { - Timeline *FeedLink `json:"timeline,omitempty"` - User *FeedLink `json:"user,omitempty"` - CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` - CurrentUser *FeedLink `json:"current_user,omitempty"` - CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` - CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` - CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` - }{ + Links: &FeedLinks{ Timeline: &FeedLink{ HRef: String("https://github.com/timeline"), Type: String("application/atom+xml"), @@ -138,3 +130,181 @@ var wantFeeds = &Feeds{ }, }, } + +func TestFeedLink_Marshal(t *testing.T) { + testJSONMarshal(t, &FeedLink{}, "{}") + + u := &FeedLink{ + HRef: String("h"), + Type: String("t"), + } + + want := `{ + "href": "h", + "type": "t" + }` + + testJSONMarshal(t, u, want) +} + +func TestFeeds_Marshal(t *testing.T) { + testJSONMarshal(t, &Feeds{}, "{}") + + u := &Feeds{ + TimelineURL: String("t"), + UserURL: String("u"), + CurrentUserPublicURL: String("cupu"), + CurrentUserURL: String("cuu"), + CurrentUserActorURL: String("cuau"), + CurrentUserOrganizationURL: String("cuou"), + CurrentUserOrganizationURLs: []string{"a"}, + Links: &FeedLinks{ + Timeline: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + User: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserPublic: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUser: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserActor: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserOrganization: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserOrganizations: []*FeedLink{ + { + HRef: String("h"), + Type: String("t"), + }, + }, + }, + } + + want := `{ + "timeline_url": "t", + "user_url": "u", + "current_user_public_url": "cupu", + "current_user_url": "cuu", + "current_user_actor_url": "cuau", + "current_user_organization_url": "cuou", + "current_user_organization_urls": ["a"], + "_links": { + "timeline": { + "href": "h", + "type": "t" + }, + "user": { + "href": "h", + "type": "t" + }, + "current_user_public": { + "href": "h", + "type": "t" + }, + "current_user": { + "href": "h", + "type": "t" + }, + "current_user_actor": { + "href": "h", + "type": "t" + }, + "current_user_organization": { + "href": "h", + "type": "t" + }, + "current_user_organizations": [ + { + "href": "h", + "type": "t" + } + ] + } + }` + + testJSONMarshal(t, u, want) +} + +func TestFeedLinks_Marshal(t *testing.T) { + testJSONMarshal(t, &FeedLinks{}, "{}") + + u := &FeedLinks{ + Timeline: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + User: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserPublic: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUser: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserActor: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserOrganization: &FeedLink{ + HRef: String("h"), + Type: String("t"), + }, + CurrentUserOrganizations: []*FeedLink{ + { + HRef: String("h"), + Type: String("t"), + }, + }, + } + + want := `{ + "timeline": { + "href": "h", + "type": "t" + }, + "user": { + "href": "h", + "type": "t" + }, + "current_user_public": { + "href": "h", + "type": "t" + }, + "current_user": { + "href": "h", + "type": "t" + }, + "current_user_actor": { + "href": "h", + "type": "t" + }, + "current_user_organization": { + "href": "h", + "type": "t" + }, + "current_user_organizations": [ + { + "href": "h", + "type": "t" + } + ] + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/activity_watching_test.go b/github/activity_watching_test.go index c41205f4119..15b0f330783 100644 --- a/github/activity_watching_test.go +++ b/github/activity_watching_test.go @@ -257,3 +257,29 @@ func TestActivityService_DeleteRepositorySubscription(t *testing.T) { return client.Activity.DeleteRepositorySubscription(ctx, "o", "r") }) } + +func TestSubscription_Marshal(t *testing.T) { + testJSONMarshal(t, &Subscription{}, "{}") + + u := &Subscription{ + Subscribed: Bool(true), + Ignored: Bool(false), + Reason: String("r"), + CreatedAt: &Timestamp{referenceTime}, + URL: String("u"), + RepositoryURL: String("ru"), + ThreadURL: String("tu"), + } + + want := `{ + "subscribed": true, + "ignored": false, + "reason": "r", + "created_at": ` + referenceTimeStr + `, + "url": "u", + "repository_url": "ru", + "thread_url": "tu" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/admin_orgs_test.go b/github/admin_orgs_test.go index 85d73fb19d3..0282425bf06 100644 --- a/github/admin_orgs_test.go +++ b/github/admin_orgs_test.go @@ -141,3 +141,49 @@ func TestAdminOrgs_RenameByName(t *testing.T) { return resp, err }) } + +func TestCreateOrgRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &createOrgRequest{}, "{}") + + u := &createOrgRequest{ + Login: String("l"), + Admin: String("a"), + } + + want := `{ + "login": "l", + "admin": "a" + }` + + testJSONMarshal(t, u, want) +} + +func TestRenameOrgRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &renameOrgRequest{}, "{}") + + u := &renameOrgRequest{ + Login: String("l"), + } + + want := `{ + "login": "l" + }` + + testJSONMarshal(t, u, want) +} + +func TestRenameOrgResponse_Marshal(t *testing.T) { + testJSONMarshal(t, &renameOrgRequest{}, "{}") + + u := &RenameOrgResponse{ + Message: String("m"), + URL: String("u"), + } + + want := `{ + "message": "m", + "url": "u" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/admin_stats_test.go b/github/admin_stats_test.go index 0d20b74cad8..dab2bc21fce 100644 --- a/github/admin_stats_test.go +++ b/github/admin_stats_test.go @@ -209,3 +209,311 @@ var testAdminStats = &AdminStats{ TotalPullRequestComments: Int(30), }, } + +func TestIssueStats_Marshal(t *testing.T) { + testJSONMarshal(t, &IssueStats{}, "{}") + + u := &IssueStats{ + TotalIssues: Int(1), + OpenIssues: Int(1), + ClosedIssues: Int(1), + } + + want := `{ + "total_issues": 1, + "open_issues": 1, + "closed_issues": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestHookStats_Marshal(t *testing.T) { + testJSONMarshal(t, &HookStats{}, "{}") + + u := &HookStats{ + TotalHooks: Int(1), + ActiveHooks: Int(1), + InactiveHooks: Int(1), + } + + want := `{ + "total_hooks": 1, + "active_hooks": 1, + "inactive_hooks": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestMilestoneStats_Marshal(t *testing.T) { + testJSONMarshal(t, &MilestoneStats{}, "{}") + + u := &MilestoneStats{ + TotalMilestones: Int(1), + OpenMilestones: Int(1), + ClosedMilestones: Int(1), + } + + want := `{ + "total_milestones": 1, + "open_milestones": 1, + "closed_milestones": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestOrgStats_Marshal(t *testing.T) { + testJSONMarshal(t, &OrgStats{}, "{}") + + u := &OrgStats{ + TotalOrgs: Int(1), + DisabledOrgs: Int(1), + TotalTeams: Int(1), + TotalTeamMembers: Int(1), + } + + want := `{ + "total_orgs": 1, + "disabled_orgs": 1, + "total_teams": 1, + "total_team_members": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestCommentStats_Marshal(t *testing.T) { + testJSONMarshal(t, &CommentStats{}, "{}") + + u := &CommentStats{ + TotalCommitComments: Int(1), + TotalGistComments: Int(1), + TotalIssueComments: Int(1), + TotalPullRequestComments: Int(1), + } + + want := `{ + "total_commit_comments": 1, + "total_gist_comments": 1, + "total_issue_comments": 1, + "total_pull_request_comments": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestPageStats_Marshal(t *testing.T) { + testJSONMarshal(t, &PageStats{}, "{}") + + u := &PageStats{ + TotalPages: Int(1), + } + + want := `{ + "total_pages": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestUserStats_Marshal(t *testing.T) { + testJSONMarshal(t, &UserStats{}, "{}") + + u := &UserStats{ + TotalUsers: Int(1), + AdminUsers: Int(1), + SuspendedUsers: Int(1), + } + + want := `{ + "total_users": 1, + "admin_users": 1, + "suspended_users": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestGistStats_Marshal(t *testing.T) { + testJSONMarshal(t, &GistStats{}, "{}") + + u := &GistStats{ + TotalGists: Int(1), + PrivateGists: Int(1), + PublicGists: Int(1), + } + + want := `{ + "total_gists": 1, + "private_gists": 1, + "public_gists": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestPullStats_Marshal(t *testing.T) { + testJSONMarshal(t, &PullStats{}, "{}") + + u := &PullStats{ + TotalPulls: Int(1), + MergedPulls: Int(1), + MergablePulls: Int(1), + UnmergablePulls: Int(1), + } + + want := `{ + "total_pulls": 1, + "merged_pulls": 1, + "mergeable_pulls": 1, + "unmergeable_pulls": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestRepoStats_Marshal(t *testing.T) { + testJSONMarshal(t, &RepoStats{}, "{}") + + u := &RepoStats{ + TotalRepos: Int(1), + RootRepos: Int(1), + ForkRepos: Int(1), + OrgRepos: Int(1), + TotalPushes: Int(1), + TotalWikis: Int(1), + } + + want := `{ + "total_repos": 1, + "root_repos": 1, + "fork_repos": 1, + "org_repos": 1, + "total_pushes": 1, + "total_wikis": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestAdminStats_Marshal(t *testing.T) { + testJSONMarshal(t, &AdminStats{}, "{}") + + u := &AdminStats{ + Repos: &RepoStats{ + TotalRepos: Int(212), + RootRepos: Int(194), + ForkRepos: Int(18), + OrgRepos: Int(51), + TotalPushes: Int(3082), + TotalWikis: Int(15), + }, + Hooks: &HookStats{ + TotalHooks: Int(27), + ActiveHooks: Int(23), + InactiveHooks: Int(4), + }, + Pages: &PageStats{ + TotalPages: Int(36), + }, + Orgs: &OrgStats{ + TotalOrgs: Int(33), + DisabledOrgs: Int(0), + TotalTeams: Int(60), + TotalTeamMembers: Int(314), + }, + Users: &UserStats{ + TotalUsers: Int(254), + AdminUsers: Int(45), + SuspendedUsers: Int(21), + }, + Pulls: &PullStats{ + TotalPulls: Int(86), + MergedPulls: Int(60), + MergablePulls: Int(21), + UnmergablePulls: Int(3), + }, + Issues: &IssueStats{ + TotalIssues: Int(179), + OpenIssues: Int(83), + ClosedIssues: Int(96), + }, + Milestones: &MilestoneStats{ + TotalMilestones: Int(7), + OpenMilestones: Int(6), + ClosedMilestones: Int(1), + }, + Gists: &GistStats{ + TotalGists: Int(178), + PrivateGists: Int(151), + PublicGists: Int(25), + }, + Comments: &CommentStats{ + TotalCommitComments: Int(6), + TotalGistComments: Int(28), + TotalIssueComments: Int(366), + TotalPullRequestComments: Int(30), + }, + } + + want := `{ + "repos": { + "total_repos": 212, + "root_repos": 194, + "fork_repos": 18, + "org_repos": 51, + "total_pushes": 3082, + "total_wikis": 15 + }, + "hooks": { + "total_hooks": 27, + "active_hooks": 23, + "inactive_hooks": 4 + }, + "pages": { + "total_pages": 36 + }, + "orgs": { + "total_orgs": 33, + "disabled_orgs": 0, + "total_teams": 60, + "total_team_members": 314 + }, + "users": { + "total_users": 254, + "admin_users": 45, + "suspended_users": 21 + }, + "pulls": { + "total_pulls": 86, + "merged_pulls": 60, + "mergeable_pulls": 21, + "unmergeable_pulls": 3 + }, + "issues": { + "total_issues": 179, + "open_issues": 83, + "closed_issues": 96 + }, + "milestones": { + "total_milestones": 7, + "open_milestones": 6, + "closed_milestones": 1 + }, + "gists": { + "total_gists": 178, + "private_gists": 151, + "public_gists": 25 + }, + "comments": { + "total_commit_comments": 6, + "total_gist_comments": 28, + "total_issue_comments": 366, + "total_pull_request_comments": 30 + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/admin_test.go b/github/admin_test.go index 0e8deaea777..207121c35cc 100644 --- a/github/admin_test.go +++ b/github/admin_test.go @@ -157,3 +157,113 @@ func TestAdminService_UserLDAPMapping_String(t *testing.T) { t.Errorf("UserLDAPMapping.String = `%v`, want `%v`", got, want) } } + +func TestTeamLDAPMapping_Marshal(t *testing.T) { + testJSONMarshal(t, &TeamLDAPMapping{}, "{}") + + u := &TeamLDAPMapping{ + ID: Int64(1), + LDAPDN: String("ldapdn"), + URL: String("u"), + Name: String("n"), + Slug: String("s"), + Description: String("d"), + Privacy: String("p"), + Permission: String("per"), + MembersURL: String("mu"), + RepositoriesURL: String("ru"), + } + + want := `{ + "id": 1, + "ldap_dn": "ldapdn", + "url": "u", + "name": "n", + "slug": "s", + "description": "d", + "privacy": "p", + "permission": "per", + "members_url": "mu", + "repositories_url": "ru" + }` + + testJSONMarshal(t, u, want) +} + +func TestUserLDAPMapping_Marshal(t *testing.T) { + testJSONMarshal(t, &UserLDAPMapping{}, "{}") + + u := &UserLDAPMapping{ + ID: Int64(1), + LDAPDN: String("ldapdn"), + Login: String("l"), + AvatarURL: String("au"), + GravatarID: String("gi"), + Type: String("t"), + SiteAdmin: Bool(true), + URL: String("u"), + EventsURL: String("eu"), + FollowingURL: String("fu"), + FollowersURL: String("fu"), + GistsURL: String("gu"), + OrganizationsURL: String("ou"), + ReceivedEventsURL: String("reu"), + ReposURL: String("ru"), + StarredURL: String("su"), + SubscriptionsURL: String("subu"), + } + + want := `{ + "id": 1, + "ldap_dn": "ldapdn", + "login": "l", + "avatar_url": "au", + "gravatar_id": "gi", + "type": "t", + "site_admin": true, + "url": "u", + "events_url": "eu", + "following_url": "fu", + "followers_url": "fu", + "gists_url": "gu", + "organizations_url": "ou", + "received_events_url": "reu", + "repos_url": "ru", + "starred_url": "su", + "subscriptions_url": "subu" + }` + + testJSONMarshal(t, u, want) +} + +func TestEnterprise_Marshal(t *testing.T) { + testJSONMarshal(t, &Enterprise{}, "{}") + + u := &Enterprise{ + ID: Int(1), + Slug: String("s"), + Name: String("n"), + NodeID: String("nid"), + AvatarURL: String("au"), + Description: String("d"), + WebsiteURL: String("wu"), + HTMLURL: String("hu"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + } + + want := `{ + "id": 1, + "slug": "s", + "name": "n", + "node_id": "nid", + "avatar_url": "au", + "description": "d", + "website_url": "wu", + "html_url": "hu", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/admin_users_test.go b/github/admin_users_test.go index 253ddf6fad7..cd008c37532 100644 --- a/github/admin_users_test.go +++ b/github/admin_users_test.go @@ -175,3 +175,99 @@ func TestUserImpersonation_Delete(t *testing.T) { return client.Admin.DeleteUserImpersonation(ctx, "github") }) } + +func TestCreateUserRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &createUserRequest{}, "{}") + + u := &createUserRequest{ + Login: String("l"), + Email: String("e"), + } + + want := `{ + "login": "l", + "email": "e" + }` + + testJSONMarshal(t, u, want) +} + +func TestImpersonateUserOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &ImpersonateUserOptions{}, "{}") + + u := &ImpersonateUserOptions{ + Scopes: []string{ + "s", + }, + } + + want := `{ + "scopes": ["s"] + }` + + testJSONMarshal(t, u, want) +} + +func TestOAuthAPP_Marshal(t *testing.T) { + testJSONMarshal(t, &OAuthAPP{}, "{}") + + u := &OAuthAPP{ + URL: String("u"), + Name: String("n"), + ClientID: String("cid"), + } + + want := `{ + "url": "u", + "name": "n", + "client_id": "cid" + }` + + testJSONMarshal(t, u, want) +} + +func TestUserAuthorization_Marshal(t *testing.T) { + testJSONMarshal(t, &UserAuthorization{}, "{}") + + u := &UserAuthorization{ + ID: Int64(1), + URL: String("u"), + Scopes: []string{ + "s", + }, + Token: String("t"), + TokenLastEight: String("tle"), + HashedToken: String("ht"), + App: &OAuthAPP{ + URL: String("u"), + Name: String("n"), + ClientID: String("cid"), + }, + Note: String("n"), + NoteURL: String("nu"), + UpdatedAt: &Timestamp{referenceTime}, + CreatedAt: &Timestamp{referenceTime}, + Fingerprint: String("f"), + } + + want := `{ + "id": 1, + "url": "u", + "scopes": ["s"], + "token": "t", + "token_last_eight": "tle", + "hashed_token": "ht", + "app": { + "url": "u", + "name": "n", + "client_id": "cid" + }, + "note": "n", + "note_url": "nu", + "updated_at": ` + referenceTimeStr + `, + "created_at": ` + referenceTimeStr + `, + "fingerprint": "f" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/apps_installation_test.go b/github/apps_installation_test.go index 563e0d2fa16..56f0ad9e81d 100644 --- a/github/apps_installation_test.go +++ b/github/apps_installation_test.go @@ -173,3 +173,29 @@ func TestAppsService_RevokeInstallationToken(t *testing.T) { return client.Apps.RevokeInstallationToken(ctx) }) } + +func TestListRepositories_Marshal(t *testing.T) { + testJSONMarshal(t, &ListRepositories{}, "{}") + + u := &ListRepositories{ + TotalCount: Int(1), + Repositories: []*Repository{ + { + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + } + + want := `{ + "total_count": 1, + "repositories": [{ + "id":1, + "name":"n", + "url":"u" + }] + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/apps_manifest_test.go b/github/apps_manifest_test.go index 5fbe9ff18b0..a5d230d048a 100644 --- a/github/apps_manifest_test.go +++ b/github/apps_manifest_test.go @@ -66,3 +66,79 @@ func TestGetConfig(t *testing.T) { return resp, err }) } + +func TestAppConfig_Marshal(t *testing.T) { + testJSONMarshal(t, &AppConfig{}, "{}") + + u := &AppConfig{ + ID: Int64(1), + NodeID: String("nid"), + Owner: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + Name: String("n"), + Description: String("d"), + ExternalURL: String("eu"), + HTMLURL: String("hu"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + ClientID: String("ci"), + ClientSecret: String("cs"), + WebhookSecret: String("ws"), + PEM: String("pem"), + } + + want := `{ + "id": 1, + "node_id": "nid", + "owner": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + }, + "name": "n", + "description": "d", + "external_url": "eu", + "html_url": "hu", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "client_id": "ci", + "client_secret": "cs", + "webhook_secret": "ws", + "pem": "pem" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/apps_marketplace_test.go b/github/apps_marketplace_test.go index 10c7dea1a0d..dcf5eb89ca1 100644 --- a/github/apps_marketplace_test.go +++ b/github/apps_marketplace_test.go @@ -235,3 +235,251 @@ func TestMarketplaceService_Stubbed_ListMarketplacePurchasesForUser(t *testing.T t.Errorf("Marketplace.ListMarketplacePurchasesForUser returned %+v, want %+v", purchases, want) } } + +func TestMarketplacePlan_Marshal(t *testing.T) { + testJSONMarshal(t, &MarketplacePlan{}, "{}") + + u := &MarketplacePlan{ + URL: String("u"), + AccountsURL: String("au"), + ID: Int64(1), + Number: Int(1), + Name: String("n"), + Description: String("d"), + MonthlyPriceInCents: Int(1), + YearlyPriceInCents: Int(1), + PriceModel: String("pm"), + UnitName: String("un"), + Bullets: &[]string{"b"}, + State: String("s"), + HasFreeTrial: Bool(false), + } + + want := `{ + "url": "u", + "accounts_url": "au", + "id": 1, + "number": 1, + "name": "n", + "description": "d", + "monthly_price_in_cents": 1, + "yearly_price_in_cents": 1, + "price_model": "pm", + "unit_name": "un", + "bullets": ["b"], + "state": "s", + "has_free_trial": false + }` + + testJSONMarshal(t, u, want) +} + +func TestMarketplacePurchase_Marshal(t *testing.T) { + testJSONMarshal(t, &MarketplacePurchase{}, "{}") + + u := &MarketplacePurchase{ + BillingCycle: String("bc"), + NextBillingDate: &Timestamp{referenceTime}, + UnitCount: Int(1), + Plan: &MarketplacePlan{ + URL: String("u"), + AccountsURL: String("au"), + ID: Int64(1), + Number: Int(1), + Name: String("n"), + Description: String("d"), + MonthlyPriceInCents: Int(1), + YearlyPriceInCents: Int(1), + PriceModel: String("pm"), + UnitName: String("un"), + Bullets: &[]string{"b"}, + State: String("s"), + HasFreeTrial: Bool(false), + }, + OnFreeTrial: Bool(false), + FreeTrialEndsOn: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + } + + want := `{ + "billing_cycle": "bc", + "next_billing_date": ` + referenceTimeStr + `, + "unit_count": 1, + "plan": { + "url": "u", + "accounts_url": "au", + "id": 1, + "number": 1, + "name": "n", + "description": "d", + "monthly_price_in_cents": 1, + "yearly_price_in_cents": 1, + "price_model": "pm", + "unit_name": "un", + "bullets": ["b"], + "state": "s", + "has_free_trial": false + }, + "on_free_trial": false, + "free_trial_ends_on": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} + +func TestMarketplacePendingChange_Marshal(t *testing.T) { + testJSONMarshal(t, &MarketplacePendingChange{}, "{}") + + u := &MarketplacePendingChange{ + EffectiveDate: &Timestamp{referenceTime}, + UnitCount: Int(1), + ID: Int64(1), + Plan: &MarketplacePlan{ + URL: String("u"), + AccountsURL: String("au"), + ID: Int64(1), + Number: Int(1), + Name: String("n"), + Description: String("d"), + MonthlyPriceInCents: Int(1), + YearlyPriceInCents: Int(1), + PriceModel: String("pm"), + UnitName: String("un"), + Bullets: &[]string{"b"}, + State: String("s"), + HasFreeTrial: Bool(false), + }, + } + + want := `{ + "effective_date": ` + referenceTimeStr + `, + "unit_count": 1, + "id": 1, + "plan": { + "url": "u", + "accounts_url": "au", + "id": 1, + "number": 1, + "name": "n", + "description": "d", + "monthly_price_in_cents": 1, + "yearly_price_in_cents": 1, + "price_model": "pm", + "unit_name": "un", + "bullets": ["b"], + "state": "s", + "has_free_trial": false + } + }` + + testJSONMarshal(t, u, want) +} + +func TestMarketplacePlanAccount_Marshal(t *testing.T) { + testJSONMarshal(t, &MarketplacePlanAccount{}, "{}") + + u := &MarketplacePlanAccount{ + URL: String("u"), + Type: String("t"), + ID: Int64(1), + Login: String("l"), + OrganizationBillingEmail: String("obe"), + MarketplacePurchase: &MarketplacePurchase{ + BillingCycle: String("bc"), + NextBillingDate: &Timestamp{referenceTime}, + UnitCount: Int(1), + Plan: &MarketplacePlan{ + URL: String("u"), + AccountsURL: String("au"), + ID: Int64(1), + Number: Int(1), + Name: String("n"), + Description: String("d"), + MonthlyPriceInCents: Int(1), + YearlyPriceInCents: Int(1), + PriceModel: String("pm"), + UnitName: String("un"), + Bullets: &[]string{"b"}, + State: String("s"), + HasFreeTrial: Bool(false), + }, + OnFreeTrial: Bool(false), + FreeTrialEndsOn: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + }, + MarketplacePendingChange: &MarketplacePendingChange{ + EffectiveDate: &Timestamp{referenceTime}, + UnitCount: Int(1), + ID: Int64(1), + Plan: &MarketplacePlan{ + URL: String("u"), + AccountsURL: String("au"), + ID: Int64(1), + Number: Int(1), + Name: String("n"), + Description: String("d"), + MonthlyPriceInCents: Int(1), + YearlyPriceInCents: Int(1), + PriceModel: String("pm"), + UnitName: String("un"), + Bullets: &[]string{"b"}, + State: String("s"), + HasFreeTrial: Bool(false), + }, + }, + } + + want := `{ + "url": "u", + "type": "t", + "id": 1, + "login": "l", + "organization_billing_email": "obe", + "marketplace_purchase": { + "billing_cycle": "bc", + "next_billing_date": ` + referenceTimeStr + `, + "unit_count": 1, + "plan": { + "url": "u", + "accounts_url": "au", + "id": 1, + "number": 1, + "name": "n", + "description": "d", + "monthly_price_in_cents": 1, + "yearly_price_in_cents": 1, + "price_model": "pm", + "unit_name": "un", + "bullets": ["b"], + "state": "s", + "has_free_trial": false + }, + "on_free_trial": false, + "free_trial_ends_on": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + ` + }, + "marketplace_pending_change": { + "effective_date": ` + referenceTimeStr + `, + "unit_count": 1, + "id": 1, + "plan": { + "url": "u", + "accounts_url": "au", + "id": 1, + "number": 1, + "name": "n", + "description": "d", + "monthly_price_in_cents": 1, + "yearly_price_in_cents": 1, + "price_model": "pm", + "unit_name": "un", + "bullets": ["b"], + "state": "s", + "has_free_trial": false + } + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/apps_test.go b/github/apps_test.go index 841fe173742..5079d41614a 100644 --- a/github/apps_test.go +++ b/github/apps_test.go @@ -594,3 +594,633 @@ func TestAppsService_FindUserInstallation(t *testing.T) { return resp, err }) } + +func TestContentReference_Marshal(t *testing.T) { + testJSONMarshal(t, &ContentReference{}, "{}") + + u := &ContentReference{ + ID: Int64(1), + NodeID: String("nid"), + Reference: String("r"), + } + + want := `{ + "id": 1, + "node_id": "nid", + "reference": "r" + }` + + testJSONMarshal(t, u, want) +} + +func TestAttachment_Marshal(t *testing.T) { + testJSONMarshal(t, &Attachment{}, "{}") + + u := &Attachment{ + ID: Int64(1), + Title: String("t"), + Body: String("b"), + } + + want := `{ + "id": 1, + "title": "t", + "body": "b" + }` + + testJSONMarshal(t, u, want) +} + +func TestInstallationPermissions_Marshal(t *testing.T) { + testJSONMarshal(t, &InstallationPermissions{}, "{}") + + u := &InstallationPermissions{ + Actions: String("a"), + Administration: String("ad"), + Checks: String("c"), + Contents: String("co"), + ContentReferences: String("cr"), + Deployments: String("d"), + Environments: String("e"), + Issues: String("i"), + Metadata: String("md"), + Members: String("m"), + OrganizationAdministration: String("oa"), + OrganizationHooks: String("oh"), + OrganizationPlan: String("op"), + OrganizationPreReceiveHooks: String("opr"), + OrganizationProjects: String("op"), + OrganizationSecrets: String("os"), + OrganizationSelfHostedRunners: String("osh"), + OrganizationUserBlocking: String("oub"), + Packages: String("pkg"), + Pages: String("pg"), + PullRequests: String("pr"), + RepositoryHooks: String("rh"), + RepositoryProjects: String("rp"), + RepositoryPreReceiveHooks: String("rprh"), + Secrets: String("s"), + SecretScanningAlerts: String("ssa"), + SecurityEvents: String("se"), + SingleFile: String("sf"), + Statuses: String("s"), + TeamDiscussions: String("td"), + VulnerabilityAlerts: String("va"), + Workflows: String("w"), + } + + want := `{ + "actions": "a", + "administration": "ad", + "checks": "c", + "contents": "co", + "content_references": "cr", + "deployments": "d", + "environments": "e", + "issues": "i", + "metadata": "md", + "members": "m", + "organization_administration": "oa", + "organization_hooks": "oh", + "organization_plan": "op", + "organization_pre_receive_hooks": "opr", + "organization_projects": "op", + "organization_secrets": "os", + "organization_self_hosted_runners": "osh", + "organization_user_blocking": "oub", + "packages": "pkg", + "pages": "pg", + "pull_requests": "pr", + "repository_hooks": "rh", + "repository_projects": "rp", + "repository_pre_receive_hooks": "rprh", + "secrets": "s", + "secret_scanning_alerts": "ssa", + "security_events": "se", + "single_file": "sf", + "statuses": "s", + "team_discussions": "td", + "vulnerability_alerts":"va", + "workflows": "w" + }` + + testJSONMarshal(t, u, want) +} + +func TestInstallation_Marshal(t *testing.T) { + testJSONMarshal(t, &Installation{}, "{}") + + u := &Installation{ + ID: Int64(1), + NodeID: String("nid"), + AppID: Int64(1), + AppSlug: String("as"), + TargetID: Int64(1), + Account: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + AccessTokensURL: String("atu"), + RepositoriesURL: String("ru"), + HTMLURL: String("hu"), + TargetType: String("tt"), + SingleFileName: String("sfn"), + RepositorySelection: String("rs"), + Events: []string{"e"}, + SingleFilePaths: []string{"s"}, + Permissions: &InstallationPermissions{ + Actions: String("a"), + Administration: String("ad"), + Checks: String("c"), + Contents: String("co"), + ContentReferences: String("cr"), + Deployments: String("d"), + Environments: String("e"), + Issues: String("i"), + Metadata: String("md"), + Members: String("m"), + OrganizationAdministration: String("oa"), + OrganizationHooks: String("oh"), + OrganizationPlan: String("op"), + OrganizationPreReceiveHooks: String("opr"), + OrganizationProjects: String("op"), + OrganizationSecrets: String("os"), + OrganizationSelfHostedRunners: String("osh"), + OrganizationUserBlocking: String("oub"), + Packages: String("pkg"), + Pages: String("pg"), + PullRequests: String("pr"), + RepositoryHooks: String("rh"), + RepositoryProjects: String("rp"), + RepositoryPreReceiveHooks: String("rprh"), + Secrets: String("s"), + SecretScanningAlerts: String("ssa"), + SecurityEvents: String("se"), + SingleFile: String("sf"), + Statuses: String("s"), + TeamDiscussions: String("td"), + VulnerabilityAlerts: String("va"), + Workflows: String("w"), + }, + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + HasMultipleSingleFiles: Bool(false), + SuspendedBy: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + SuspendedAt: &Timestamp{referenceTime}, + } + + want := `{ + "id": 1, + "node_id": "nid", + "app_id": 1, + "app_slug": "as", + "target_id": 1, + "account": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + }, + "access_tokens_url": "atu", + "repositories_url": "ru", + "html_url": "hu", + "target_type": "tt", + "single_file_name": "sfn", + "repository_selection": "rs", + "events": [ + "e" + ], + "single_file_paths": [ + "s" + ], + "permissions": { + "actions": "a", + "administration": "ad", + "checks": "c", + "contents": "co", + "content_references": "cr", + "deployments": "d", + "environments": "e", + "issues": "i", + "metadata": "md", + "members": "m", + "organization_administration": "oa", + "organization_hooks": "oh", + "organization_plan": "op", + "organization_pre_receive_hooks": "opr", + "organization_projects": "op", + "organization_secrets": "os", + "organization_self_hosted_runners": "osh", + "organization_user_blocking": "oub", + "packages": "pkg", + "pages": "pg", + "pull_requests": "pr", + "repository_hooks": "rh", + "repository_projects": "rp", + "repository_pre_receive_hooks": "rprh", + "secrets": "s", + "secret_scanning_alerts": "ssa", + "security_events": "se", + "single_file": "sf", + "statuses": "s", + "team_discussions": "td", + "vulnerability_alerts": "va", + "workflows": "w" + }, + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "has_multiple_single_files": false, + "suspended_by": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + }, + "suspended_at": ` + referenceTimeStr + ` + }` + + testJSONMarshal(t, u, want) +} + +func TestInstallationTokenOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &InstallationTokenOptions{}, "{}") + + u := &InstallationTokenOptions{ + RepositoryIDs: []int64{1}, + Permissions: &InstallationPermissions{ + Actions: String("a"), + Administration: String("ad"), + Checks: String("c"), + Contents: String("co"), + ContentReferences: String("cr"), + Deployments: String("d"), + Environments: String("e"), + Issues: String("i"), + Metadata: String("md"), + Members: String("m"), + OrganizationAdministration: String("oa"), + OrganizationHooks: String("oh"), + OrganizationPlan: String("op"), + OrganizationPreReceiveHooks: String("opr"), + OrganizationProjects: String("op"), + OrganizationSecrets: String("os"), + OrganizationSelfHostedRunners: String("osh"), + OrganizationUserBlocking: String("oub"), + Packages: String("pkg"), + Pages: String("pg"), + PullRequests: String("pr"), + RepositoryHooks: String("rh"), + RepositoryProjects: String("rp"), + RepositoryPreReceiveHooks: String("rprh"), + Secrets: String("s"), + SecretScanningAlerts: String("ssa"), + SecurityEvents: String("se"), + SingleFile: String("sf"), + Statuses: String("s"), + TeamDiscussions: String("td"), + VulnerabilityAlerts: String("va"), + Workflows: String("w"), + }, + } + + want := `{ + "repository_ids": [1], + "permissions": { + "actions": "a", + "administration": "ad", + "checks": "c", + "contents": "co", + "content_references": "cr", + "deployments": "d", + "environments": "e", + "issues": "i", + "metadata": "md", + "members": "m", + "organization_administration": "oa", + "organization_hooks": "oh", + "organization_plan": "op", + "organization_pre_receive_hooks": "opr", + "organization_projects": "op", + "organization_secrets": "os", + "organization_self_hosted_runners": "osh", + "organization_user_blocking": "oub", + "packages": "pkg", + "pages": "pg", + "pull_requests": "pr", + "repository_hooks": "rh", + "repository_projects": "rp", + "repository_pre_receive_hooks": "rprh", + "secrets": "s", + "secret_scanning_alerts": "ssa", + "security_events": "se", + "single_file": "sf", + "statuses": "s", + "team_discussions": "td", + "vulnerability_alerts": "va", + "workflows": "w" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestInstallationToken_Marshal(t *testing.T) { + testJSONMarshal(t, &InstallationToken{}, "{}") + + u := &InstallationToken{ + Token: String("t"), + ExpiresAt: &referenceTime, + Permissions: &InstallationPermissions{ + Actions: String("a"), + Administration: String("ad"), + Checks: String("c"), + Contents: String("co"), + ContentReferences: String("cr"), + Deployments: String("d"), + Environments: String("e"), + Issues: String("i"), + Metadata: String("md"), + Members: String("m"), + OrganizationAdministration: String("oa"), + OrganizationHooks: String("oh"), + OrganizationPlan: String("op"), + OrganizationPreReceiveHooks: String("opr"), + OrganizationProjects: String("op"), + OrganizationSecrets: String("os"), + OrganizationSelfHostedRunners: String("osh"), + OrganizationUserBlocking: String("oub"), + Packages: String("pkg"), + Pages: String("pg"), + PullRequests: String("pr"), + RepositoryHooks: String("rh"), + RepositoryProjects: String("rp"), + RepositoryPreReceiveHooks: String("rprh"), + Secrets: String("s"), + SecretScanningAlerts: String("ssa"), + SecurityEvents: String("se"), + SingleFile: String("sf"), + Statuses: String("s"), + TeamDiscussions: String("td"), + VulnerabilityAlerts: String("va"), + Workflows: String("w"), + }, + Repositories: []*Repository{ + { + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + } + + want := `{ + "token": "t", + "expires_at": ` + referenceTimeStr + `, + "permissions": { + "actions": "a", + "administration": "ad", + "checks": "c", + "contents": "co", + "content_references": "cr", + "deployments": "d", + "environments": "e", + "issues": "i", + "metadata": "md", + "members": "m", + "organization_administration": "oa", + "organization_hooks": "oh", + "organization_plan": "op", + "organization_pre_receive_hooks": "opr", + "organization_projects": "op", + "organization_secrets": "os", + "organization_self_hosted_runners": "osh", + "organization_user_blocking": "oub", + "packages": "pkg", + "pages": "pg", + "pull_requests": "pr", + "repository_hooks": "rh", + "repository_projects": "rp", + "repository_pre_receive_hooks": "rprh", + "secrets": "s", + "secret_scanning_alerts": "ssa", + "security_events": "se", + "single_file": "sf", + "statuses": "s", + "team_discussions": "td", + "vulnerability_alerts": "va", + "workflows": "w" + }, + "repositories": [ + { + "id": 1, + "url": "u", + "name": "n" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestApp_Marshal(t *testing.T) { + testJSONMarshal(t, &App{}, "{}") + + u := &App{ + ID: Int64(1), + Slug: String("s"), + NodeID: String("nid"), + Owner: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + Name: String("n"), + Description: String("d"), + ExternalURL: String("eu"), + HTMLURL: String("hu"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + Permissions: &InstallationPermissions{ + Actions: String("a"), + Administration: String("ad"), + Checks: String("c"), + Contents: String("co"), + ContentReferences: String("cr"), + Deployments: String("d"), + Environments: String("e"), + Issues: String("i"), + Metadata: String("md"), + Members: String("m"), + OrganizationAdministration: String("oa"), + OrganizationHooks: String("oh"), + OrganizationPlan: String("op"), + OrganizationPreReceiveHooks: String("opr"), + OrganizationProjects: String("op"), + OrganizationSecrets: String("os"), + OrganizationSelfHostedRunners: String("osh"), + OrganizationUserBlocking: String("oub"), + Packages: String("pkg"), + Pages: String("pg"), + PullRequests: String("pr"), + RepositoryHooks: String("rh"), + RepositoryProjects: String("rp"), + RepositoryPreReceiveHooks: String("rprh"), + Secrets: String("s"), + SecretScanningAlerts: String("ssa"), + SecurityEvents: String("se"), + SingleFile: String("sf"), + Statuses: String("s"), + TeamDiscussions: String("td"), + VulnerabilityAlerts: String("va"), + Workflows: String("w"), + }, + Events: []string{"s"}, + } + + want := `{ + "id": 1, + "slug": "s", + "node_id": "nid", + "owner": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + }, + "name": "n", + "description": "d", + "external_url": "eu", + "html_url": "hu", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "permissions": { + "actions": "a", + "administration": "ad", + "checks": "c", + "contents": "co", + "content_references": "cr", + "deployments": "d", + "environments": "e", + "issues": "i", + "metadata": "md", + "members": "m", + "organization_administration": "oa", + "organization_hooks": "oh", + "organization_plan": "op", + "organization_pre_receive_hooks": "opr", + "organization_projects": "op", + "organization_secrets": "os", + "organization_self_hosted_runners": "osh", + "organization_user_blocking": "oub", + "packages": "pkg", + "pages": "pg", + "pull_requests": "pr", + "repository_hooks": "rh", + "repository_projects": "rp", + "repository_pre_receive_hooks": "rprh", + "secrets": "s", + "secret_scanning_alerts": "ssa", + "security_events": "se", + "single_file": "sf", + "statuses": "s", + "team_discussions": "td", + "vulnerability_alerts": "va", + "workflows": "w" + }, + "events": ["s"] + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/authorizations_test.go b/github/authorizations_test.go index b1b3ed6c574..bd7ff29d811 100644 --- a/github/authorizations_test.go +++ b/github/authorizations_test.go @@ -203,3 +203,185 @@ func TestAuthorizationsService_DeleteImpersonation(t *testing.T) { return client.Authorizations.DeleteImpersonation(ctx, "u") }) } + +func TestAuthorizationUpdateRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &AuthorizationUpdateRequest{}, "{}") + + u := &AuthorizationUpdateRequest{ + Scopes: []string{"s"}, + AddScopes: []string{"a"}, + RemoveScopes: []string{"r"}, + Note: String("n"), + NoteURL: String("nu"), + Fingerprint: String("f"), + } + + want := `{ + "scopes": ["s"], + "add_scopes": ["a"], + "remove_scopes": ["r"], + "note": "n", + "note_url": "nu", + "fingerprint": "f" + }` + + testJSONMarshal(t, u, want) +} + +func TestAuthorizationRequest_Marshal(t *testing.T) { + testJSONMarshal(t, &AuthorizationRequest{}, "{}") + + u := &AuthorizationRequest{ + Scopes: []Scope{"s"}, + ClientID: String("cid"), + ClientSecret: String("cs"), + Note: String("n"), + NoteURL: String("nu"), + Fingerprint: String("f"), + } + + want := `{ + "scopes": ["s"], + "client_id": "cid", + "client_secret": "cs", + "note": "n", + "note_url": "nu", + "fingerprint": "f" + }` + + testJSONMarshal(t, u, want) +} + +func TestAuthorizationApp_Marshal(t *testing.T) { + testJSONMarshal(t, &AuthorizationApp{}, "{}") + + u := &AuthorizationApp{ + URL: String("u"), + Name: String("n"), + ClientID: String("cid"), + } + + want := `{ + "url": "u", + "name": "n", + "client_id": "cid" + }` + + testJSONMarshal(t, u, want) +} + +func TestGrant_Marshal(t *testing.T) { + testJSONMarshal(t, &Grant{}, "{}") + + u := &Grant{ + ID: Int64(1), + URL: String("u"), + App: &AuthorizationApp{ + URL: String("u"), + Name: String("n"), + ClientID: String("cid"), + }, + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + Scopes: []string{"s"}, + } + + want := `{ + "id": 1, + "url": "u", + "app": { + "url": "u", + "name": "n", + "client_id": "cid" + }, + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "scopes": ["s"] + }` + + testJSONMarshal(t, u, want) +} + +func TestAuthorization_Marshal(t *testing.T) { + testJSONMarshal(t, &Authorization{}, "{}") + + u := &Authorization{ + ID: Int64(1), + URL: String("u"), + Scopes: []Scope{"s"}, + Token: String("t"), + TokenLastEight: String("tle"), + HashedToken: String("ht"), + App: &AuthorizationApp{ + URL: String("u"), + Name: String("n"), + ClientID: String("cid"), + }, + Note: String("n"), + NoteURL: String("nu"), + UpdatedAt: &Timestamp{referenceTime}, + CreatedAt: &Timestamp{referenceTime}, + Fingerprint: String("f"), + User: &User{ + Login: String("l"), + ID: Int64(1), + URL: String("u"), + AvatarURL: String("a"), + GravatarID: String("g"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + Hireable: Bool(true), + Bio: String("b"), + TwitterUsername: String("t"), + PublicRepos: Int(1), + Followers: Int(1), + Following: Int(1), + CreatedAt: &Timestamp{referenceTime}, + SuspendedAt: &Timestamp{referenceTime}, + }, + } + + want := `{ + "id": 1, + "url": "u", + "scopes": ["s"], + "token": "t", + "token_last_eight": "tle", + "hashed_token": "ht", + "app": { + "url": "u", + "name": "n", + "client_id": "cid" + }, + "note": "n", + "note_url": "nu", + "updated_at": ` + referenceTimeStr + `, + "created_at": ` + referenceTimeStr + `, + "fingerprint": "f", + "user": { + "login": "l", + "id": 1, + "avatar_url": "a", + "gravatar_id": "g", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e", + "hireable": true, + "bio": "b", + "twitter_username": "t", + "public_repos": 1, + "followers": 1, + "following": 1, + "created_at": ` + referenceTimeStr + `, + "suspended_at": ` + referenceTimeStr + `, + "url": "u" + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/billing_test.go b/github/billing_test.go index 92fada80c0a..7d1c2a1d055 100644 --- a/github/billing_test.go +++ b/github/billing_test.go @@ -297,3 +297,85 @@ func TestBillingService_GetStorageBillingUser_invalidUser(t *testing.T) { _, _, err := client.Billing.GetStorageBillingUser(ctx, "%") testURLParseError(t, err) } + +func TestMinutesUsedBreakdown_Marshal(t *testing.T) { + testJSONMarshal(t, &MinutesUsedBreakdown{}, "{}") + + u := &MinutesUsedBreakdown{ + Ubuntu: 1, + MacOS: 1, + Windows: 1, + } + + want := `{ + "UBUNTU": 1, + "MACOS": 1, + "WINDOWS": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestActionBilling_Marshal(t *testing.T) { + testJSONMarshal(t, &MinutesUsedBreakdown{}, "{}") + + u := &ActionBilling{ + TotalMinutesUsed: 1, + TotalPaidMinutesUsed: 1, + IncludedMinutes: 1, + MinutesUsedBreakdown: MinutesUsedBreakdown{ + Ubuntu: 1, + MacOS: 1, + Windows: 1, + }, + } + + want := `{ + "total_minutes_used": 1, + "total_paid_minutes_used": 1, + "included_minutes": 1, + "minutes_used_breakdown": { + "UBUNTU": 1, + "MACOS": 1, + "WINDOWS": 1 + } + }` + + testJSONMarshal(t, u, want) +} + +func TestPackageBilling_Marshal(t *testing.T) { + testJSONMarshal(t, &PackageBilling{}, "{}") + + u := &PackageBilling{ + TotalGigabytesBandwidthUsed: 1, + TotalPaidGigabytesBandwidthUsed: 1, + IncludedGigabytesBandwidth: 1, + } + + want := `{ + "total_gigabytes_bandwidth_used": 1, + "total_paid_gigabytes_bandwidth_used": 1, + "included_gigabytes_bandwidth": 1 + }` + + testJSONMarshal(t, u, want) +} + +func TestStorageBilling_Marshal(t *testing.T) { + testJSONMarshal(t, &StorageBilling{}, "{}") + + u := &StorageBilling{ + DaysLeftInBillingCycle: 1, + EstimatedPaidStorageForMonth: 1, + EstimatedStorageForMonth: 1, + } + + want := `{ + "days_left_in_billing_cycle": 1, + "estimated_paid_storage_for_month": 1, + "estimated_storage_for_month": 1 + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/checks_test.go b/github/checks_test.go index 5d3315fd8b2..26da9abf780 100644 --- a/github/checks_test.go +++ b/github/checks_test.go @@ -949,3 +949,767 @@ func Test_CheckSuiteMarshal(t *testing.T) { testJSONMarshal(t, &c, w) } + +func TestCheckRunAnnotation_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckRunAnnotation{}, "{}") + + u := &CheckRunAnnotation{ + Path: String("p"), + StartLine: Int(1), + EndLine: Int(1), + StartColumn: Int(1), + EndColumn: Int(1), + AnnotationLevel: String("al"), + Message: String("m"), + Title: String("t"), + RawDetails: String("rd"), + } + + want := `{ + "path": "p", + "start_line": 1, + "end_line": 1, + "start_column": 1, + "end_column": 1, + "annotation_level": "al", + "message": "m", + "title": "t", + "raw_details": "rd" + }` + + testJSONMarshal(t, u, want) +} + +func TestCheckRunImage_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckRunImage{}, "{}") + + u := &CheckRunImage{ + Alt: String("a"), + ImageURL: String("i"), + Caption: String("c"), + } + + want := `{ + "alt": "a", + "image_url": "i", + "caption": "c" + }` + + testJSONMarshal(t, u, want) +} + +func TestCheckRunAction_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckRunAction{}, "{}") + + u := &CheckRunAction{ + Label: "l", + Description: "d", + Identifier: "i", + } + + want := `{ + "label": "l", + "description": "d", + "identifier": "i" + }` + + testJSONMarshal(t, u, want) +} + +func TestAutoTriggerCheck_Marshal(t *testing.T) { + testJSONMarshal(t, &AutoTriggerCheck{}, "{}") + + u := &AutoTriggerCheck{ + AppID: Int64(1), + Setting: Bool(false), + } + + want := `{ + "app_id": 1, + "setting": false + }` + + testJSONMarshal(t, u, want) +} + +func TestCreateCheckSuiteOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &CreateCheckSuiteOptions{}, "{}") + + u := &CreateCheckSuiteOptions{ + HeadSHA: "hsha", + HeadBranch: String("hb"), + } + + want := `{ + "head_sha": "hsha", + "head_branch": "hb" + }` + + testJSONMarshal(t, u, want) +} + +func TestCheckRunOutput_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckRunOutput{}, "{}") + + u := &CheckRunOutput{ + Title: String("ti"), + Summary: String("s"), + Text: String("t"), + AnnotationsCount: Int(1), + AnnotationsURL: String("au"), + Annotations: []*CheckRunAnnotation{ + { + Path: String("p"), + StartLine: Int(1), + EndLine: Int(1), + StartColumn: Int(1), + EndColumn: Int(1), + AnnotationLevel: String("al"), + Message: String("m"), + Title: String("t"), + RawDetails: String("rd"), + }, + }, + Images: []*CheckRunImage{ + { + Alt: String("a"), + ImageURL: String("i"), + Caption: String("c"), + }, + }, + } + + want := `{ + "title": "ti", + "summary": "s", + "text": "t", + "annotations_count": 1, + "annotations_url": "au", + "annotations": [ + { + "path": "p", + "start_line": 1, + "end_line": 1, + "start_column": 1, + "end_column": 1, + "annotation_level": "al", + "message": "m", + "title": "t", + "raw_details": "rd" + } + ], + "images": [ + { + "alt": "a", + "image_url": "i", + "caption": "c" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestCreateCheckRunOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &CreateCheckRunOptions{}, "{}") + + u := &CreateCheckRunOptions{ + Name: "n", + HeadSHA: "hsha", + DetailsURL: String("durl"), + ExternalID: String("eid"), + Status: String("s"), + Conclusion: String("c"), + StartedAt: &Timestamp{referenceTime}, + CompletedAt: &Timestamp{referenceTime}, + Output: &CheckRunOutput{ + Title: String("ti"), + Summary: String("s"), + Text: String("t"), + AnnotationsCount: Int(1), + AnnotationsURL: String("au"), + Annotations: []*CheckRunAnnotation{ + { + Path: String("p"), + StartLine: Int(1), + EndLine: Int(1), + StartColumn: Int(1), + EndColumn: Int(1), + AnnotationLevel: String("al"), + Message: String("m"), + Title: String("t"), + RawDetails: String("rd"), + }, + }, + Images: []*CheckRunImage{ + { + Alt: String("a"), + ImageURL: String("i"), + Caption: String("c"), + }, + }, + }, + Actions: []*CheckRunAction{ + { + Label: "l", + Description: "d", + Identifier: "i", + }, + }, + } + + want := `{ + "name": "n", + "head_sha": "hsha", + "details_url": "durl", + "external_id": "eid", + "status": "s", + "conclusion": "c", + "started_at": ` + referenceTimeStr + `, + "completed_at": ` + referenceTimeStr + `, + "output": { + "title": "ti", + "summary": "s", + "text": "t", + "annotations_count": 1, + "annotations_url": "au", + "annotations": [ + { + "path": "p", + "start_line": 1, + "end_line": 1, + "start_column": 1, + "end_column": 1, + "annotation_level": "al", + "message": "m", + "title": "t", + "raw_details": "rd" + } + ], + "images": [ + { + "alt": "a", + "image_url": "i", + "caption": "c" + } + ] + }, + "actions": [ + { + "label": "l", + "description": "d", + "identifier": "i" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestUpdateCheckRunOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &UpdateCheckRunOptions{}, "{}") + + u := &UpdateCheckRunOptions{ + Name: "n", + DetailsURL: String("durl"), + ExternalID: String("eid"), + Status: String("s"), + Conclusion: String("c"), + CompletedAt: &Timestamp{referenceTime}, + Output: &CheckRunOutput{ + Title: String("ti"), + Summary: String("s"), + Text: String("t"), + AnnotationsCount: Int(1), + AnnotationsURL: String("au"), + Annotations: []*CheckRunAnnotation{ + { + Path: String("p"), + StartLine: Int(1), + EndLine: Int(1), + StartColumn: Int(1), + EndColumn: Int(1), + AnnotationLevel: String("al"), + Message: String("m"), + Title: String("t"), + RawDetails: String("rd"), + }, + }, + Images: []*CheckRunImage{ + { + Alt: String("a"), + ImageURL: String("i"), + Caption: String("c"), + }, + }, + }, + Actions: []*CheckRunAction{ + { + Label: "l", + Description: "d", + Identifier: "i", + }, + }, + } + + want := `{ + "name": "n", + "details_url": "durl", + "external_id": "eid", + "status": "s", + "conclusion": "c", + "completed_at": ` + referenceTimeStr + `, + "output": { + "title": "ti", + "summary": "s", + "text": "t", + "annotations_count": 1, + "annotations_url": "au", + "annotations": [ + { + "path": "p", + "start_line": 1, + "end_line": 1, + "start_column": 1, + "end_column": 1, + "annotation_level": "al", + "message": "m", + "title": "t", + "raw_details": "rd" + } + ], + "images": [ + { + "alt": "a", + "image_url": "i", + "caption": "c" + } + ] + }, + "actions": [ + { + "label": "l", + "description": "d", + "identifier": "i" + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestListCheckRunsResults_Marshal(t *testing.T) { + testJSONMarshal(t, &ListCheckRunsResults{}, "{}") + + l := &ListCheckRunsResults{ + Total: Int(1), + CheckRuns: []*CheckRun{ + { + ID: Int64(1), + NodeID: String("n"), + HeadSHA: String("h"), + ExternalID: String("1"), + URL: String("u"), + HTMLURL: String("u"), + DetailsURL: String("u"), + Status: String("s"), + Conclusion: String("c"), + StartedAt: &Timestamp{referenceTime}, + CompletedAt: &Timestamp{referenceTime}, + Output: &CheckRunOutput{ + Annotations: []*CheckRunAnnotation{ + { + AnnotationLevel: String("a"), + EndLine: Int(1), + Message: String("m"), + Path: String("p"), + RawDetails: String("r"), + StartLine: Int(1), + Title: String("t"), + }, + }, + AnnotationsCount: Int(1), + AnnotationsURL: String("a"), + Images: []*CheckRunImage{ + { + Alt: String("a"), + ImageURL: String("i"), + Caption: String("c"), + }, + }, + Title: String("t"), + Summary: String("s"), + Text: String("t"), + }, + Name: String("n"), + CheckSuite: &CheckSuite{ + ID: Int64(1), + }, + App: &App{ + ID: Int64(1), + NodeID: String("n"), + Owner: &User{ + Login: String("l"), + ID: Int64(1), + NodeID: String("n"), + URL: String("u"), + ReposURL: String("r"), + EventsURL: String("e"), + AvatarURL: String("a"), + }, + Name: String("n"), + Description: String("d"), + HTMLURL: String("h"), + ExternalURL: String("u"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + }, + PullRequests: []*PullRequest{ + { + URL: String("u"), + ID: Int64(1), + Number: Int(1), + Head: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("s"), + Name: String("n"), + }, + }, + Base: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + }, + }, + }, + }, + } + + w := `{ + "total_count": 1, + "check_runs": [ + { + "id": 1, + "node_id": "n", + "head_sha": "h", + "external_id": "1", + "url": "u", + "html_url": "u", + "details_url": "u", + "status": "s", + "conclusion": "c", + "started_at": ` + referenceTimeStr + `, + "completed_at": ` + referenceTimeStr + `, + "output": { + "title": "t", + "summary": "s", + "text": "t", + "annotations_count": 1, + "annotations_url": "a", + "annotations": [ + { + "path": "p", + "start_line": 1, + "end_line": 1, + "annotation_level": "a", + "message": "m", + "title": "t", + "raw_details": "r" + } + ], + "images": [ + { + "alt": "a", + "image_url": "i", + "caption": "c" + } + ] + }, + "name": "n", + "check_suite": { + "id": 1 + }, + "app": { + "id": 1, + "node_id": "n", + "owner": { + "login": "l", + "id": 1, + "node_id": "n", + "avatar_url": "a", + "url": "u", + "events_url": "e", + "repos_url": "r" + }, + "name": "n", + "description": "d", + "external_url": "u", + "html_url": "h", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + ` + }, + "pull_requests": [ + { + "id": 1, + "number": 1, + "url": "u", + "head": { + "ref": "r", + "sha": "s", + "repo": { + "id": 1, + "name": "n", + "url": "s" + } + }, + "base": { + "ref": "r", + "sha": "s", + "repo": { + "id": 1, + "name": "n", + "url": "u" + } + } + } + ] + } + ] + }` + + testJSONMarshal(t, &l, w) +} + +func TestListCheckSuiteResults_Marshal(t *testing.T) { + testJSONMarshal(t, &ListCheckSuiteResults{}, "{}") + + l := &ListCheckSuiteResults{ + Total: Int(1), + CheckSuites: []*CheckSuite{ + { + ID: Int64(1), + NodeID: String("n"), + HeadBranch: String("h"), + HeadSHA: String("h"), + URL: String("u"), + BeforeSHA: String("b"), + AfterSHA: String("a"), + Status: String("s"), + Conclusion: String("c"), + App: &App{ + ID: Int64(1), + NodeID: String("n"), + Owner: &User{ + Login: String("l"), + ID: Int64(1), + NodeID: String("n"), + URL: String("u"), + ReposURL: String("r"), + EventsURL: String("e"), + AvatarURL: String("a"), + }, + Name: String("n"), + Description: String("d"), + HTMLURL: String("h"), + ExternalURL: String("u"), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + }, + Repository: &Repository{ + ID: Int64(1), + }, + PullRequests: []*PullRequest{ + { + URL: String("u"), + ID: Int64(1), + Number: Int(1), + Head: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("s"), + Name: String("n"), + }, + }, + Base: &PullRequestBranch{ + Ref: String("r"), + SHA: String("s"), + Repo: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + }, + }, + }, + HeadCommit: &Commit{ + SHA: String("s"), + }, + }, + }, + } + + w := `{ + "total_count": 1, + "check_suites": [ + { + "id": 1, + "node_id": "n", + "head_branch": "h", + "head_sha": "h", + "url": "u", + "before": "b", + "after": "a", + "status": "s", + "conclusion": "c", + "app": { + "id": 1, + "node_id": "n", + "owner": { + "login": "l", + "id": 1, + "node_id": "n", + "avatar_url": "a", + "url": "u", + "events_url": "e", + "repos_url": "r" + }, + "name": "n", + "description": "d", + "external_url": "u", + "html_url": "h", + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + ` + }, + "repository": { + "id": 1 + }, + "pull_requests": [ + { + "id": 1, + "number": 1, + "url": "u", + "head": { + "ref": "r", + "sha": "s", + "repo": { + "id": 1, + "name": "n", + "url": "s" + } + }, + "base": { + "ref": "r", + "sha": "s", + "repo": { + "id": 1, + "name": "n", + "url": "u" + } + } + } + ], + "head_commit": { + "sha": "s" + } + } + ] + }` + + testJSONMarshal(t, &l, w) +} + +func TestCheckSuitePreferenceOptions_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckSuitePreferenceOptions{}, "{}") + + u := &CheckSuitePreferenceOptions{ + AutoTriggerChecks: []*AutoTriggerCheck{ + { + AppID: Int64(1), + Setting: Bool(false), + }, + }, + } + + want := `{ + "auto_trigger_checks": [ + { + "app_id": 1, + "setting": false + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestPreferenceList_Marshal(t *testing.T) { + testJSONMarshal(t, &PreferenceList{}, "{}") + + u := &PreferenceList{ + AutoTriggerChecks: []*AutoTriggerCheck{ + { + AppID: Int64(1), + Setting: Bool(false), + }, + }, + } + + want := `{ + "auto_trigger_checks": [ + { + "app_id": 1, + "setting": false + } + ] + }` + + testJSONMarshal(t, u, want) +} + +func TestCheckSuitePreferenceResults_Marshal(t *testing.T) { + testJSONMarshal(t, &CheckSuitePreferenceResults{}, "{}") + + u := &CheckSuitePreferenceResults{ + Preferences: &PreferenceList{ + AutoTriggerChecks: []*AutoTriggerCheck{ + { + AppID: Int64(1), + Setting: Bool(false), + }, + }, + }, + Repository: &Repository{ + ID: Int64(1), + URL: String("u"), + Name: String("n"), + }, + } + + want := `{ + "preferences": { + "auto_trigger_checks": [ + { + "app_id": 1, + "setting": false + } + ] + }, + "repository": { + "id":1, + "name":"n", + "url":"u" + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/code-scanning.go b/github/code-scanning.go index 9eb711cf437..8602c446322 100644 --- a/github/code-scanning.go +++ b/github/code-scanning.go @@ -18,11 +18,23 @@ import ( // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/code-scanning/ type CodeScanningService service +// Tool represents the tool used to generate a GitHub Code Scanning Alert. +// +// GitHub API docs: https://docs.github.com/en/rest/reference/code-scanning#list-code-scanning-alerts-for-a-repository +type Tool struct { + Name *string `json:"name,omitempty"` + GUID *string `json:"guid,omitempty"` + Version *string `json:"version,omitempty"` +} + +// Alert represents an individual GitHub Code Scanning Alert on a single repository. +// +// GitHub API docs: https://docs.github.com/en/rest/reference/code-scanning#list-code-scanning-alerts-for-a-repository type Alert struct { RuleID *string `json:"rule_id,omitempty"` RuleSeverity *string `json:"rule_severity,omitempty"` RuleDescription *string `json:"rule_description,omitempty"` - Tool *string `json:"tool,omitempty"` + Tool *Tool `json:"tool,omitempty"` CreatedAt *Timestamp `json:"created_at,omitempty"` Open *bool `json:"open,omitempty"` ClosedBy *User `json:"closed_by,omitempty"` diff --git a/github/code-scanning_test.go b/github/code-scanning_test.go index be9fb3de4c3..1ea506c46a4 100644 --- a/github/code-scanning_test.go +++ b/github/code-scanning_test.go @@ -64,7 +64,11 @@ func TestActionsService_ListAlertsForRepo(t *testing.T) { "rule_id":"js/trivial-conditional", "rule_severity":"warning", "rule_description":"Useless conditional", - "tool":"CodeQL", + "tool": { + "name": "CodeQL", + "guid": null, + "version": "1.4.0" + }, "created_at":"2020-05-06T12:00:00Z", "open":true, "closed_by":null, @@ -76,7 +80,11 @@ func TestActionsService_ListAlertsForRepo(t *testing.T) { "rule_id":"js/useless-expression", "rule_severity":"warning", "rule_description":"Expression has no effect", - "tool":"CodeQL", + "tool": { + "name": "CodeQL", + "guid": null, + "version": "1.4.0" + }, "created_at":"2020-05-06T12:00:00Z", "open":true, "closed_by":null, @@ -99,7 +107,7 @@ func TestActionsService_ListAlertsForRepo(t *testing.T) { RuleID: String("js/trivial-conditional"), RuleSeverity: String("warning"), RuleDescription: String("Useless conditional"), - Tool: String("CodeQL"), + Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, CreatedAt: &date, Open: Bool(true), ClosedBy: nil, @@ -111,7 +119,7 @@ func TestActionsService_ListAlertsForRepo(t *testing.T) { RuleID: String("js/useless-expression"), RuleSeverity: String("warning"), RuleDescription: String("Expression has no effect"), - Tool: String("CodeQL"), + Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, CreatedAt: &date, Open: Bool(true), ClosedBy: nil, @@ -148,7 +156,11 @@ func TestActionsService_GetAlert(t *testing.T) { fmt.Fprint(w, `{"rule_id":"js/useless-expression", "rule_severity":"warning", "rule_description":"Expression has no effect", - "tool":"CodeQL", + "tool": { + "name": "CodeQL", + "guid": null, + "version": "1.4.0" + }, "created_at":"2019-01-02T15:04:05Z", "open":true, "closed_by":null, @@ -168,7 +180,7 @@ func TestActionsService_GetAlert(t *testing.T) { RuleID: String("js/useless-expression"), RuleSeverity: String("warning"), RuleDescription: String("Expression has no effect"), - Tool: String("CodeQL"), + Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, CreatedAt: &date, Open: Bool(true), ClosedBy: nil, @@ -194,3 +206,59 @@ func TestActionsService_GetAlert(t *testing.T) { return resp, err }) } + +func TestAlert_Marshal(t *testing.T) { + testJSONMarshal(t, &Alert{}, "{}") + + u := &Alert{ + RuleID: String("rid"), + RuleSeverity: String("rs"), + RuleDescription: String("rd"), + Tool: &Tool{ + Name: String("n"), + GUID: String("g"), + Version: String("v"), + }, + CreatedAt: &Timestamp{referenceTime}, + Open: Bool(false), + ClosedBy: &User{ + Login: String("l"), + ID: Int64(1), + NodeID: String("n"), + URL: String("u"), + ReposURL: String("r"), + EventsURL: String("e"), + AvatarURL: String("a"), + }, + ClosedAt: &Timestamp{referenceTime}, + URL: String("url"), + HTMLURL: String("hurl"), + } + + want := `{ + "rule_id": "rid", + "rule_severity": "rs", + "rule_description": "rd", + "tool": { + "name": "n", + "guid": "g", + "version": "v" + }, + "created_at": ` + referenceTimeStr + `, + "open": false, + "closed_by": { + "login": "l", + "id": 1, + "node_id": "n", + "avatar_url": "a", + "url": "u", + "events_url": "e", + "repos_url": "r" + }, + "closed_at": ` + referenceTimeStr + `, + "url": "url", + "html_url": "hurl" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/doc.go b/github/doc.go index def690b83af..bd2e3ea063f 100644 --- a/github/doc.go +++ b/github/doc.go @@ -8,7 +8,7 @@ Package github provides a client for using the GitHub API. Usage: - import "github.com/google/go-github/v35/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) + import "github.com/google/go-github/v37/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) import "github.com/google/go-github/github" // with go modules disabled Construct a new GitHub client, then use the various services on the client to diff --git a/github/event_test.go b/github/event_test.go index da61c87285f..713f3b1ed7f 100644 --- a/github/event_test.go +++ b/github/event_test.go @@ -29,3 +29,104 @@ func TestPayload_NoPanic(t *testing.T) { e := &Event{Type: &name, RawPayload: &body} e.Payload() } + +func TestEvent_Marshal(t *testing.T) { + testJSONMarshal(t, &Event{}, "{}") + + l := make(map[string]interface{}) + l["key"] = "value" + + jsonMsg, _ := json.Marshal(&l) + + u := &Event{ + Type: String("t"), + Public: Bool(false), + RawPayload: (*json.RawMessage)(&jsonMsg), + Repo: &Repository{ + ID: Int64(1), + URL: String("s"), + Name: String("n"), + }, + Actor: &User{ + Login: String("l"), + ID: Int64(1), + NodeID: String("n"), + URL: String("u"), + ReposURL: String("r"), + EventsURL: String("e"), + AvatarURL: String("a"), + }, + Org: &Organization{ + BillingEmail: String("be"), + Blog: String("b"), + Company: String("c"), + Email: String("e"), + TwitterUsername: String("tu"), + Location: String("loc"), + Name: String("n"), + Description: String("d"), + IsVerified: Bool(true), + HasOrganizationProjects: Bool(true), + HasRepositoryProjects: Bool(true), + DefaultRepoPermission: String("drp"), + MembersCanCreateRepos: Bool(true), + MembersCanCreateInternalRepos: Bool(true), + MembersCanCreatePrivateRepos: Bool(true), + MembersCanCreatePublicRepos: Bool(false), + MembersAllowedRepositoryCreationType: String("marct"), + MembersCanCreatePages: Bool(true), + MembersCanCreatePublicPages: Bool(false), + MembersCanCreatePrivatePages: Bool(true), + }, + CreatedAt: &referenceTime, + ID: String("id"), + } + + want := `{ + "type": "t", + "public": false, + "payload": { + "key": "value" + }, + "repo": { + "id": 1, + "name": "n", + "url": "s" + }, + "actor": { + "login": "l", + "id": 1, + "node_id": "n", + "avatar_url": "a", + "url": "u", + "events_url": "e", + "repos_url": "r" + }, + "org": { + "name": "n", + "company": "c", + "blog": "b", + "location": "loc", + "email": "e", + "twitter_username": "tu", + "description": "d", + "billing_email": "be", + "is_verified": true, + "has_organization_projects": true, + "has_repository_projects": true, + "default_repository_permission": "drp", + "members_can_create_repositories": true, + "members_can_create_public_repositories": false, + "members_can_create_private_repositories": true, + "members_can_create_internal_repositories": true, + "members_allowed_repository_creation_type": "marct", + "members_can_create_pages": true, + "members_can_create_public_pages": false, + "members_can_create_private_pages": true + }, + "created_at": ` + referenceTimeStr + `, + "id": "id" + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/event_types.go b/github/event_types.go index 48347f37d04..f99a1296a09 100644 --- a/github/event_types.go +++ b/github/event_types.go @@ -215,66 +215,111 @@ type GollumEvent struct { // EditChange represents the changes when an issue, pull request, or comment has // been edited. type EditChange struct { - Title *struct { - From *string `json:"from,omitempty"` - } `json:"title,omitempty"` - Body *struct { - From *string `json:"from,omitempty"` - } `json:"body,omitempty"` - Base *struct { - Ref *struct { - From *string `json:"from,omitempty"` - } `json:"ref,omitempty"` - SHA *struct { - From *string `json:"from,omitempty"` - } `json:"sha,omitempty"` - } `json:"base,omitempty"` + Title *EditTitle `json:"title,omitempty"` + Body *EditBody `json:"body,omitempty"` + Base *EditBase `json:"base,omitempty"` +} + +// EditTitle represents a pull-request title change. +type EditTitle struct { + From *string `json:"from,omitempty"` +} + +// EditBody represents a change of pull-request body. +type EditBody struct { + From *string `json:"from,omitempty"` +} + +// EditBase represents the change of a pull-request base branch. +type EditBase struct { + Ref *EditRef `json:"ref,omitempty"` + SHA *EditSHA `json:"sha,omitempty"` +} + +// EditRef represents a ref change of a pull-request. +type EditRef struct { + From *string `json:"from,omitempty"` +} + +// EditSHA represents a sha change of a pull-request. +type EditSHA struct { + From *string `json:"from,omitempty"` } // ProjectChange represents the changes when a project has been edited. type ProjectChange struct { - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` - Body *struct { - From *string `json:"from,omitempty"` - } `json:"body,omitempty"` + Name *ProjectName `json:"name,omitempty"` + Body *ProjectBody `json:"body,omitempty"` +} + +// ProjectName represents a project name change. +type ProjectName struct { + From *string `json:"from,omitempty"` +} + +// ProjectBody represents a project body change. +type ProjectBody struct { + From *string `json:"from,omitempty"` } // ProjectCardChange represents the changes when a project card has been edited. type ProjectCardChange struct { - Note *struct { - From *string `json:"from,omitempty"` - } `json:"note,omitempty"` + Note *ProjectCardNote `json:"note,omitempty"` +} + +// ProjectCardNote represents a change of a note of a project card. +type ProjectCardNote struct { + From *string `json:"from,omitempty"` } // ProjectColumnChange represents the changes when a project column has been edited. type ProjectColumnChange struct { - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` + Name *ProjectColumnName `json:"name,omitempty"` +} + +// ProjectColumnName represents a project column name change. +type ProjectColumnName struct { + From *string `json:"from,omitempty"` } // TeamChange represents the changes when a team has been edited. type TeamChange struct { - Description *struct { - From *string `json:"from,omitempty"` - } `json:"description,omitempty"` - Name *struct { - From *string `json:"from,omitempty"` - } `json:"name,omitempty"` - Privacy *struct { - From *string `json:"from,omitempty"` - } `json:"privacy,omitempty"` - Repository *struct { - Permissions *struct { - From *struct { - Admin *bool `json:"admin,omitempty"` - Pull *bool `json:"pull,omitempty"` - Push *bool `json:"push,omitempty"` - } `json:"from,omitempty"` - } `json:"permissions,omitempty"` - } `json:"repository,omitempty"` + Description *TeamDescription `json:"description,omitempty"` + Name *TeamName `json:"name,omitempty"` + Privacy *TeamPrivacy `json:"privacy,omitempty"` + Repository *TeamRepository `json:"repository,omitempty"` +} + +// TeamDescription represents a team description change. +type TeamDescription struct { + From *string `json:"from,omitempty"` +} + +// TeamName represents a team name change. +type TeamName struct { + From *string `json:"from,omitempty"` +} + +// TeamPrivacy represents a team privacy change. +type TeamPrivacy struct { + From *string `json:"from,omitempty"` +} + +// TeamRepository represents a team repository permission change. +type TeamRepository struct { + Permissions *TeamPermissions `json:"permissions,omitempty"` +} + +// TeamPermissions represents a team permission change. +type TeamPermissions struct { + From *TeamPermissionsFrom `json:"from,omitempty"` +} + +// TeamPermissionsFrom represents a team permission change. +type TeamPermissionsFrom struct { + Admin *bool `json:"admin,omitempty"` + Pull *bool `json:"pull,omitempty"` + Push *bool `json:"push,omitempty"` } // InstallationEvent is triggered when a GitHub App has been installed, uninstalled, suspend, unsuspended @@ -890,22 +935,28 @@ type RepositoryVulnerabilityAlertEvent struct { Action *string `json:"action,omitempty"` //The security alert of the vulnerable dependency. - Alert *struct { - ID *int64 `json:"id,omitempty"` - AffectedRange *string `json:"affected_range,omitempty"` - AffectedPackageName *string `json:"affected_package_name,omitempty"` - ExternalReference *string `json:"external_reference,omitempty"` - ExternalIdentifier *string `json:"external_identifier,omitempty"` - FixedIn *string `json:"fixed_in,omitempty"` - Dismisser *User `json:"dismisser,omitempty"` - DismissReason *string `json:"dismiss_reason,omitempty"` - DismissedAt *Timestamp `json:"dismissed_at,omitempty"` - } `json:"alert,omitempty"` + Alert *RepositoryVulnerabilityAlert `json:"alert,omitempty"` //The repository of the vulnerable dependency. Repository *Repository `json:"repository,omitempty"` } +// RepositoryVulnerabilityAlert represents a repository security alert. +type RepositoryVulnerabilityAlert struct { + ID *int64 `json:"id,omitempty"` + AffectedRange *string `json:"affected_range,omitempty"` + AffectedPackageName *string `json:"affected_package_name,omitempty"` + ExternalReference *string `json:"external_reference,omitempty"` + ExternalIdentifier *string `json:"external_identifier,omitempty"` + GitHubSecurityAdvisoryID *string `json:"ghsa_id,omitempty"` + Severity *string `json:"severity,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + FixedIn *string `json:"fixed_in,omitempty"` + Dismisser *User `json:"dismisser,omitempty"` + DismissReason *string `json:"dismiss_reason,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` +} + // StarEvent is triggered when a star is added or removed from a repository. // The Webhook event name is "star". // diff --git a/github/event_types_test.go b/github/event_types_test.go index 986d9719f78..7c98c80be64 100644 --- a/github/event_types_test.go +++ b/github/event_types_test.go @@ -12,16 +12,12 @@ import ( func TestEditChange_Marshal_TitleChange(t *testing.T) { testJSONMarshal(t, &EditChange{}, "{}") - TitleFrom := struct { - From *string `json:"from,omitempty"` - }{ - From: String("TitleFrom"), - } - u := &EditChange{ - Title: &TitleFrom, - Body: nil, - Base: nil, + Title: &EditTitle{ + From: String("TitleFrom"), + }, + Body: nil, + Base: nil, } want := `{ @@ -36,16 +32,12 @@ func TestEditChange_Marshal_TitleChange(t *testing.T) { func TestEditChange_Marshal_BodyChange(t *testing.T) { testJSONMarshal(t, &EditChange{}, "{}") - BodyFrom := struct { - From *string `json:"from,omitempty"` - }{ - From: String("BodyFrom"), - } - u := &EditChange{ Title: nil, - Body: &BodyFrom, - Base: nil, + Body: &EditBody{ + From: String("BodyFrom"), + }, + Base: nil, } want := `{ @@ -60,28 +52,13 @@ func TestEditChange_Marshal_BodyChange(t *testing.T) { func TestEditChange_Marshal_BaseChange(t *testing.T) { testJSONMarshal(t, &EditChange{}, "{}") - RefFrom := struct { - From *string `json:"from,omitempty"` - }{ - From: String("BaseRefFrom"), - } - - SHAFrom := struct { - From *string `json:"from,omitempty"` - }{ - From: String("BaseSHAFrom"), - } - - Base := struct { - Ref *struct { - From *string `json:"from,omitempty"` - } `json:"ref,omitempty"` - SHA *struct { - From *string `json:"from,omitempty"` - } `json:"sha,omitempty"` - }{ - Ref: &RefFrom, - SHA: &SHAFrom, + Base := EditBase{ + Ref: &EditRef{ + From: String("BaseRefFrom"), + }, + SHA: &EditSHA{ + From: String("BaseSHAFrom"), + }, } u := &EditChange{ @@ -103,3 +80,69 @@ func TestEditChange_Marshal_BaseChange(t *testing.T) { testJSONMarshal(t, u, want) } + +func TestProjectChange_Marshal_NameChange(t *testing.T) { + testJSONMarshal(t, &ProjectChange{}, "{}") + + u := &ProjectChange{ + Name: &ProjectName{From: String("NameFrom")}, + Body: nil, + } + + want := `{ + "name": { + "from": "NameFrom" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestProjectChange_Marshal_BodyChange(t *testing.T) { + testJSONMarshal(t, &ProjectChange{}, "{}") + + u := &ProjectChange{ + Name: nil, + Body: &ProjectBody{From: String("BodyFrom")}, + } + + want := `{ + "body": { + "from": "BodyFrom" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestProjectCardChange_Marshal_NoteChange(t *testing.T) { + testJSONMarshal(t, &ProjectCardChange{}, "{}") + + u := &ProjectCardChange{ + Note: &ProjectCardNote{From: String("NoteFrom")}, + } + + want := `{ + "note": { + "from": "NoteFrom" + } + }` + + testJSONMarshal(t, u, want) +} + +func TestProjectColumnChange_Marshal_NameChange(t *testing.T) { + testJSONMarshal(t, &ProjectColumnChange{}, "{}") + + u := &ProjectColumnChange{ + Name: &ProjectColumnName{From: String("NameFrom")}, + } + + want := `{ + "name": { + "from": "NameFrom" + } + }` + + testJSONMarshal(t, u, want) +} diff --git a/github/examples_test.go b/github/examples_test.go index 33851fac80e..730d62283a5 100644 --- a/github/examples_test.go +++ b/github/examples_test.go @@ -12,7 +12,7 @@ import ( "fmt" "log" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) func ExampleClient_Markdown() { diff --git a/github/github-accessors.go b/github/github-accessors.go index 1c17384eac0..46efcc9c425 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -212,12 +212,12 @@ func (a *Alert) GetRuleSeverity() string { return *a.RuleSeverity } -// GetTool returns the Tool field if it's non-nil, zero value otherwise. -func (a *Alert) GetTool() string { - if a == nil || a.Tool == nil { - return "" +// GetTool returns the Tool field. +func (a *Alert) GetTool() *Tool { + if a == nil { + return nil } - return *a.Tool + return a.Tool } // GetURL returns the URL field if it's non-nil, zero value otherwise. @@ -3620,6 +3620,78 @@ func (d *DraftReviewComment) GetStartSide() string { return *d.StartSide } +// GetRef returns the Ref field. +func (e *EditBase) GetRef() *EditRef { + if e == nil { + return nil + } + return e.Ref +} + +// GetSHA returns the SHA field. +func (e *EditBase) GetSHA() *EditSHA { + if e == nil { + return nil + } + return e.SHA +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditBody) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetBase returns the Base field. +func (e *EditChange) GetBase() *EditBase { + if e == nil { + return nil + } + return e.Base +} + +// GetBody returns the Body field. +func (e *EditChange) GetBody() *EditBody { + if e == nil { + return nil + } + return e.Body +} + +// GetTitle returns the Title field. +func (e *EditChange) GetTitle() *EditTitle { + if e == nil { + return nil + } + return e.Title +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditRef) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditSHA) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditTitle) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (e *Enterprise) GetAvatarURL() string { if e == nil || e.AvatarURL == nil { @@ -3820,6 +3892,22 @@ func (e *EnvReviewers) GetType() string { return *e.Type } +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *ErrorBlock) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetBlock returns the Block field. +func (e *ErrorResponse) GetBlock() *ErrorBlock { + if e == nil { + return nil + } + return e.Block +} + // GetActor returns the Actor field. func (e *Event) GetActor() *User { if e == nil { @@ -3900,6 +3988,54 @@ func (f *FeedLink) GetType() string { return *f.Type } +// GetCurrentUser returns the CurrentUser field. +func (f *FeedLinks) GetCurrentUser() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUser +} + +// GetCurrentUserActor returns the CurrentUserActor field. +func (f *FeedLinks) GetCurrentUserActor() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserActor +} + +// GetCurrentUserOrganization returns the CurrentUserOrganization field. +func (f *FeedLinks) GetCurrentUserOrganization() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserOrganization +} + +// GetCurrentUserPublic returns the CurrentUserPublic field. +func (f *FeedLinks) GetCurrentUserPublic() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserPublic +} + +// GetTimeline returns the Timeline field. +func (f *FeedLinks) GetTimeline() *FeedLink { + if f == nil { + return nil + } + return f.Timeline +} + +// GetUser returns the User field. +func (f *FeedLinks) GetUser() *FeedLink { + if f == nil { + return nil + } + return f.User +} + // GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetCurrentUserActorURL() string { if f == nil || f.CurrentUserActorURL == nil { @@ -3932,6 +4068,14 @@ func (f *Feeds) GetCurrentUserURL() string { return *f.CurrentUserURL } +// GetLinks returns the Links field. +func (f *Feeds) GetLinks() *FeedLinks { + if f == nil { + return nil + } + return f.Links +} + // GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. func (f *Feeds) GetTimelineURL() string { if f == nil || f.TimelineURL == nil { @@ -9316,6 +9460,14 @@ func (p *Project) GetURL() string { return *p.URL } +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectBody) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + // GetArchived returns the Archived field if it's non-nil, zero value otherwise. func (p *ProjectCard) GetArchived() bool { if p == nil || p.Archived == nil { @@ -9436,6 +9588,14 @@ func (p *ProjectCard) GetURL() string { return *p.URL } +// GetNote returns the Note field. +func (p *ProjectCardChange) GetNote() *ProjectCardNote { + if p == nil { + return nil + } + return p.Note +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectCardEvent) GetAction() string { if p == nil || p.Action == nil { @@ -9508,6 +9668,14 @@ func (p *ProjectCardListOptions) GetArchivedState() string { return *p.ArchivedState } +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectCardNote) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + // GetArchived returns the Archived field if it's non-nil, zero value otherwise. func (p *ProjectCardOptions) GetArchived() bool { if p == nil || p.Archived == nil { @@ -9516,6 +9684,22 @@ func (p *ProjectCardOptions) GetArchived() bool { return *p.Archived } +// GetBody returns the Body field. +func (p *ProjectChange) GetBody() *ProjectBody { + if p == nil { + return nil + } + return p.Body +} + +// GetName returns the Name field. +func (p *ProjectChange) GetName() *ProjectName { + if p == nil { + return nil + } + return p.Name +} + // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (p *ProjectCollaboratorOptions) GetPermission() string { if p == nil || p.Permission == nil { @@ -9588,6 +9772,14 @@ func (p *ProjectColumn) GetURL() string { return *p.URL } +// GetName returns the Name field. +func (p *ProjectColumnChange) GetName() *ProjectColumnName { + if p == nil { + return nil + } + return p.Name +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectColumnEvent) GetAction() string { if p == nil || p.Action == nil { @@ -9652,6 +9844,14 @@ func (p *ProjectColumnEvent) GetSender() *User { return p.Sender } +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectColumnName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (p *ProjectEvent) GetAction() string { if p == nil || p.Action == nil { @@ -9708,6 +9908,14 @@ func (p *ProjectEvent) GetSender() *User { return p.Sender } +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + // GetBody returns the Body field if it's non-nil, zero value otherwise. func (p *ProjectOptions) GetBody() string { if p == nil || p.Body == nil { @@ -9788,6 +9996,14 @@ func (p *Protection) GetEnforceAdmins() *AdminEnforcement { return p.EnforceAdmins } +// GetRequiredConversationResolution returns the RequiredConversationResolution field. +func (p *Protection) GetRequiredConversationResolution() *RequiredConversationResolution { + if p == nil { + return nil + } + return p.RequiredConversationResolution +} + // GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { if p == nil { @@ -9972,6 +10188,14 @@ func (p *PullRequest) GetAuthorAssociation() string { return *p.AuthorAssociation } +// GetAutoMerge returns the AutoMerge field. +func (p *PullRequest) GetAutoMerge() *PullRequestAutoMerge { + if p == nil { + return nil + } + return p.AutoMerge +} + // GetBase returns the Base field. func (p *PullRequest) GetBase() *PullRequestBranch { if p == nil { @@ -10284,6 +10508,38 @@ func (p *PullRequest) GetUser() *User { return p.User } +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitMessage() string { + if p == nil || p.CommitMessage == nil { + return "" + } + return *p.CommitMessage +} + +// GetCommitTitle returns the CommitTitle field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitTitle() string { + if p == nil || p.CommitTitle == nil { + return "" + } + return *p.CommitTitle +} + +// GetEnabledBy returns the EnabledBy field. +func (p *PullRequestAutoMerge) GetEnabledBy() *User { + if p == nil { + return nil + } + return p.EnabledBy +} + +// GetMergeMethod returns the MergeMethod field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetMergeMethod() string { + if p == nil || p.MergeMethod == nil { + return "" + } + return *p.MergeMethod +} + // GetLabel returns the Label field if it's non-nil, zero value otherwise. func (p *PullRequestBranch) GetLabel() string { if p == nil || p.Label == nil { @@ -12460,6 +12716,14 @@ func (r *Repository) GetNotificationsURL() string { return *r.NotificationsURL } +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssues() int { + if r == nil || r.OpenIssues == nil { + return 0 + } + return *r.OpenIssues +} + // GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. func (r *Repository) GetOpenIssuesCount() int { if r == nil || r.OpenIssuesCount == nil { @@ -12676,6 +12940,14 @@ func (r *Repository) GetVisibility() string { return *r.Visibility } +// GetWatchers returns the Watchers field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchers() int { + if r == nil || r.Watchers == nil { + return 0 + } + return *r.Watchers +} + // GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. func (r *Repository) GetWatchersCount() int { if r == nil || r.WatchersCount == nil { @@ -13452,6 +13724,102 @@ func (r *RepositoryTag) GetZipballURL() string { return *r.ZipballURL } +// GetAffectedPackageName returns the AffectedPackageName field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedPackageName() string { + if r == nil || r.AffectedPackageName == nil { + return "" + } + return *r.AffectedPackageName +} + +// GetAffectedRange returns the AffectedRange field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedRange() string { + if r == nil || r.AffectedRange == nil { + return "" + } + return *r.AffectedRange +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissedAt() Timestamp { + if r == nil || r.DismissedAt == nil { + return Timestamp{} + } + return *r.DismissedAt +} + +// GetDismisser returns the Dismisser field. +func (r *RepositoryVulnerabilityAlert) GetDismisser() *User { + if r == nil { + return nil + } + return r.Dismisser +} + +// GetDismissReason returns the DismissReason field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissReason() string { + if r == nil || r.DismissReason == nil { + return "" + } + return *r.DismissReason +} + +// GetExternalIdentifier returns the ExternalIdentifier field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalIdentifier() string { + if r == nil || r.ExternalIdentifier == nil { + return "" + } + return *r.ExternalIdentifier +} + +// GetExternalReference returns the ExternalReference field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalReference() string { + if r == nil || r.ExternalReference == nil { + return "" + } + return *r.ExternalReference +} + +// GetFixedIn returns the FixedIn field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetFixedIn() string { + if r == nil || r.FixedIn == nil { + return "" + } + return *r.FixedIn +} + +// GetGitHubSecurityAdvisoryID returns the GitHubSecurityAdvisoryID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetGitHubSecurityAdvisoryID() string { + if r == nil || r.GitHubSecurityAdvisoryID == nil { + return "" + } + return *r.GitHubSecurityAdvisoryID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { if r == nil || r.Action == nil { @@ -13460,6 +13828,14 @@ func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { return *r.Action } +// GetAlert returns the Alert field. +func (r *RepositoryVulnerabilityAlertEvent) GetAlert() *RepositoryVulnerabilityAlert { + if r == nil { + return nil + } + return r.Alert +} + // GetRepository returns the Repository field. func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository { if r == nil { @@ -14468,6 +14844,46 @@ func (t *TeamAddEvent) GetTeam() *Team { return t.Team } +// GetDescription returns the Description field. +func (t *TeamChange) GetDescription() *TeamDescription { + if t == nil { + return nil + } + return t.Description +} + +// GetName returns the Name field. +func (t *TeamChange) GetName() *TeamName { + if t == nil { + return nil + } + return t.Name +} + +// GetPrivacy returns the Privacy field. +func (t *TeamChange) GetPrivacy() *TeamPrivacy { + if t == nil { + return nil + } + return t.Privacy +} + +// GetRepository returns the Repository field. +func (t *TeamChange) GetRepository() *TeamRepository { + if t == nil { + return nil + } + return t.Repository +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamDescription) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + // GetAuthor returns the Author field. func (t *TeamDiscussion) GetAuthor() *User { if t == nil { @@ -14748,6 +15164,54 @@ func (t *TeamLDAPMapping) GetURL() string { return *t.URL } +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamName) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetFrom returns the From field. +func (t *TeamPermissions) GetFrom() *TeamPermissionsFrom { + if t == nil { + return nil + } + return t.From +} + +// GetAdmin returns the Admin field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetAdmin() bool { + if t == nil || t.Admin == nil { + return false + } + return *t.Admin +} + +// GetPull returns the Pull field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPull() bool { + if t == nil || t.Pull == nil { + return false + } + return *t.Pull +} + +// GetPush returns the Push field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPush() bool { + if t == nil || t.Push == nil { + return false + } + return *t.Push +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamPrivacy) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + // GetPermission returns the Permission field if it's non-nil, zero value otherwise. func (t *TeamProjectOptions) GetPermission() string { if t == nil || t.Permission == nil { @@ -14756,6 +15220,14 @@ func (t *TeamProjectOptions) GetPermission() string { return *t.Permission } +// GetPermissions returns the Permissions field. +func (t *TeamRepository) GetPermissions() *TeamPermissions { + if t == nil { + return nil + } + return t.Permissions +} + // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (t *TemplateRepoRequest) GetDescription() string { if t == nil || t.Description == nil { @@ -14924,6 +15396,14 @@ func (t *Timeline) GetSource() *Source { return t.Source } +// GetState returns the State field if it's non-nil, zero value otherwise. +func (t *Timeline) GetState() string { + if t == nil || t.State == nil { + return "" + } + return *t.State +} + // GetURL returns the URL field if it's non-nil, zero value otherwise. func (t *Timeline) GetURL() string { if t == nil || t.URL == nil { @@ -14932,6 +15412,30 @@ func (t *Timeline) GetURL() string { return *t.URL } +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (t *Tool) GetGUID() string { + if t == nil || t.GUID == nil { + return "" + } + return *t.GUID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Tool) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (t *Tool) GetVersion() string { + if t == nil || t.Version == nil { + return "" + } + return *t.Version +} + // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. func (t *TopicResult) GetCreatedAt() Timestamp { if t == nil || t.CreatedAt == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 750c6a40f8f..4fcdd919208 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -231,10 +231,7 @@ func TestAlert_GetRuleSeverity(tt *testing.T) { } func TestAlert_GetTool(tt *testing.T) { - var zeroValue string - a := &Alert{Tool: &zeroValue} - a.GetTool() - a = &Alert{} + a := &Alert{} a.GetTool() a = nil a.GetTool() @@ -4244,6 +4241,81 @@ func TestDraftReviewComment_GetStartSide(tt *testing.T) { d.GetStartSide() } +func TestEditBase_GetRef(tt *testing.T) { + e := &EditBase{} + e.GetRef() + e = nil + e.GetRef() +} + +func TestEditBase_GetSHA(tt *testing.T) { + e := &EditBase{} + e.GetSHA() + e = nil + e.GetSHA() +} + +func TestEditBody_GetFrom(tt *testing.T) { + var zeroValue string + e := &EditBody{From: &zeroValue} + e.GetFrom() + e = &EditBody{} + e.GetFrom() + e = nil + e.GetFrom() +} + +func TestEditChange_GetBase(tt *testing.T) { + e := &EditChange{} + e.GetBase() + e = nil + e.GetBase() +} + +func TestEditChange_GetBody(tt *testing.T) { + e := &EditChange{} + e.GetBody() + e = nil + e.GetBody() +} + +func TestEditChange_GetTitle(tt *testing.T) { + e := &EditChange{} + e.GetTitle() + e = nil + e.GetTitle() +} + +func TestEditRef_GetFrom(tt *testing.T) { + var zeroValue string + e := &EditRef{From: &zeroValue} + e.GetFrom() + e = &EditRef{} + e.GetFrom() + e = nil + e.GetFrom() +} + +func TestEditSHA_GetFrom(tt *testing.T) { + var zeroValue string + e := &EditSHA{From: &zeroValue} + e.GetFrom() + e = &EditSHA{} + e.GetFrom() + e = nil + e.GetFrom() +} + +func TestEditTitle_GetFrom(tt *testing.T) { + var zeroValue string + e := &EditTitle{From: &zeroValue} + e.GetFrom() + e = &EditTitle{} + e.GetFrom() + e = nil + e.GetFrom() +} + func TestEnterprise_GetAvatarURL(tt *testing.T) { var zeroValue string e := &Enterprise{AvatarURL: &zeroValue} @@ -4491,6 +4563,23 @@ func TestEnvReviewers_GetType(tt *testing.T) { e.GetType() } +func TestErrorBlock_GetCreatedAt(tt *testing.T) { + var zeroValue Timestamp + e := &ErrorBlock{CreatedAt: &zeroValue} + e.GetCreatedAt() + e = &ErrorBlock{} + e.GetCreatedAt() + e = nil + e.GetCreatedAt() +} + +func TestErrorResponse_GetBlock(tt *testing.T) { + e := &ErrorResponse{} + e.GetBlock() + e = nil + e.GetBlock() +} + func TestEvent_GetActor(tt *testing.T) { e := &Event{} e.GetActor() @@ -4582,6 +4671,48 @@ func TestFeedLink_GetType(tt *testing.T) { f.GetType() } +func TestFeedLinks_GetCurrentUser(tt *testing.T) { + f := &FeedLinks{} + f.GetCurrentUser() + f = nil + f.GetCurrentUser() +} + +func TestFeedLinks_GetCurrentUserActor(tt *testing.T) { + f := &FeedLinks{} + f.GetCurrentUserActor() + f = nil + f.GetCurrentUserActor() +} + +func TestFeedLinks_GetCurrentUserOrganization(tt *testing.T) { + f := &FeedLinks{} + f.GetCurrentUserOrganization() + f = nil + f.GetCurrentUserOrganization() +} + +func TestFeedLinks_GetCurrentUserPublic(tt *testing.T) { + f := &FeedLinks{} + f.GetCurrentUserPublic() + f = nil + f.GetCurrentUserPublic() +} + +func TestFeedLinks_GetTimeline(tt *testing.T) { + f := &FeedLinks{} + f.GetTimeline() + f = nil + f.GetTimeline() +} + +func TestFeedLinks_GetUser(tt *testing.T) { + f := &FeedLinks{} + f.GetUser() + f = nil + f.GetUser() +} + func TestFeeds_GetCurrentUserActorURL(tt *testing.T) { var zeroValue string f := &Feeds{CurrentUserActorURL: &zeroValue} @@ -4622,6 +4753,13 @@ func TestFeeds_GetCurrentUserURL(tt *testing.T) { f.GetCurrentUserURL() } +func TestFeeds_GetLinks(tt *testing.T) { + f := &Feeds{} + f.GetLinks() + f = nil + f.GetLinks() +} + func TestFeeds_GetTimelineURL(tt *testing.T) { var zeroValue string f := &Feeds{TimelineURL: &zeroValue} @@ -10953,6 +11091,16 @@ func TestProject_GetURL(tt *testing.T) { p.GetURL() } +func TestProjectBody_GetFrom(tt *testing.T) { + var zeroValue string + p := &ProjectBody{From: &zeroValue} + p.GetFrom() + p = &ProjectBody{} + p.GetFrom() + p = nil + p.GetFrom() +} + func TestProjectCard_GetArchived(tt *testing.T) { var zeroValue bool p := &ProjectCard{Archived: &zeroValue} @@ -11100,6 +11248,13 @@ func TestProjectCard_GetURL(tt *testing.T) { p.GetURL() } +func TestProjectCardChange_GetNote(tt *testing.T) { + p := &ProjectCardChange{} + p.GetNote() + p = nil + p.GetNote() +} + func TestProjectCardEvent_GetAction(tt *testing.T) { var zeroValue string p := &ProjectCardEvent{Action: &zeroValue} @@ -11172,6 +11327,16 @@ func TestProjectCardListOptions_GetArchivedState(tt *testing.T) { p.GetArchivedState() } +func TestProjectCardNote_GetFrom(tt *testing.T) { + var zeroValue string + p := &ProjectCardNote{From: &zeroValue} + p.GetFrom() + p = &ProjectCardNote{} + p.GetFrom() + p = nil + p.GetFrom() +} + func TestProjectCardOptions_GetArchived(tt *testing.T) { var zeroValue bool p := &ProjectCardOptions{Archived: &zeroValue} @@ -11182,6 +11347,20 @@ func TestProjectCardOptions_GetArchived(tt *testing.T) { p.GetArchived() } +func TestProjectChange_GetBody(tt *testing.T) { + p := &ProjectChange{} + p.GetBody() + p = nil + p.GetBody() +} + +func TestProjectChange_GetName(tt *testing.T) { + p := &ProjectChange{} + p.GetName() + p = nil + p.GetName() +} + func TestProjectCollaboratorOptions_GetPermission(tt *testing.T) { var zeroValue string p := &ProjectCollaboratorOptions{Permission: &zeroValue} @@ -11272,6 +11451,13 @@ func TestProjectColumn_GetURL(tt *testing.T) { p.GetURL() } +func TestProjectColumnChange_GetName(tt *testing.T) { + p := &ProjectColumnChange{} + p.GetName() + p = nil + p.GetName() +} + func TestProjectColumnEvent_GetAction(tt *testing.T) { var zeroValue string p := &ProjectColumnEvent{Action: &zeroValue} @@ -11334,6 +11520,16 @@ func TestProjectColumnEvent_GetSender(tt *testing.T) { p.GetSender() } +func TestProjectColumnName_GetFrom(tt *testing.T) { + var zeroValue string + p := &ProjectColumnName{From: &zeroValue} + p.GetFrom() + p = &ProjectColumnName{} + p.GetFrom() + p = nil + p.GetFrom() +} + func TestProjectEvent_GetAction(tt *testing.T) { var zeroValue string p := &ProjectEvent{Action: &zeroValue} @@ -11386,6 +11582,16 @@ func TestProjectEvent_GetSender(tt *testing.T) { p.GetSender() } +func TestProjectName_GetFrom(tt *testing.T) { + var zeroValue string + p := &ProjectName{From: &zeroValue} + p.GetFrom() + p = &ProjectName{} + p.GetFrom() + p = nil + p.GetFrom() +} + func TestProjectOptions_GetBody(tt *testing.T) { var zeroValue string p := &ProjectOptions{Body: &zeroValue} @@ -11474,6 +11680,13 @@ func TestProtection_GetEnforceAdmins(tt *testing.T) { p.GetEnforceAdmins() } +func TestProtection_GetRequiredConversationResolution(tt *testing.T) { + p := &Protection{} + p.GetRequiredConversationResolution() + p = nil + p.GetRequiredConversationResolution() +} + func TestProtection_GetRequiredPullRequestReviews(tt *testing.T) { p := &Protection{} p.GetRequiredPullRequestReviews() @@ -11671,6 +11884,13 @@ func TestPullRequest_GetAuthorAssociation(tt *testing.T) { p.GetAuthorAssociation() } +func TestPullRequest_GetAutoMerge(tt *testing.T) { + p := &PullRequest{} + p.GetAutoMerge() + p = nil + p.GetAutoMerge() +} + func TestPullRequest_GetBase(tt *testing.T) { p := &PullRequest{} p.GetBase() @@ -12043,6 +12263,43 @@ func TestPullRequest_GetUser(tt *testing.T) { p.GetUser() } +func TestPullRequestAutoMerge_GetCommitMessage(tt *testing.T) { + var zeroValue string + p := &PullRequestAutoMerge{CommitMessage: &zeroValue} + p.GetCommitMessage() + p = &PullRequestAutoMerge{} + p.GetCommitMessage() + p = nil + p.GetCommitMessage() +} + +func TestPullRequestAutoMerge_GetCommitTitle(tt *testing.T) { + var zeroValue string + p := &PullRequestAutoMerge{CommitTitle: &zeroValue} + p.GetCommitTitle() + p = &PullRequestAutoMerge{} + p.GetCommitTitle() + p = nil + p.GetCommitTitle() +} + +func TestPullRequestAutoMerge_GetEnabledBy(tt *testing.T) { + p := &PullRequestAutoMerge{} + p.GetEnabledBy() + p = nil + p.GetEnabledBy() +} + +func TestPullRequestAutoMerge_GetMergeMethod(tt *testing.T) { + var zeroValue string + p := &PullRequestAutoMerge{MergeMethod: &zeroValue} + p.GetMergeMethod() + p = &PullRequestAutoMerge{} + p.GetMergeMethod() + p = nil + p.GetMergeMethod() +} + func TestPullRequestBranch_GetLabel(tt *testing.T) { var zeroValue string p := &PullRequestBranch{Label: &zeroValue} @@ -14592,6 +14849,16 @@ func TestRepository_GetNotificationsURL(tt *testing.T) { r.GetNotificationsURL() } +func TestRepository_GetOpenIssues(tt *testing.T) { + var zeroValue int + r := &Repository{OpenIssues: &zeroValue} + r.GetOpenIssues() + r = &Repository{} + r.GetOpenIssues() + r = nil + r.GetOpenIssues() +} + func TestRepository_GetOpenIssuesCount(tt *testing.T) { var zeroValue int r := &Repository{OpenIssuesCount: &zeroValue} @@ -14847,6 +15114,16 @@ func TestRepository_GetVisibility(tt *testing.T) { r.GetVisibility() } +func TestRepository_GetWatchers(tt *testing.T) { + var zeroValue int + r := &Repository{Watchers: &zeroValue} + r.GetWatchers() + r = &Repository{} + r.GetWatchers() + r = nil + r.GetWatchers() +} + func TestRepository_GetWatchersCount(tt *testing.T) { var zeroValue int r := &Repository{WatchersCount: &zeroValue} @@ -15745,6 +16022,123 @@ func TestRepositoryTag_GetZipballURL(tt *testing.T) { r.GetZipballURL() } +func TestRepositoryVulnerabilityAlert_GetAffectedPackageName(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{AffectedPackageName: &zeroValue} + r.GetAffectedPackageName() + r = &RepositoryVulnerabilityAlert{} + r.GetAffectedPackageName() + r = nil + r.GetAffectedPackageName() +} + +func TestRepositoryVulnerabilityAlert_GetAffectedRange(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{AffectedRange: &zeroValue} + r.GetAffectedRange() + r = &RepositoryVulnerabilityAlert{} + r.GetAffectedRange() + r = nil + r.GetAffectedRange() +} + +func TestRepositoryVulnerabilityAlert_GetCreatedAt(tt *testing.T) { + var zeroValue Timestamp + r := &RepositoryVulnerabilityAlert{CreatedAt: &zeroValue} + r.GetCreatedAt() + r = &RepositoryVulnerabilityAlert{} + r.GetCreatedAt() + r = nil + r.GetCreatedAt() +} + +func TestRepositoryVulnerabilityAlert_GetDismissedAt(tt *testing.T) { + var zeroValue Timestamp + r := &RepositoryVulnerabilityAlert{DismissedAt: &zeroValue} + r.GetDismissedAt() + r = &RepositoryVulnerabilityAlert{} + r.GetDismissedAt() + r = nil + r.GetDismissedAt() +} + +func TestRepositoryVulnerabilityAlert_GetDismisser(tt *testing.T) { + r := &RepositoryVulnerabilityAlert{} + r.GetDismisser() + r = nil + r.GetDismisser() +} + +func TestRepositoryVulnerabilityAlert_GetDismissReason(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{DismissReason: &zeroValue} + r.GetDismissReason() + r = &RepositoryVulnerabilityAlert{} + r.GetDismissReason() + r = nil + r.GetDismissReason() +} + +func TestRepositoryVulnerabilityAlert_GetExternalIdentifier(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{ExternalIdentifier: &zeroValue} + r.GetExternalIdentifier() + r = &RepositoryVulnerabilityAlert{} + r.GetExternalIdentifier() + r = nil + r.GetExternalIdentifier() +} + +func TestRepositoryVulnerabilityAlert_GetExternalReference(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{ExternalReference: &zeroValue} + r.GetExternalReference() + r = &RepositoryVulnerabilityAlert{} + r.GetExternalReference() + r = nil + r.GetExternalReference() +} + +func TestRepositoryVulnerabilityAlert_GetFixedIn(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{FixedIn: &zeroValue} + r.GetFixedIn() + r = &RepositoryVulnerabilityAlert{} + r.GetFixedIn() + r = nil + r.GetFixedIn() +} + +func TestRepositoryVulnerabilityAlert_GetGitHubSecurityAdvisoryID(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{GitHubSecurityAdvisoryID: &zeroValue} + r.GetGitHubSecurityAdvisoryID() + r = &RepositoryVulnerabilityAlert{} + r.GetGitHubSecurityAdvisoryID() + r = nil + r.GetGitHubSecurityAdvisoryID() +} + +func TestRepositoryVulnerabilityAlert_GetID(tt *testing.T) { + var zeroValue int64 + r := &RepositoryVulnerabilityAlert{ID: &zeroValue} + r.GetID() + r = &RepositoryVulnerabilityAlert{} + r.GetID() + r = nil + r.GetID() +} + +func TestRepositoryVulnerabilityAlert_GetSeverity(tt *testing.T) { + var zeroValue string + r := &RepositoryVulnerabilityAlert{Severity: &zeroValue} + r.GetSeverity() + r = &RepositoryVulnerabilityAlert{} + r.GetSeverity() + r = nil + r.GetSeverity() +} + func TestRepositoryVulnerabilityAlertEvent_GetAction(tt *testing.T) { var zeroValue string r := &RepositoryVulnerabilityAlertEvent{Action: &zeroValue} @@ -15755,6 +16149,13 @@ func TestRepositoryVulnerabilityAlertEvent_GetAction(tt *testing.T) { r.GetAction() } +func TestRepositoryVulnerabilityAlertEvent_GetAlert(tt *testing.T) { + r := &RepositoryVulnerabilityAlertEvent{} + r.GetAlert() + r = nil + r.GetAlert() +} + func TestRepositoryVulnerabilityAlertEvent_GetRepository(tt *testing.T) { r := &RepositoryVulnerabilityAlertEvent{} r.GetRepository() @@ -16946,6 +17347,44 @@ func TestTeamAddEvent_GetTeam(tt *testing.T) { t.GetTeam() } +func TestTeamChange_GetDescription(tt *testing.T) { + t := &TeamChange{} + t.GetDescription() + t = nil + t.GetDescription() +} + +func TestTeamChange_GetName(tt *testing.T) { + t := &TeamChange{} + t.GetName() + t = nil + t.GetName() +} + +func TestTeamChange_GetPrivacy(tt *testing.T) { + t := &TeamChange{} + t.GetPrivacy() + t = nil + t.GetPrivacy() +} + +func TestTeamChange_GetRepository(tt *testing.T) { + t := &TeamChange{} + t.GetRepository() + t = nil + t.GetRepository() +} + +func TestTeamDescription_GetFrom(tt *testing.T) { + var zeroValue string + t := &TeamDescription{From: &zeroValue} + t.GetFrom() + t = &TeamDescription{} + t.GetFrom() + t = nil + t.GetFrom() +} + func TestTeamDiscussion_GetAuthor(tt *testing.T) { t := &TeamDiscussion{} t.GetAuthor() @@ -17272,6 +17711,63 @@ func TestTeamLDAPMapping_GetURL(tt *testing.T) { t.GetURL() } +func TestTeamName_GetFrom(tt *testing.T) { + var zeroValue string + t := &TeamName{From: &zeroValue} + t.GetFrom() + t = &TeamName{} + t.GetFrom() + t = nil + t.GetFrom() +} + +func TestTeamPermissions_GetFrom(tt *testing.T) { + t := &TeamPermissions{} + t.GetFrom() + t = nil + t.GetFrom() +} + +func TestTeamPermissionsFrom_GetAdmin(tt *testing.T) { + var zeroValue bool + t := &TeamPermissionsFrom{Admin: &zeroValue} + t.GetAdmin() + t = &TeamPermissionsFrom{} + t.GetAdmin() + t = nil + t.GetAdmin() +} + +func TestTeamPermissionsFrom_GetPull(tt *testing.T) { + var zeroValue bool + t := &TeamPermissionsFrom{Pull: &zeroValue} + t.GetPull() + t = &TeamPermissionsFrom{} + t.GetPull() + t = nil + t.GetPull() +} + +func TestTeamPermissionsFrom_GetPush(tt *testing.T) { + var zeroValue bool + t := &TeamPermissionsFrom{Push: &zeroValue} + t.GetPush() + t = &TeamPermissionsFrom{} + t.GetPush() + t = nil + t.GetPush() +} + +func TestTeamPrivacy_GetFrom(tt *testing.T) { + var zeroValue string + t := &TeamPrivacy{From: &zeroValue} + t.GetFrom() + t = &TeamPrivacy{} + t.GetFrom() + t = nil + t.GetFrom() +} + func TestTeamProjectOptions_GetPermission(tt *testing.T) { var zeroValue string t := &TeamProjectOptions{Permission: &zeroValue} @@ -17282,6 +17778,13 @@ func TestTeamProjectOptions_GetPermission(tt *testing.T) { t.GetPermission() } +func TestTeamRepository_GetPermissions(tt *testing.T) { + t := &TeamRepository{} + t.GetPermissions() + t = nil + t.GetPermissions() +} + func TestTemplateRepoRequest_GetDescription(tt *testing.T) { var zeroValue string t := &TemplateRepoRequest{Description: &zeroValue} @@ -17471,6 +17974,16 @@ func TestTimeline_GetSource(tt *testing.T) { t.GetSource() } +func TestTimeline_GetState(tt *testing.T) { + var zeroValue string + t := &Timeline{State: &zeroValue} + t.GetState() + t = &Timeline{} + t.GetState() + t = nil + t.GetState() +} + func TestTimeline_GetURL(tt *testing.T) { var zeroValue string t := &Timeline{URL: &zeroValue} @@ -17481,6 +17994,36 @@ func TestTimeline_GetURL(tt *testing.T) { t.GetURL() } +func TestTool_GetGUID(tt *testing.T) { + var zeroValue string + t := &Tool{GUID: &zeroValue} + t.GetGUID() + t = &Tool{} + t.GetGUID() + t = nil + t.GetGUID() +} + +func TestTool_GetName(tt *testing.T) { + var zeroValue string + t := &Tool{Name: &zeroValue} + t.GetName() + t = &Tool{} + t.GetName() + t = nil + t.GetName() +} + +func TestTool_GetVersion(tt *testing.T) { + var zeroValue string + t := &Tool{Version: &zeroValue} + t.GetVersion() + t = &Tool{} + t.GetVersion() + t = nil + t.GetVersion() +} + func TestTopicResult_GetCreatedAt(tt *testing.T) { var zeroValue Timestamp t := &TopicResult{CreatedAt: &zeroValue} diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go index cf0c7ebe817..952176a60db 100644 --- a/github/github-stringify_test.go +++ b/github/github-stringify_test.go @@ -1129,12 +1129,13 @@ func TestPullRequest_String(t *testing.T) { MaintainerCanModify: Bool(false), AuthorAssociation: String(""), NodeID: String(""), + AutoMerge: &PullRequestAutoMerge{}, Links: &PRLinks{}, Head: &PullRequestBranch{}, Base: &PullRequestBranch{}, ActiveLockReason: String(""), } - want := `github.PullRequest{ID:0, Number:0, State:"", Locked:false, Title:"", Body:"", User:github.User{}, Draft:false, Merged:false, Mergeable:false, MergeableState:"", MergedBy:github.User{}, MergeCommitSHA:"", Rebaseable:false, Comments:0, Commits:0, Additions:0, Deletions:0, ChangedFiles:0, URL:"", HTMLURL:"", IssueURL:"", StatusesURL:"", DiffURL:"", PatchURL:"", CommitsURL:"", CommentsURL:"", ReviewCommentsURL:"", ReviewCommentURL:"", ReviewComments:0, Assignee:github.User{}, Milestone:github.Milestone{}, MaintainerCanModify:false, AuthorAssociation:"", NodeID:"", Links:github.PRLinks{}, Head:github.PullRequestBranch{}, Base:github.PullRequestBranch{}, ActiveLockReason:""}` + want := `github.PullRequest{ID:0, Number:0, State:"", Locked:false, Title:"", Body:"", User:github.User{}, Draft:false, Merged:false, Mergeable:false, MergeableState:"", MergedBy:github.User{}, MergeCommitSHA:"", Rebaseable:false, Comments:0, Commits:0, Additions:0, Deletions:0, ChangedFiles:0, URL:"", HTMLURL:"", IssueURL:"", StatusesURL:"", DiffURL:"", PatchURL:"", CommitsURL:"", CommentsURL:"", ReviewCommentsURL:"", ReviewCommentURL:"", ReviewComments:0, Assignee:github.User{}, Milestone:github.Milestone{}, MaintainerCanModify:false, AuthorAssociation:"", NodeID:"", AutoMerge:github.PullRequestAutoMerge{}, Links:github.PRLinks{}, Head:github.PullRequestBranch{}, Base:github.PullRequestBranch{}, ActiveLockReason:""}` if got := v.String(); got != want { t.Errorf("PullRequest.String = %v, want %v", got, want) } @@ -1381,9 +1382,11 @@ func TestRepository_String(t *testing.T) { ForksCount: Int(0), NetworkCount: Int(0), OpenIssuesCount: Int(0), + OpenIssues: Int(0), StargazersCount: Int(0), SubscribersCount: Int(0), WatchersCount: Int(0), + Watchers: Int(0), Size: Int(0), AutoInit: Bool(false), Parent: &Repository{}, @@ -1446,7 +1449,7 @@ func TestRepository_String(t *testing.T) { TeamsURL: String(""), Visibility: String(""), } - want := `github.Repository{ID:0, NodeID:"", Owner:github.User{}, Name:"", FullName:"", Description:"", Homepage:"", CodeOfConduct:github.CodeOfConduct{}, DefaultBranch:"", MasterBranch:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PushedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", CloneURL:"", GitURL:"", MirrorURL:"", SSHURL:"", SVNURL:"", Language:"", Fork:false, ForksCount:0, NetworkCount:0, OpenIssuesCount:0, StargazersCount:0, SubscribersCount:0, WatchersCount:0, Size:0, AutoInit:false, Parent:github.Repository{}, Source:github.Repository{}, TemplateRepository:github.Repository{}, Organization:github.Organization{}, AllowRebaseMerge:false, AllowSquashMerge:false, AllowMergeCommit:false, DeleteBranchOnMerge:false, Archived:false, Disabled:false, License:github.License{}, Private:false, HasIssues:false, HasWiki:false, HasPages:false, HasProjects:false, HasDownloads:false, IsTemplate:false, LicenseTemplate:"", GitignoreTemplate:"", TeamID:0, URL:"", ArchiveURL:"", AssigneesURL:"", BlobsURL:"", BranchesURL:"", CollaboratorsURL:"", CommentsURL:"", CommitsURL:"", CompareURL:"", ContentsURL:"", ContributorsURL:"", DeploymentsURL:"", DownloadsURL:"", EventsURL:"", ForksURL:"", GitCommitsURL:"", GitRefsURL:"", GitTagsURL:"", HooksURL:"", IssueCommentURL:"", IssueEventsURL:"", IssuesURL:"", KeysURL:"", LabelsURL:"", LanguagesURL:"", MergesURL:"", MilestonesURL:"", NotificationsURL:"", PullsURL:"", ReleasesURL:"", StargazersURL:"", StatusesURL:"", SubscribersURL:"", SubscriptionURL:"", TagsURL:"", TreesURL:"", TeamsURL:"", Visibility:""}` + want := `github.Repository{ID:0, NodeID:"", Owner:github.User{}, Name:"", FullName:"", Description:"", Homepage:"", CodeOfConduct:github.CodeOfConduct{}, DefaultBranch:"", MasterBranch:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PushedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", CloneURL:"", GitURL:"", MirrorURL:"", SSHURL:"", SVNURL:"", Language:"", Fork:false, ForksCount:0, NetworkCount:0, OpenIssuesCount:0, OpenIssues:0, StargazersCount:0, SubscribersCount:0, WatchersCount:0, Watchers:0, Size:0, AutoInit:false, Parent:github.Repository{}, Source:github.Repository{}, TemplateRepository:github.Repository{}, Organization:github.Organization{}, AllowRebaseMerge:false, AllowSquashMerge:false, AllowMergeCommit:false, DeleteBranchOnMerge:false, Archived:false, Disabled:false, License:github.License{}, Private:false, HasIssues:false, HasWiki:false, HasPages:false, HasProjects:false, HasDownloads:false, IsTemplate:false, LicenseTemplate:"", GitignoreTemplate:"", TeamID:0, URL:"", ArchiveURL:"", AssigneesURL:"", BlobsURL:"", BranchesURL:"", CollaboratorsURL:"", CommentsURL:"", CommitsURL:"", CompareURL:"", ContentsURL:"", ContributorsURL:"", DeploymentsURL:"", DownloadsURL:"", EventsURL:"", ForksURL:"", GitCommitsURL:"", GitRefsURL:"", GitTagsURL:"", HooksURL:"", IssueCommentURL:"", IssueEventsURL:"", IssuesURL:"", KeysURL:"", LabelsURL:"", LanguagesURL:"", MergesURL:"", MilestonesURL:"", NotificationsURL:"", PullsURL:"", ReleasesURL:"", StargazersURL:"", StatusesURL:"", SubscribersURL:"", SubscriptionURL:"", TagsURL:"", TreesURL:"", TeamsURL:"", Visibility:""}` if got := v.String(); got != want { t.Errorf("Repository.String = %v, want %v", got, want) } diff --git a/github/github.go b/github/github.go index efde8f8dbab..264e27f476d 100644 --- a/github/github.go +++ b/github/github.go @@ -522,6 +522,12 @@ func parseRate(r *http.Response) Rate { return rate } +type requestContext uint8 + +const ( + bypassRateLimitCheck requestContext = iota +) + // BareDo sends an API request and lets you handle the api response. If an error // or API Error occurs, the error will contain more information. Otherwise you // are supposed to read and close the response's Body. If rate limit is exceeded @@ -538,12 +544,14 @@ func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, erro rateLimitCategory := category(req.URL.Path) - // If we've hit rate limit, don't make further requests before Reset time. - if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { - return &Response{ - Response: err.Response, - Rate: err.Rate, - }, err + if bypass := ctx.Value(bypassRateLimitCheck); bypass == nil { + // If we've hit rate limit, don't make further requests before Reset time. + if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { + return &Response{ + Response: err.Response, + Rate: err.Rate, + }, err + } } resp, err := c.client.Do(req) @@ -679,18 +687,21 @@ type ErrorResponse struct { Message string `json:"message"` // error message Errors []Error `json:"errors"` // more detail on individual errors // Block is only populated on certain types of errors such as code 451. - // See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ - // for more information. - Block *struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - } `json:"block,omitempty"` + 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/en/free-pro-team@latest/rest/reference/#client-errors 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"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + func (r *ErrorResponse) Error() string { return fmt.Sprintf("%v %v: %d %v %+v", r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), @@ -1022,6 +1033,9 @@ func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) response := new(struct { Resources *RateLimits `json:"resources"` }) + + // This resource is not subject to rate limits. + ctx = context.WithValue(ctx, bypassRateLimitCheck, true) resp, err := c.Do(ctx, req, response) if err != nil { return nil, resp, err diff --git a/github/github_test.go b/github/github_test.go index 828898fd0e9..158510abe24 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -201,6 +201,9 @@ func testNewRequestAndDoFailure(t *testing.T, methodName string, client *Client, client.BaseURL.Path = "/api-v3/" client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute) resp, err = f() + if bypass := resp.Request.Context().Value(bypassRateLimitCheck); bypass != nil { + return + } if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want { if resp != nil { t.Errorf("rate.Reset.Time > now %v resp = %#v, want StatusCode=%v", methodName, resp.Response, want) @@ -1091,10 +1094,7 @@ func TestCheckResponse(t *testing.T) { Response: res, Message: "m", Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "dmca", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1194,10 +1194,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Message: "m", Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1213,10 +1210,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1229,10 +1223,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m1", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1245,10 +1236,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1260,10 +1248,7 @@ func TestErrorResponse_Is(t *testing.T) { otherError: &ErrorResponse{ Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1276,10 +1261,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r1", Field: "f1", Code: "c1"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1292,10 +1274,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1317,10 +1296,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r1", CreatedAt: &Timestamp{time.Date(2016, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1333,10 +1309,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: nil, }, @@ -1349,10 +1322,7 @@ func TestErrorResponse_Is(t *testing.T) { Response: &http.Response{}, Errors: []Error{{Resource: "r", Field: "f", Code: "c"}}, Message: "m", - Block: &struct { - Reason string `json:"reason,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - }{ + Block: &ErrorBlock{ Reason: "r", CreatedAt: &Timestamp{time.Date(2017, time.March, 17, 15, 39, 46, 0, time.UTC)}, }, @@ -1711,6 +1681,52 @@ func TestRateLimits_coverage(t *testing.T) { }) } +func TestRateLimits_overQuota(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + client.rateLimits[coreCategory] = Rate{ + Limit: 1, + Remaining: 0, + Reset: Timestamp{time.Now().Add(time.Hour).Local()}, + } + mux.HandleFunc("/rate_limit", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, `{"resources":{ + "core": {"limit":2,"remaining":1,"reset":1372700873}, + "search": {"limit":3,"remaining":2,"reset":1372700874} + }}`) + }) + + ctx := context.Background() + rate, _, err := client.RateLimits(ctx) + if err != nil { + t.Errorf("RateLimits returned error: %v", err) + } + + want := &RateLimits{ + Core: &Rate{ + Limit: 2, + Remaining: 1, + Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 53, 0, time.UTC).Local()}, + }, + Search: &Rate{ + Limit: 3, + Remaining: 2, + Reset: Timestamp{time.Date(2013, time.July, 1, 17, 47, 54, 0, time.UTC).Local()}, + }, + } + if !cmp.Equal(rate, want) { + t.Errorf("RateLimits returned %+v, want %+v", rate, want) + } + + if got, want := client.rateLimits[coreCategory], *want.Core; got != want { + t.Errorf("client.rateLimits[coreCategory] is %+v, want %+v", got, want) + } + if got, want := client.rateLimits[searchCategory], *want.Search; got != want { + t.Errorf("client.rateLimits[searchCategory] is %+v, want %+v", got, want) + } +} + func TestSetCredentialsAsHeaders(t *testing.T) { req := new(http.Request) id, secret := "id", "secret" @@ -1997,3 +2013,10 @@ func TestBareDo_returnsOpenBody(t *testing.T) { t.Fatalf("resp.Body.Close() returned error: %v", err) } } + +// roundTripperFunc creates a mock RoundTripper (transport) +type roundTripperFunc func(*http.Request) (*http.Response, error) + +func (fn roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { + return fn(r) +} diff --git a/github/issues_timeline.go b/github/issues_timeline.go index 2033a7237bb..1fd13b128c7 100644 --- a/github/issues_timeline.go +++ b/github/issues_timeline.go @@ -81,6 +81,9 @@ type Timeline struct { // reopened // The issue was reopened by the actor. // + // reviewed + // The pull request was reviewed. + // // subscribed // The actor subscribed to receive notifications for an issue. // @@ -118,6 +121,10 @@ type Timeline struct { // Only provided for 'renamed' events. Rename *Rename `json:"rename,omitempty"` ProjectCard *ProjectCard `json:"project_card,omitempty"` + // The state of a submitted review. Can be one of: 'commented', + // 'changes_requested' or 'approved'. + // Only provided for 'reviewed' events. + State *string `json:"state,omitempty"` } // Source represents a reference's source. diff --git a/github/messages.go b/github/messages.go index 98a76da644d..06ea9e4cfe5 100644 --- a/github/messages.go +++ b/github/messages.go @@ -19,6 +19,7 @@ import ( "fmt" "hash" "io/ioutil" + "mime" "net/http" "net/url" "strings" @@ -157,7 +158,14 @@ func messageMAC(signature string) ([]byte, func() hash.Hash, error) { func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) { var body []byte // Raw body that GitHub uses to calculate the signature. - switch ct := r.Header.Get("Content-Type"); ct { + ct := r.Header.Get("Content-Type") + + mediatype, _, err := mime.ParseMediaType(ct) + if err != nil { + mediatype = "" + } + + switch mediatype { case "application/json": var err error if body, err = ioutil.ReadAll(r.Body); err != nil { diff --git a/github/messages_test.go b/github/messages_test.go index a13e5a99c65..5fed4a2d244 100644 --- a/github/messages_test.go +++ b/github/messages_test.go @@ -229,6 +229,33 @@ func TestValidatePayload_BadRequestBody(t *testing.T) { } } +func TestValidatePayload_InvalidContentTypeParams(t *testing.T) { + req, err := http.NewRequest("POST", "http://localhost/event", nil) + if err != nil { + t.Fatalf("NewRequest: %v", err) + } + req.Header.Set("Content-Type", "application/json; charset=") + if _, err = ValidatePayload(req, nil); err == nil { + t.Error("ValidatePayload = nil, want err") + } +} + +func TestValidatePayload_ValidContentTypeParams(t *testing.T) { + var requestBody = `{"yo":true}` + buf := bytes.NewBufferString(requestBody) + + req, err := http.NewRequest("POST", "http://localhost/event", buf) + if err != nil { + t.Fatalf("NewRequest: %v", err) + } + req.Header.Set("Content-Type", "application/json; charset=UTF-8") + + _, err = ValidatePayload(req, nil) + if err != nil { + t.Error("ValidatePayload = nil, want err") + } +} + func TestParseWebHook(t *testing.T) { tests := []struct { payload interface{} diff --git a/github/pulls.go b/github/pulls.go index 0b48c232a6d..6c866ea8840 100644 --- a/github/pulls.go +++ b/github/pulls.go @@ -18,50 +18,59 @@ import ( // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/ type PullRequestsService service +// PullRequestAutoMerge represents the "auto_merge" response for a PullRequest. +type PullRequestAutoMerge struct { + EnabledBy *User `json:"enabled_by,omitempty"` + MergeMethod *string `json:"merge_method,omitempty"` + CommitTitle *string `json:"commit_title,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + // PullRequest represents a GitHub pull request on a repository. type PullRequest struct { - ID *int64 `json:"id,omitempty"` - Number *int `json:"number,omitempty"` - State *string `json:"state,omitempty"` - Locked *bool `json:"locked,omitempty"` - Title *string `json:"title,omitempty"` - Body *string `json:"body,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - ClosedAt *time.Time `json:"closed_at,omitempty"` - MergedAt *time.Time `json:"merged_at,omitempty"` - Labels []*Label `json:"labels,omitempty"` - User *User `json:"user,omitempty"` - Draft *bool `json:"draft,omitempty"` - Merged *bool `json:"merged,omitempty"` - Mergeable *bool `json:"mergeable,omitempty"` - MergeableState *string `json:"mergeable_state,omitempty"` - MergedBy *User `json:"merged_by,omitempty"` - MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` - Rebaseable *bool `json:"rebaseable,omitempty"` - Comments *int `json:"comments,omitempty"` - Commits *int `json:"commits,omitempty"` - Additions *int `json:"additions,omitempty"` - Deletions *int `json:"deletions,omitempty"` - ChangedFiles *int `json:"changed_files,omitempty"` - URL *string `json:"url,omitempty"` - HTMLURL *string `json:"html_url,omitempty"` - IssueURL *string `json:"issue_url,omitempty"` - StatusesURL *string `json:"statuses_url,omitempty"` - DiffURL *string `json:"diff_url,omitempty"` - PatchURL *string `json:"patch_url,omitempty"` - CommitsURL *string `json:"commits_url,omitempty"` - CommentsURL *string `json:"comments_url,omitempty"` - ReviewCommentsURL *string `json:"review_comments_url,omitempty"` - ReviewCommentURL *string `json:"review_comment_url,omitempty"` - ReviewComments *int `json:"review_comments,omitempty"` - Assignee *User `json:"assignee,omitempty"` - Assignees []*User `json:"assignees,omitempty"` - Milestone *Milestone `json:"milestone,omitempty"` - MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` - AuthorAssociation *string `json:"author_association,omitempty"` - NodeID *string `json:"node_id,omitempty"` - RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + MergedAt *time.Time `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Draft *bool `json:"draft,omitempty"` + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Rebaseable *bool `json:"rebaseable,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + ReviewComments *int `json:"review_comments,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` // RequestedTeams is populated as part of the PullRequestEvent. // See, https://docs.github.com/en/developers/webhooks-and-events/github-event-types#pullrequestevent for an example. diff --git a/github/repos.go b/github/repos.go index 8f34cf8b6d3..d336e8bf773 100644 --- a/github/repos.go +++ b/github/repos.go @@ -9,6 +9,7 @@ import ( "context" "encoding/json" "fmt" + "net/http" "strings" ) @@ -44,9 +45,11 @@ type Repository struct { ForksCount *int `json:"forks_count,omitempty"` NetworkCount *int `json:"network_count,omitempty"` OpenIssuesCount *int `json:"open_issues_count,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated. StargazersCount *int `json:"stargazers_count,omitempty"` SubscribersCount *int `json:"subscribers_count,omitempty"` - WatchersCount *int `json:"watchers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated. + Watchers *int `json:"watchers,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated. Size *int `json:"size,omitempty"` AutoInit *bool `json:"auto_init,omitempty"` Parent *Repository `json:"parent,omitempty"` @@ -751,13 +754,14 @@ type Branch struct { // Protection represents a repository branch's protection. type Protection struct { - RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` - RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` - EnforceAdmins *AdminEnforcement `json:"enforce_admins"` - Restrictions *BranchRestrictions `json:"restrictions"` - RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` - AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` - AllowDeletions *AllowDeletions `json:"allow_deletions"` + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` + EnforceAdmins *AdminEnforcement `json:"enforce_admins"` + Restrictions *BranchRestrictions `json:"restrictions"` + RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` + AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` + AllowDeletions *AllowDeletions `json:"allow_deletions"` + RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"` } // ProtectionRequest represents a request to create/edit a branch's protection. @@ -849,6 +853,11 @@ type AllowForcePushes struct { Enabled bool `json:"enabled"` } +// RequiredConversationResolution, if enabled, requires all comments on the pull request to be resolved before it can be merged to a protected branch. +type RequiredConversationResolution struct { + Enabled bool `json:"enabled"` +} + // AdminEnforcement represents the configuration to enforce required status checks for repository administrators. type AdminEnforcement struct { URL *string `json:"url,omitempty"` @@ -933,20 +942,49 @@ func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, re // GetBranch gets the specified branch for a repository. // // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-a-branch -func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) { +func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, followRedirects bool) (*Branch, *Response, error) { u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) - req, err := s.client.NewRequest("GET", u, nil) + + resp, err := s.getBranchFromURL(ctx, u, followRedirects) if err != nil { return nil, nil, err } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } b := new(Branch) - resp, err := s.client.Do(ctx, req, b) + err = json.NewDecoder(resp.Body).Decode(b) + return b, newResponse(resp), err +} + +func (s *RepositoriesService) getBranchFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) { + req, err := s.client.NewRequest("GET", u, nil) if err != nil { - return nil, resp, err + return nil, err } - return b, resp, nil + var resp *http.Response + // Use http.DefaultTransport if no custom Transport is configured + req = withContext(ctx, req) + if s.client.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = s.client.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, err + } + + // If redirect response is returned, follow it + if followRedirects && resp.StatusCode == http.StatusMovedPermanently { + resp.Body.Close() + u = resp.Header.Get("Location") + resp, err = s.getBranchFromURL(ctx, u, false) + } + return resp, err } // GetBranchProtection gets the protection of a given branch. diff --git a/github/repos_contents_test.go b/github/repos_contents_test.go index a58833325b2..c5874669609 100644 --- a/github/repos_contents_test.go +++ b/github/repos_contents_test.go @@ -7,6 +7,7 @@ package github import ( "context" + "errors" "fmt" "io/ioutil" "net/http" @@ -690,6 +691,15 @@ func TestRepositoriesService_GetArchiveLink(t *testing.T) { _, _, err = client.Repositories.GetArchiveLink(ctx, "\n", "\n", Tarball, &RepositoryContentGetOptions{}, true) return err }) + + // Add custom round tripper + client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { + return nil, errors.New("failed to get archive link") + }) + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true) + return err + }) } func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_dontFollowRedirects(t *testing.T) { diff --git a/github/repos_test.go b/github/repos_test.go index 7e42229e878..4bb6be22a56 100644 --- a/github/repos_test.go +++ b/github/repos_test.go @@ -8,8 +8,10 @@ package github import ( "context" "encoding/json" + "errors" "fmt" "net/http" + "net/url" "strings" "testing" @@ -886,7 +888,7 @@ func TestRepositoriesService_GetBranch(t *testing.T) { }) ctx := context.Background() - branch, _, err := client.Repositories.GetBranch(ctx, "o", "r", "b") + branch, _, err := client.Repositories.GetBranch(ctx, "o", "r", "b", false) if err != nil { t.Errorf("Repositories.GetBranch returned error: %v", err) } @@ -908,16 +910,74 @@ func TestRepositoriesService_GetBranch(t *testing.T) { const methodName = "GetBranch" testBadOptions(t, methodName, func() (err error) { - _, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n") + _, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", false) return err }) +} - testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { - got, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b") - if got != nil { - t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) - } - return resp, err +func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t *testing.T) { + client, mux, serverURL, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + redirectURL, _ := url.Parse(serverURL + baseURLPath + "/repos/o/r/branches/br") + http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently) + }) + mux.HandleFunc("/repos/o/r/branches/br", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`) + }) + ctx := context.Background() + branch, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", true) + if err != nil { + t.Errorf("Repositories.GetBranch returned error: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusOK) + } + + want := &Branch{ + Name: String("n"), + Commit: &RepositoryCommit{ + SHA: String("s"), + Commit: &Commit{ + Message: String("m"), + }, + }, + Protected: Bool(true), + } + if !cmp.Equal(branch, want) { + t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want) + } +} + +func TestRepositoriesService_GetBranch_notFound(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + http.Error(w, "branch not found", http.StatusNotFound) + }) + ctx := context.Background() + _, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", true) + if err == nil { + t.Error("Repositories.GetBranch returned error: nil") + } + if resp.StatusCode != http.StatusNotFound { + t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusNotFound) + } + + // Add custom round tripper + client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { + return nil, errors.New("failed to get branch") + }) + + const methodName = "GetBranch" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Repositories.GetBranch(ctx, "o", "r", "b", true) + return err }) } @@ -959,6 +1019,9 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) { "restrictions":{ "users":[{"id":1,"login":"u"}], "teams":[{"id":2,"slug":"t"}] + }, + "required_conversation_resolution": { + "enabled": true } }`) }) @@ -999,6 +1062,9 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) { {Slug: String("t"), ID: Int64(2)}, }, }, + RequiredConversationResolution: &RequiredConversationResolution{ + Enabled: true, + }, } if !cmp.Equal(protection, want) { t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want) diff --git a/github/teams_test.go b/github/teams_test.go index 1409cf5610e..aa18e8a8af5 100644 --- a/github/teams_test.go +++ b/github/teams_test.go @@ -1585,3 +1585,89 @@ func TestTeamsService_CreateOrUpdateIDPGroupConnectionsBySlug_empty(t *testing.T t.Errorf("Teams.CreateOrUpdateIDPGroupConnectionsBySlug returned %+v. want %+v", groups, want) } } + +func TestTeams_marshall(t *testing.T) { + testJSONMarshal(t, &Team{}, "{}") + + u := &Team{ + ID: Int64(1), + NodeID: String("n"), + Name: String("n"), + Description: String("d"), + URL: String("u"), + Slug: String("s"), + Permission: String("p"), + Privacy: String("p"), + MembersCount: Int(1), + ReposCount: Int(1), + MembersURL: String("m"), + RepositoriesURL: String("r"), + Organization: &Organization{ + Login: String("l"), + ID: Int64(1), + NodeID: String("n"), + AvatarURL: String("a"), + HTMLURL: String("h"), + Name: String("n"), + Company: String("c"), + Blog: String("b"), + Location: String("l"), + Email: String("e"), + }, + Parent: &Team{ + ID: Int64(1), + NodeID: String("n"), + Name: String("n"), + Description: String("d"), + URL: String("u"), + Slug: String("s"), + Permission: String("p"), + Privacy: String("p"), + MembersCount: Int(1), + ReposCount: Int(1), + }, + LDAPDN: String("l"), + } + + want := `{ + "id": 1, + "node_id": "n", + "name": "n", + "description": "d", + "url": "u", + "slug": "s", + "permission": "p", + "privacy": "p", + "members_count": 1, + "repos_count": 1, + "members_url": "m", + "repositories_url": "r", + "organization": { + "login": "l", + "id": 1, + "node_id": "n", + "avatar_url": "a", + "html_url": "h", + "name": "n", + "company": "c", + "blog": "b", + "location": "l", + "email": "e" + }, + "parent": { + "id": 1, + "node_id": "n", + "name": "n", + "description": "d", + "url": "u", + "slug": "s", + "permission": "p", + "privacy": "p", + "members_count": 1, + "repos_count": 1 + }, + "ldap_dn": "l" + }` + + testJSONMarshal(t, u, want) +} diff --git a/go.mod b/go.mod index a4d53c838f6..c2d65842679 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/google/go-github/v35 +module github.com/google/go-github/v37 require ( github.com/golang/protobuf v1.3.2 // indirect diff --git a/test/fields/fields.go b/test/fields/fields.go index 07cf9451da7..149a3e078c2 100644 --- a/test/fields/fields.go +++ b/test/fields/fields.go @@ -25,7 +25,7 @@ import ( "reflect" "strings" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/test/integration/activity_test.go b/test/integration/activity_test.go index f0a85461f6a..d1b8b5013e8 100644 --- a/test/integration/activity_test.go +++ b/test/integration/activity_test.go @@ -12,7 +12,7 @@ import ( "context" "testing" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) const ( diff --git a/test/integration/authorizations_test.go b/test/integration/authorizations_test.go index e0f05f527fd..0841ffc4f2d 100644 --- a/test/integration/authorizations_test.go +++ b/test/integration/authorizations_test.go @@ -17,7 +17,7 @@ import ( "testing" "time" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) const msgEnvMissing = "Skipping test because the required environment variable (%v) is not present." diff --git a/test/integration/github_test.go b/test/integration/github_test.go index 21bcf1a3577..5dd6b4b494a 100644 --- a/test/integration/github_test.go +++ b/test/integration/github_test.go @@ -15,7 +15,7 @@ import ( "net/http" "os" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" "golang.org/x/oauth2" ) diff --git a/test/integration/repos_test.go b/test/integration/repos_test.go index 30445adab7c..ddaae4a0a26 100644 --- a/test/integration/repos_test.go +++ b/test/integration/repos_test.go @@ -16,7 +16,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) func TestRepositories_CRUD(t *testing.T) { @@ -70,7 +70,7 @@ func TestRepositories_BranchesTags(t *testing.T) { t.Fatalf("Repositories.ListBranches('git', 'git') returned no branches") } - _, _, err = client.Repositories.GetBranch(context.Background(), "git", "git", *branches[0].Name) + _, _, err = client.Repositories.GetBranch(context.Background(), "git", "git", *branches[0].Name, false) if err != nil { t.Fatalf("Repositories.GetBranch() returned error: %v", err) } @@ -102,7 +102,7 @@ func TestRepositories_EditBranches(t *testing.T) { t.Fatalf("createRandomTestRepository returned error: %v", err) } - branch, _, err := client.Repositories.GetBranch(context.Background(), *repo.Owner.Login, *repo.Name, "master") + branch, _, err := client.Repositories.GetBranch(context.Background(), *repo.Owner.Login, *repo.Name, "master", false) if err != nil { t.Fatalf("Repositories.GetBranch() returned error: %v", err) } diff --git a/test/integration/users_test.go b/test/integration/users_test.go index 1b8145e87ff..f983d0dbd97 100644 --- a/test/integration/users_test.go +++ b/test/integration/users_test.go @@ -14,7 +14,7 @@ import ( "math/rand" "testing" - "github.com/google/go-github/v35/github" + "github.com/google/go-github/v37/github" ) func TestUsers_Get(t *testing.T) { diff --git a/update-urls/main.go b/update-urls/main.go index d0d4955abd9..a82ffbd9ced 100644 --- a/update-urls/main.go +++ b/update-urls/main.go @@ -655,12 +655,12 @@ func (e *Endpoint) String() string { return b.String() } -func (ep *Endpoint) checkHttpMethodOverride(path string) { - lookupOverride := fmt.Sprintf("%v.%v: %v %v", ep.serviceName, ep.endpointName, ep.httpMethod, path) +func (e *Endpoint) checkHttpMethodOverride(path string) { + lookupOverride := fmt.Sprintf("%v.%v: %v %v", e.serviceName, e.endpointName, e.httpMethod, path) logf("Looking up override for %q", lookupOverride) if v, ok := methodOverrides[lookupOverride]; ok { logf("overriding method for %v to %q", lookupOverride, v) - ep.httpMethod = v + e.httpMethod = v return } }