Repository: google/go-github
Pull request #1870 (2021-05-07 13:40:33)

Change all *map to map in JSON structs
Fixes: #1865.

Note that this should _not_ be a breaking API change if I'm not mistaken.

codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#1870](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (4ba396a) into [master](https://codecov.io/gh/google/go-github/commit/a19996a59629e9dc2b32dc2fb8628040e6e38459?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (a19996a) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-github/pull/1870/graphs/tree.svg?width=650&height=150&src=pr&token=EgYjGjZlI0&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)

```diff
@@           Coverage Diff           @@
##           master    #1870   +/-   ##
=======================================
  Coverage   97.65%   97.65%           
=======================================
  Files         105      105           
  Lines        6771     6771           
=======================================
  Hits         6612     6612           
  Misses         86       86           
  Partials       73       73           
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/repos.go](https://codecov.io/gh/google/go-github/pull/1870/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3JlcG9zLmdv) | `98.70% <ø> (ø)` | |
| [github/teams.go](https://codecov.io/gh/google/go-github/pull/1870/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3RlYW1zLmdv) | `98.09% <ø> (ø)` | |
| [github/users.go](https://codecov.io/gh/google/go-github/pull/1870/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3VzZXJzLmdv) | `94.73% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Last update [a19996a...4ba396a](https://codecov.io/gh/google/go-github/pull/1870?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).


Patch:
diff --git a/github/github-accessors.go b/github/github-accessors.go
index e6f34943..c392d8c9 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -5412,6 +5412,22 @@ func (i *Invitation) GetEmail() string {
 	return *i.Email
 }
 
+// GetFailedAt returns the FailedAt field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetFailedAt() Timestamp {
+	if i == nil || i.FailedAt == nil {
+		return Timestamp{}
+	}
+	return *i.FailedAt
+}
+
+// GetFailedReason returns the FailedReason field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetFailedReason() string {
+	if i == nil || i.FailedReason == nil {
+		return ""
+	}
+	return *i.FailedReason
+}
+
 // GetID returns the ID field if it's non-nil, zero value otherwise.
 func (i *Invitation) GetID() int64 {
 	if i == nil || i.ID == nil {
@@ -12420,12 +12436,12 @@ func (r *Repository) GetParent() *Repository {
 	return r.Parent
 }
 
-// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise.
 func (r *Repository) GetPermissions() map[string]bool {
 	if r == nil || r.Permissions == nil {
 		return map[string]bool{}
 	}
-	return *r.Permissions
+	return r.Permissions
 }
 
 // GetPrivate returns the Private field if it's non-nil, zero value otherwise.
@@ -14308,12 +14324,12 @@ func (t *Team) GetPermission() string {
 	return *t.Permission
 }
 
-// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise.
 func (t *Team) GetPermissions() map[string]bool {
 	if t == nil || t.Permissions == nil {
 		return map[string]bool{}
 	}
-	return *t.Permissions
+	return t.Permissions
 }
 
 // GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise.
@@ -15396,12 +15412,12 @@ func (u *User) GetOwnedPrivateRepos() int {
 	return *u.OwnedPrivateRepos
 }
 
-// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise.
+// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise.
 func (u *User) GetPermissions() map[string]bool {
 	if u == nil || u.Permissions == nil {
 		return map[string]bool{}
 	}
-	return *u.Permissions
+	return u.Permissions
 }
 
 // GetPlan returns the Plan field.
diff --git a/github/orgs_members.go b/github/orgs_members.go
index 311ebc68..f3a2f17c 100644
--- a/github/orgs_members.go
+++ b/github/orgs_members.go
@@ -362,3 +362,27 @@ func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org,
 	}
 	return orgInvitationTeams, resp, nil
 }
+
+// ListFailedOrgInvitations returns a list of failed inviatations.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/orgs#list-failed-organization-invitations
+func (s *OrganizationsService) ListFailedOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/failed_invitations", org)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var failedInvitations []*Invitation
+	resp, err := s.client.Do(ctx, req, &failedInvitations)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return failedInvitations, resp, nil
+}
diff --git a/github/repos.go b/github/repos.go
index 989f2756..a7ec9d11 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -20,47 +20,47 @@ type RepositoriesService service
 
 // Repository represents a GitHub repository.
 type Repository struct {
-	ID                  *int64           `json:"id,omitempty"`
-	NodeID              *string          `json:"node_id,omitempty"`
-	Owner               *User            `json:"owner,omitempty"`
-	Name                *string          `json:"name,omitempty"`
-	FullName            *string          `json:"full_name,omitempty"`
-	Description         *string          `json:"description,omitempty"`
-	Homepage            *string          `json:"homepage,omitempty"`
-	CodeOfConduct       *CodeOfConduct   `json:"code_of_conduct,omitempty"`
-	DefaultBranch       *string          `json:"default_branch,omitempty"`
-	MasterBranch        *string          `json:"master_branch,omitempty"`
-	CreatedAt           *Timestamp       `json:"created_at,omitempty"`
-	PushedAt            *Timestamp       `json:"pushed_at,omitempty"`
-	UpdatedAt           *Timestamp       `json:"updated_at,omitempty"`
-	HTMLURL             *string          `json:"html_url,omitempty"`
-	CloneURL            *string          `json:"clone_url,omitempty"`
-	GitURL              *string          `json:"git_url,omitempty"`
-	MirrorURL           *string          `json:"mirror_url,omitempty"`
-	SSHURL              *string          `json:"ssh_url,omitempty"`
-	SVNURL              *string          `json:"svn_url,omitempty"`
-	Language            *string          `json:"language,omitempty"`
-	Fork                *bool            `json:"fork,omitempty"`
-	ForksCount          *int             `json:"forks_count,omitempty"`
-	NetworkCount        *int             `json:"network_count,omitempty"`
-	OpenIssuesCount     *int             `json:"open_issues_count,omitempty"`
-	StargazersCount     *int             `json:"stargazers_count,omitempty"`
-	SubscribersCount    *int             `json:"subscribers_count,omitempty"`
-	WatchersCount       *int             `json:"watchers_count,omitempty"`
-	Size                *int             `json:"size,omitempty"`
-	AutoInit            *bool            `json:"auto_init,omitempty"`
-	Parent              *Repository      `json:"parent,omitempty"`
-	Source              *Repository      `json:"source,omitempty"`
-	TemplateRepository  *Repository      `json:"template_repository,omitempty"`
-	Organization        *Organization    `json:"organization,omitempty"`
-	Permissions         *map[string]bool `json:"permissions,omitempty"`
-	AllowRebaseMerge    *bool            `json:"allow_rebase_merge,omitempty"`
-	AllowSquashMerge    *bool            `json:"allow_squash_merge,omitempty"`
-	AllowMergeCommit    *bool            `json:"allow_merge_commit,omitempty"`
-	DeleteBranchOnMerge *bool            `json:"delete_branch_on_merge,omitempty"`
-	Topics              []string         `json:"topics,omitempty"`
-	Archived            *bool            `json:"archived,omitempty"`
-	Disabled            *bool            `json:"disabled,omitempty"`
+	ID                  *int64          `json:"id,omitempty"`
+	NodeID              *string         `json:"node_id,omitempty"`
+	Owner               *User           `json:"owner,omitempty"`
+	Name                *string         `json:"name,omitempty"`
+	FullName            *string         `json:"full_name,omitempty"`
+	Description         *string         `json:"description,omitempty"`
+	Homepage            *string         `json:"homepage,omitempty"`
+	CodeOfConduct       *CodeOfConduct  `json:"code_of_conduct,omitempty"`
+	DefaultBranch       *string         `json:"default_branch,omitempty"`
+	MasterBranch        *string         `json:"master_branch,omitempty"`
+	CreatedAt           *Timestamp      `json:"created_at,omitempty"`
+	PushedAt            *Timestamp      `json:"pushed_at,omitempty"`
+	UpdatedAt           *Timestamp      `json:"updated_at,omitempty"`
+	HTMLURL             *string         `json:"html_url,omitempty"`
+	CloneURL            *string         `json:"clone_url,omitempty"`
+	GitURL              *string         `json:"git_url,omitempty"`
+	MirrorURL           *string         `json:"mirror_url,omitempty"`
+	SSHURL              *string         `json:"ssh_url,omitempty"`
+	SVNURL              *string         `json:"svn_url,omitempty"`
+	Language            *string         `json:"language,omitempty"`
+	Fork                *bool           `json:"fork,omitempty"`
+	ForksCount          *int            `json:"forks_count,omitempty"`
+	NetworkCount        *int            `json:"network_count,omitempty"`
+	OpenIssuesCount     *int            `json:"open_issues_count,omitempty"`
+	StargazersCount     *int            `json:"stargazers_count,omitempty"`
+	SubscribersCount    *int            `json:"subscribers_count,omitempty"`
+	WatchersCount       *int            `json:"watchers_count,omitempty"`
+	Size                *int            `json:"size,omitempty"`
+	AutoInit            *bool           `json:"auto_init,omitempty"`
+	Parent              *Repository     `json:"parent,omitempty"`
+	Source              *Repository     `json:"source,omitempty"`
+	TemplateRepository  *Repository     `json:"template_repository,omitempty"`
+	Organization        *Organization   `json:"organization,omitempty"`
+	Permissions         map[string]bool `json:"permissions,omitempty"`
+	AllowRebaseMerge    *bool           `json:"allow_rebase_merge,omitempty"`
+	AllowSquashMerge    *bool           `json:"allow_squash_merge,omitempty"`
+	AllowMergeCommit    *bool           `json:"allow_merge_commit,omitempty"`
+	DeleteBranchOnMerge *bool           `json:"delete_branch_on_merge,omitempty"`
+	Topics              []string        `json:"topics,omitempty"`
+	Archived            *bool           `json:"archived,omitempty"`
+	Disabled            *bool           `json:"disabled,omitempty"`
 
 	// Only provided when using RepositoriesService.Get while in preview
 	License *License `json:"license,omitempty"`
diff --git a/github/teams.go b/github/teams.go
index 2e1cd3da..7a8a5d8a 100644
--- a/github/teams.go
+++ b/github/teams.go
@@ -34,7 +34,7 @@ type Team struct {
 
 	// Permissions identifies the permissions that a team has on a given
 	// repository. This is only populated when calling Repositories.ListTeams.
-	Permissions *map[string]bool `json:"permissions,omitempty"`
+	Permissions map[string]bool `json:"permissions,omitempty"`
 
 	// Privacy identifies the level of privacy this team should have.
 	// Possible values are:
@@ -71,6 +71,8 @@ type Invitation struct {
 	Inviter           *User      `json:"inviter,omitempty"`
 	TeamCount         *int       `json:"team_count,omitempty"`
 	InvitationTeamURL *string    `json:"invitation_team_url,omitempty"`
+	FailedAt          *Timestamp `json:"failed_at,omitempty"`
+	FailedReason      *string    `json:"failed_reason,omitempty"`
 }
 
 func (i Invitation) String() string {
diff --git a/github/users.go b/github/users.go
index 38daece3..f45b1f67 100644
--- a/github/users.go
+++ b/github/users.go
@@ -68,7 +68,7 @@ type User struct {
 
 	// Permissions identifies the permissions that a user has on a given
 	// repository. This is only populated when calling Repositories.ListCollaborators.
-	Permissions *map[string]bool `json:"permissions,omitempty"`
+	Permissions map[string]bool `json:"permissions,omitempty"`
 }
 
 func (u User) String() string {


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 2c449f8b..7dfb0011 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -6397,6 +6397,26 @@ func TestInvitation_GetEmail(tt *testing.T) {
 	i.GetEmail()
 }
 
+func TestInvitation_GetFailedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	i := &Invitation{FailedAt: &zeroValue}
+	i.GetFailedAt()
+	i = &Invitation{}
+	i.GetFailedAt()
+	i = nil
+	i.GetFailedAt()
+}
+
+func TestInvitation_GetFailedReason(tt *testing.T) {
+	var zeroValue string
+	i := &Invitation{FailedReason: &zeroValue}
+	i.GetFailedReason()
+	i = &Invitation{}
+	i.GetFailedReason()
+	i = nil
+	i.GetFailedReason()
+}
+
 func TestInvitation_GetID(tt *testing.T) {
 	var zeroValue int64
 	i := &Invitation{ID: &zeroValue}
@@ -14534,8 +14554,8 @@ func TestRepository_GetParent(tt *testing.T) {
 }
 
 func TestRepository_GetPermissions(tt *testing.T) {
-	var zeroValue map[string]bool
-	r := &Repository{Permissions: &zeroValue}
+	zeroValue := map[string]bool{}
+	r := &Repository{Permissions: zeroValue}
 	r.GetPermissions()
 	r = &Repository{}
 	r.GetPermissions()
@@ -16762,8 +16782,8 @@ func TestTeam_GetPermission(tt *testing.T) {
 }
 
 func TestTeam_GetPermissions(tt *testing.T) {
-	var zeroValue map[string]bool
-	t := &Team{Permissions: &zeroValue}
+	zeroValue := map[string]bool{}
+	t := &Team{Permissions: zeroValue}
 	t.GetPermissions()
 	t = &Team{}
 	t.GetPermissions()
@@ -18056,8 +18076,8 @@ func TestUser_GetOwnedPrivateRepos(tt *testing.T) {
 }
 
 func TestUser_GetPermissions(tt *testing.T) {
-	var zeroValue map[string]bool
-	u := &User{Permissions: &zeroValue}
+	zeroValue := map[string]bool{}
+	u := &User{Permissions: zeroValue}
 	u.GetPermissions()
 	u = &User{}
 	u.GetPermissions()
diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go
index b1dceb0c..cf0c7ebe 100644
--- a/github/github-stringify_test.go
+++ b/github/github-stringify_test.go
@@ -624,8 +624,10 @@ func TestInvitation_String(t *testing.T) {
 		Inviter:           &User{},
 		TeamCount:         Int(0),
 		InvitationTeamURL: String(""),
+		FailedAt:          &Timestamp{},
+		FailedReason:      String(""),
 	}
-	want := `github.Invitation{ID:0, NodeID:"", Login:"", Email:"", Role:"", Inviter:github.User{}, TeamCount:0, InvitationTeamURL:""}`
+	want := `github.Invitation{ID:0, NodeID:"", Login:"", Email:"", Role:"", Inviter:github.User{}, TeamCount:0, InvitationTeamURL:"", FailedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, FailedReason:""}`
 	if got := v.String(); got != want {
 		t.Errorf("Invitation.String = %v, want %v", got, want)
 	}
diff --git a/github/orgs_members_test.go b/github/orgs_members_test.go
index ec41b3d7..7172b4c3 100644
--- a/github/orgs_members_test.go
+++ b/github/orgs_members_test.go
@@ -744,3 +744,108 @@ func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) {
 		return resp, err
 	})
 }
+
+func TestOrganizationsService_ListFailedOrgInvitations(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/failed_invitations", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"page": "2", "per_page": "1"})
+		fmt.Fprint(w, `[
+			{
+			   "id":1,
+			   "login":"monalisa",
+			   "node_id":"MDQ6VXNlcjE=",
+			   "email":"octocat@github.com",
+			   "role":"direct_member",
+			   "created_at":"2016-11-30T06:46:10Z",
+			   "failed_at":"2017-01-02T01:10:00Z",
+			   "failed_reason":"the reason",
+			   "inviter":{
+				  "login":"other_user",
+				  "id":1,
+				  "node_id":"MDQ6VXNlcjE=",
+				  "avatar_url":"https://github.com/images/error/other_user_happy.gif",
+				  "gravatar_id":"",
+				  "url":"https://api.github.com/users/other_user",
+				  "html_url":"https://github.com/other_user",
+				  "followers_url":"https://api.github.com/users/other_user/followers",
+				  "following_url":"https://api.github.com/users/other_user/following{/other_user}",
+				  "gists_url":"https://api.github.com/users/other_user/gists{/gist_id}",
+				  "starred_url":"https://api.github.com/users/other_user/starred{/owner}{/repo}",
+				  "subscriptions_url":"https://api.github.com/users/other_user/subscriptions",
+				  "organizations_url":"https://api.github.com/users/other_user/orgs",
+				  "repos_url":"https://api.github.com/users/other_user/repos",
+				  "events_url":"https://api.github.com/users/other_user/events{/privacy}",
+				  "received_events_url":"https://api.github.com/users/other_user/received_events",
+				  "type":"User",
+				  "site_admin":false
+			   },
+			   "team_count":2,
+			   "invitation_team_url":"https://api.github.com/organizations/2/invitations/1/teams"
+			}
+		]`)
+	})
+
+	opts := &ListOptions{Page: 2, PerPage: 1}
+	ctx := context.Background()
+	failedInvitations, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts)
+	if err != nil {
+		t.Errorf("Organizations.ListFailedOrgInvitations returned error: %v", err)
+	}
+
+	createdAt := time.Date(2016, time.November, 30, 6, 46, 10, 0, time.UTC)
+	want := []*Invitation{
+		{
+			ID:           Int64(1),
+			Login:        String("monalisa"),
+			NodeID:       String("MDQ6VXNlcjE="),
+			Email:        String("octocat@github.com"),
+			Role:         String("direct_member"),
+			FailedAt:     &Timestamp{time.Date(2017, time.January, 2, 1, 10, 0, 0, time.UTC)},
+			FailedReason: String("the reason"),
+			CreatedAt:    &createdAt,
+			Inviter: &User{
+				Login:             String("other_user"),
+				ID:                Int64(1),
+				NodeID:            String("MDQ6VXNlcjE="),
+				AvatarURL:         String("https://github.com/images/error/other_user_happy.gif"),
+				GravatarID:        String(""),
+				URL:               String("https://api.github.com/users/other_user"),
+				HTMLURL:           String("https://github.com/other_user"),
+				FollowersURL:      String("https://api.github.com/users/other_user/followers"),
+				FollowingURL:      String("https://api.github.com/users/other_user/following{/other_user}"),
+				GistsURL:          String("https://api.github.com/users/other_user/gists{/gist_id}"),
+				StarredURL:        String("https://api.github.com/users/other_user/starred{/owner}{/repo}"),
+				SubscriptionsURL:  String("https://api.github.com/users/other_user/subscriptions"),
+				OrganizationsURL:  String("https://api.github.com/users/other_user/orgs"),
+				ReposURL:          String("https://api.github.com/users/other_user/repos"),
+				EventsURL:         String("https://api.github.com/users/other_user/events{/privacy}"),
+				ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events"),
+				Type:              String("User"),
+				SiteAdmin:         Bool(false),
+			},
+			TeamCount:         Int(2),
+			InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"),
+		},
+	}
+
+	if !reflect.DeepEqual(failedInvitations, want) {
+		t.Errorf("Organizations.ListFailedOrgInvitations returned %+v, want %+v", failedInvitations, want)
+	}
+
+	const methodName = "ListFailedOrgInvitations"
+	testBadOptions(t, methodName, func() error {
+		_, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}