Repository: google/go-github
Pull request #857 (2018-02-28 06:01:12)

Corrects create org invitation return value.

googlebot: 
Thanks for your pull request. t looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

:memo: **Please visit <https://cla.developers.google.com/> to sign.**

Once you've signed (or fixed any issues), please reply here (e.g. `I signed it!`) and we'll verify it.

----

#### What to do if you already signed the CLA

##### Individual signers

*   It's possible we don't have your GitHub username or you're using a different email address on your commit. Check [your existing CLA data](https://cla.developers.google.com/clas) and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).

##### Corporate signers

*   Your company has a Point of Contact who decides which employees are authorized to participate. Ask your POC to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to `go/cla#troubleshoot`.
*   The email used to register you as an authorized contributor must be the email used for the Git commit. Check [your existing CLA data](https://cla.developers.google.com/clas) and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).
*   The email used to register you as an authorized contributor must also be [attached to your GitHub account](https://github.com/settings/emails).
		

<!-- need_sender_cla -->
1995parham: I signed it!
googlebot: CLAs look good, thanks!

<!-- ok -->
gmlewis: According to the example in the GitHub API docs:
https://developer.github.com/v3/orgs/members/#create-organization-invitation
this endpoint returns a list (their example shows a list of one item).

Why is this change needed, @1995parham ?

Using the API as it is today, a user would access `invitation[0]`.
1995parham: I use the following code based on [this](https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership) API and got an error for using an array of invitation.

```go
email := "email@email.com"
client.Organizations.CreateOrgInvitation(ctx, "ce104", &CreateOrgInvitationOptions{
    Email: &email,
}) 
```
gmlewis: Thank you for the clarification, @1995parham.

In that case, I think you need to use a different endpoint.

In the [link you provided](https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership), note that the REST endpoint is: `PUT /orgs/:org/memberships/:username`.

In the function you modified in this PR, the endpoint is:

```go
	u := fmt.Sprintf("orgs/%v/invitations", org)
 	req, err := s.client.NewRequest("POST", u, opt)
```

which translates to: `POST /orgs/:org/invitations`.

So to use the first endpoint, you will want to call:
[`client.Organizations.EditOrgMembership`](https://github.com/google/go-github/blob/master/github/orgs_members.go#L240-L244)
and make sure you provide a non-empty `user` argument to the call.

Please let me know if that information resolves the issue for you or if I have misunderstood.


Patch:
diff --git a/github/apps_installation.go b/github/apps_installation.go
index af85cb87..5a424ff1 100644
--- a/github/apps_installation.go
+++ b/github/apps_installation.go
@@ -13,6 +13,7 @@ import (
 // Installation represents a GitHub Apps installation.
 type Installation struct {
 	ID              *int64  `json:"id,omitempty"`
+	AppID           *int64  `json:"app_id,omitempty"`
 	Account         *User   `json:"account,omitempty"`
 	AccessTokensURL *string `json:"access_tokens_url,omitempty"`
 	RepositoriesURL *string `json:"repositories_url,omitempty"`
diff --git a/github/github-accessors.go b/github/github-accessors.go
index db510063..32306121 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -2708,6 +2708,14 @@ func (i *Installation) GetAccount() *User {
 	return i.Account
 }
 
+// GetAppID returns the AppID field if it's non-nil, zero value otherwise.
+func (i *Installation) GetAppID() int64 {
+	if i == nil || i.AppID == nil {
+		return 0
+	}
+	return *i.AppID
+}
+
 // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
 func (i *Installation) GetHTMLURL() string {
 	if i == nil || i.HTMLURL == nil {
diff --git a/github/orgs_members.go b/github/orgs_members.go
index fb1957e6..98e138e7 100644
--- a/github/orgs_members.go
+++ b/github/orgs_members.go
@@ -323,7 +323,7 @@ type CreateOrgInvitationOptions struct {
 // the authenticated user must be an organization owner.
 //
 // https://developer.github.com/v3/orgs/members/#create-organization-invitation
-func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) ([]*Invitation, *Response, error) {
+func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opt *CreateOrgInvitationOptions) (*Invitation, *Response, error) {
 	u := fmt.Sprintf("orgs/%v/invitations", org)
 
 	req, err := s.client.NewRequest("POST", u, opt)
@@ -334,12 +334,12 @@ func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org stri
 	// TODO: remove custom Accept header when this API fully launches.
 	req.Header.Set("Accept", mediaTypeOrganizationInvitationPreview)
 
-	var invitations []*Invitation
-	resp, err := s.client.Do(ctx, req, &invitations)
+	var invitation *Invitation
+	resp, err := s.client.Do(ctx, req, &invitation)
 	if err != nil {
 		return nil, resp, err
 	}
-	return invitations, resp, nil
+	return invitation, resp, nil
 }
 
 // ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization,


Test patch:
diff --git a/github/apps_test.go b/github/apps_test.go
index f306e1a9..d1ebde48 100644
--- a/github/apps_test.go
+++ b/github/apps_test.go
@@ -66,7 +66,7 @@ func TestAppsService_ListInstallations(t *testing.T) {
 			"page":     "1",
 			"per_page": "2",
 		})
-		fmt.Fprint(w, `[{"id":1}]`)
+		fmt.Fprint(w, `[{"id":1, "app_id":1}]`)
 	})
 
 	opt := &ListOptions{Page: 1, PerPage: 2}
@@ -75,7 +75,7 @@ func TestAppsService_ListInstallations(t *testing.T) {
 		t.Errorf("Apps.ListInstallations returned error: %v", err)
 	}
 
-	want := []*Installation{{ID: Int64(1)}}
+	want := []*Installation{{ID: Int64(1), AppID: Int64(1)}}
 	if !reflect.DeepEqual(installations, want) {
 		t.Errorf("Apps.ListInstallations returned %+v, want %+v", installations, want)
 	}
@@ -88,7 +88,7 @@ func TestAppsService_GetInstallation(t *testing.T) {
 	mux.HandleFunc("/app/installations/1", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, "GET")
 		testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
-		fmt.Fprint(w, `{"id":1}`)
+		fmt.Fprint(w, `{"id":1, "app_id":1}`)
 	})
 
 	installation, _, err := client.Apps.GetInstallation(context.Background(), 1)
@@ -96,7 +96,7 @@ func TestAppsService_GetInstallation(t *testing.T) {
 		t.Errorf("Apps.GetInstallation returned error: %v", err)
 	}
 
-	want := &Installation{ID: Int64(1)}
+	want := &Installation{ID: Int64(1), AppID: Int64(1)}
 	if !reflect.DeepEqual(installation, want) {
 		t.Errorf("Apps.GetInstallation returned %+v, want %+v", installation, want)
 	}
@@ -113,7 +113,7 @@ func TestAppsService_ListUserInstallations(t *testing.T) {
 			"page":     "1",
 			"per_page": "2",
 		})
-		fmt.Fprint(w, `{"installations":[{"id":1}]}`)
+		fmt.Fprint(w, `{"installations":[{"id":1, "app_id":1}]}`)
 	})
 
 	opt := &ListOptions{Page: 1, PerPage: 2}
@@ -122,7 +122,7 @@ func TestAppsService_ListUserInstallations(t *testing.T) {
 		t.Errorf("Apps.ListUserInstallations returned error: %v", err)
 	}
 
-	want := []*Installation{{ID: Int64(1)}}
+	want := []*Installation{{ID: Int64(1), AppID: Int64(1)}}
 	if !reflect.DeepEqual(installations, want) {
 		t.Errorf("Apps.ListUserInstallations returned %+v, want %+v", installations, want)
 	}
diff --git a/github/orgs_members_test.go b/github/orgs_members_test.go
index 83a63535..b69b39fe 100644
--- a/github/orgs_members_test.go
+++ b/github/orgs_members_test.go
@@ -471,7 +471,7 @@ func TestOrganizationsService_CreateOrgInvitation(t *testing.T) {
 			t.Errorf("Request body = %+v, want %+v", v, input)
 		}
 
-		fmt.Fprintln(w, `[{"email": "octocat@github.com"}]`)
+		fmt.Fprintln(w, `{"email": "octocat@github.com"}`)
 
 	})
 
@@ -480,7 +480,7 @@ func TestOrganizationsService_CreateOrgInvitation(t *testing.T) {
 		t.Errorf("Organizations.CreateOrgInvitation returned error: %v", err)
 	}
 
-	want := []*Invitation{{Email: String("octocat@github.com")}}
+	want := &Invitation{Email: String("octocat@github.com")}
 	if !reflect.DeepEqual(invitations, want) {
 		t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want)
 	}