Add ListPendingOrgInvitations method and Invitation.Inviter field.#527
Add ListPendingOrgInvitations method and Invitation.Inviter field.#527varadarajana wants to merge 13 commits intogoogle:masterfrom
Conversation
|
The golang documentation of time, requires structs to access as time.Time and not *time.Time. So changed it as it. YYYY-MM-DDTHH:MM:SSZ |
|
I have now added support for Orgs List Members Invitation also. Now this contains both List Members as well as Team Invitations. |
dmitshur
left a comment
There was a problem hiding this comment.
Looks good. I've reviewed and left first pass comments.
github/orgs_members.go
Outdated
| //ListPendingOrgInvitations returns a list of contains a role field which refers to the | ||
| //Organization Invitation role and will be one of the following values: | ||
| //direct_member, admin, billing_manager, hiring_manager, or reinstate. | ||
| //If the invitee is not a GitHub member, the login field in the return hash will be null. |
There was a problem hiding this comment.
Don't forget to include a space between the text and //.
There was a problem hiding this comment.
This documentation is hard to read and strangely detailed (it refers to specifics of the returned values inside Invitation struct).
We should either omit it altogether, just say // ListPendingOrgInvitations returns a list of pending organization invitations., or update it to be specific to go-github. The returned thing is []Invitation, a slice of invitations, not a hash. There's no null, it's nil. Etc.
It would make sense to me to move the documentation of role to the Invitation struct itself, not here. Unless it's specific to this method, is it?
github/orgs_members.go
Outdated
| //If the invitee is not a GitHub member, the login field in the return hash will be null. | ||
| // | ||
| // GitHub API docs: | ||
| // https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations |
There was a problem hiding this comment.
There's no benefit in putting the long URL on a new line. We're not hard-limited to the width of a punch card, it's fine to keep it on the same line.
github/orgs_teams.go
Outdated
| Role *string `json:"role,omitempty"` | ||
| //golang documentation states | ||
| //Programs using times should typically store and pass them as values, not pointers. | ||
| //That is, time variables and struct fields should be of type time.Time, not *time.Time |
There was a problem hiding this comment.
This comment shouldn't be here as part of the final PR.
I will respond to it.
While it's true that it's fine to use time.Time as a value, the reason we're using it as a point here is because of JSON encoding. We want to be able to tell (sometimes) that a field is absent by checking if its value is nil.
So, we want to keep CreatedAt as a pointer to *time.Time. If you want to discuss this further, I suggest opening a new issue, because it's outside of the scope of this PR.
Edit: I missed your #527 (comment), let me look into that. I'll update this comment afterwards.
There was a problem hiding this comment.
Okay, question, have you considered using *Timestamp here instead of *time.Time?
Can you be more specific about the problem you're seeing with *time.Time as is?
There was a problem hiding this comment.
@shurcooL in fact this time i tried pointer to time.Time, and it worked. i assigned it to a variable and then passed its address.
github/orgs_teams.go
Outdated
| return Stringify(i) | ||
| } | ||
|
|
||
| // Inviter represents the entity introduced in team and org invitations |
There was a problem hiding this comment.
A period is missing at the end of this sentence.
Also, you can write the full word "organization", there's no need for a short form here.
github/orgs_members_test.go
Outdated
| t.Errorf("Organizations.ListPendingOrgInvitations returned error: %v", err) | ||
| } | ||
|
|
||
| tm := time.Date(2017, 01, 21, 0, 0, 0, 0, time.UTC) |
There was a problem hiding this comment.
Nitpick, what does tm mean? It doesn't seem to be short for anything, and I don't think it's an acronym. Is it meant to stand for "time" except without letters i and e?
I'd suggest naming it something more clear. Just createdAt could work well.
There was a problem hiding this comment.
@shurcooL yes, tm was not proper, i have set it as createdAt
github/orgs_teams.go
Outdated
|
|
||
| // Invitation represents a team member's inviation status | ||
| // Invitation represents a team member's invitation status. | ||
| // Role can be one of the values - direct_member, admin, billing_manager, hiring_manager, or reinstate. |
There was a problem hiding this comment.
// Role can be one of the values ...
Move that comment near Role field:
// Role can be one of ...
Role *string `json:"role,omitempty"`See
go-github/github/migrations_source_import.go
Lines 14 to 15 in c9c37fd
github/orgs_teams.go
Outdated
| Events_url *string `json:"events_url,omitempty"` | ||
| Received_events_url *string `json:"received_events_url,omitempty"` | ||
| Type *string `json:"type,omitempty"` | ||
| Site_admin bool `json:"site_admin,omitempty"` |
There was a problem hiding this comment.
Site_admin should also be a pointer, i.e., *bool.
There was a problem hiding this comment.
Most of these variables need to be renamed to follow Go style.
See:
- https://github.com/golang/go/wiki/CodeReviewComments#mixed-caps
- https://github.com/golang/go/wiki/CodeReviewComments#initialisms
So, it should be SiteAdmin, not Site_admin. URL, not Url. HTMLURL, not Html_url, etc.
dmitshur
left a comment
There was a problem hiding this comment.
Thanks for addressing previous feedback, that part looks great.
I've spotted another simplification we can make. The new Inviter struct can be replaced by an existing one. See inline comments.
github/orgs_teams.go
Outdated
| ReceivedEventsURL *string `json:"received_events_url,omitempty"` | ||
| Type *string `json:"type,omitempty"` | ||
| SiteAdmin *bool `json:"site_admin,omitempty"` | ||
| } |
There was a problem hiding this comment.
I think this new struct is just a subset of User. I think we can and should use User instead of creating a new struct. So you can delete this struct.
There was a problem hiding this comment.
@shurcooL yes, thank you, i missed it. I have corrected it and checked in.
github/orgs_teams.go
Outdated
| // Role can be one of the values - direct_member, admin, billing_manager, hiring_manager, or reinstate. | ||
| Role *string `json:"role,omitempty"` | ||
| CreatedAt *time.Time `json:"created_at,omitempty"` | ||
| Inviter *Inviter `json:"inviter,omitempty"` |
There was a problem hiding this comment.
Use User instead of Inviter here:
Inviter *User `json:"inviter,omitempty"`See here for precedent:
https://github.com/google/go-github/blob/c9c37fd6/github/repos_invitations.go#L15
There was a problem hiding this comment.
@shurcooL yes, thank you, i missed it. I have corrected it and checked in.
dmitshur
left a comment
There was a problem hiding this comment.
LGTM. Thanks @varadarajana.
@gmlewis, mind looking it over before we merge?
| // ListPendingOrgInvitations returns a list of pending invitations. | ||
| // | ||
| // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations | ||
| func (s *OrganizationsService) ListPendingOrgInvitations(org int, opt *ListOptions) ([]*Invitation, *Response, error) { |
There was a problem hiding this comment.
One more thought. Should we spell out the entire word "Organization"? I don't think we shorten "Organization" to "Org" anywhere else. E.g.:
https://godoc.org/github.com/google/go-github/github#ActivityService.ListEventsForOrganization
There was a problem hiding this comment.
Correct me if I'm wrong, but an invite only relates to Organizations anyway, right?
Also, this is the OrganizationsService, so I'm thinking that a more idiomatic-Go-way to handle this (specifically to reduce stutter) would be to drop the Org entirely... so when a client uses the call, it would look like:
... := c.Organizations.ListPendingInvitations(...)Thoughts?
There was a problem hiding this comment.
Good catch, that's even better!
There was a problem hiding this comment.
I don't think we shorten "Organization" to "Org" anywhere else.
Well, I just found a counterexample of that:
https://github.com/google/go-github/blob/4baf08e3bbebb0f/github/orgs_members.go#L178-L181
There was a problem hiding this comment.
Yeah... I don't like that as much.
Your call, @shurcooL as a tie-breaker. 😃
There was a problem hiding this comment.
Hmm. Looking at the methods of OrganizationsService more closely, it seems there's many, many uses of Org. So I'm afraid it might make sense to stay consistent with that and keep this as is.
It seems valuable to keep Org because it makes it more clear that the pending invitation applies to org, rather than team (which also exists).
Notice there's RemoveOrgMembership and RemoveTeamMembership.
After this PR, there will be ListPendingOrgInvitations and ListPendingTeamInvitations, which is very consistent.
gmlewis
left a comment
There was a problem hiding this comment.
This is looking great, @varadarajana... thank you!
Just a few minor comments if you don't mind.
| // ListPendingOrgInvitations returns a list of pending invitations. | ||
| // | ||
| // GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations | ||
| func (s *OrganizationsService) ListPendingOrgInvitations(org int, opt *ListOptions) ([]*Invitation, *Response, error) { |
There was a problem hiding this comment.
Correct me if I'm wrong, but an invite only relates to Organizations anyway, right?
Also, this is the OrganizationsService, so I'm thinking that a more idiomatic-Go-way to handle this (specifically to reduce stutter) would be to drop the Org entirely... so when a client uses the call, it would look like:
... := c.Organizations.ListPendingInvitations(...)Thoughts?
| // TODO: remove custom Accept header when this API fully launches. | ||
| req.Header.Set("Accept", mediaTypeOrgMembershipPreview) | ||
|
|
||
| pendingInvitations := new([]*Invitation) |
There was a problem hiding this comment.
Just for the record, I don't like calling new to make a pointer to a slice (since it is already a reference type)... but I see this happens all over in this repo, so let's leave it... and maybe some day I can throw together a PR to replace it and see what the other authors think about the change.
There was a problem hiding this comment.
Agree that this would be best to tackle in a separate PR since it happens everywhere.
I feel similarly about the whole pattern of returning err instead of nil in situations where err is known to be nil; I will make a PR for that sometime.
There was a problem hiding this comment.
OK, I can address this change in a separate PR.
For the record, it will become:
var pendingInvitations []*Invitation
resp, err := s.client.Do(req, &pendingInvitations)
if err != nil {
return nil, resp, err
}
return pendingInvitations, resp, nil
github/orgs_teams.go
Outdated
| ID *int `json:"id,omitempty"` | ||
| Login *string `json:"login,omitempty"` | ||
| Email *string `json:"email,omitempty"` | ||
| // Role can be one of the values - direct_member, admin, billing_manager, hiring_manager, or reinstate. |
There was a problem hiding this comment.
nit - would you mind putting the acceptable values in quotes to follow the style of the other documentation in the repo?
| testFormValues(t, r, values{"page": "1"}) | ||
| testHeader(t, r, "Accept", mediaTypeOrgMembershipPreview) | ||
| fmt.Fprint(w, `[{"id":1}]`) | ||
| fmt.Fprint(w, `[ |
There was a problem hiding this comment.
Can we please reduce this test to just fields of interest?
There was a problem hiding this comment.
@gmlewis, @shurcooL I agree I made the test case big with the full test data. I have used all values that are returned by this API call, i felt test coverage will be better that way. I was not sure which field to omit, as JSON will return all of them.
Is there a guideline to choose some of these fields from from the response?
There was a problem hiding this comment.
I personally don't mind having all the fields here, since they come directly from GitHub API examples.
If we reduce it to just IDs, keep the new inviter field with an ID too.
| testMethod(t, r, "GET") | ||
| testFormValues(t, r, values{"page": "1"}) | ||
| testHeader(t, r, "Accept", mediaTypeOrgMembershipPreview) | ||
| fmt.Fprint(w, `[ |
There was a problem hiding this comment.
Can we please reduce this test to just fields of interest?
|
LGTM. |
|
Integrated in 0e7db46 |
Fixes google#514. Closes google#527. Change-Id: Id42e4304aae2388af67dca345bf12aa042b773f1

This change is made to incorporate changes to GitHub for Issue #514
Here I have tried to change the test case to include the entire response.
I have not been able to compare time.Time field in Invitation struct. I need to work on the Date time conversions.
Resolves #514.