Repository: google/go-github
Pull request #3155 (2024-04-26 17:08:04)

Allow an empty array of repo ids as a request parameter
Fixes: #3106.

Add extra endpoint function that allows client to pass an empty array of repository ids to the installations/<install_id>/access_tokens endpoint as a parameter. Response lists all repositories in an installation.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/google/go-github/pull/3155?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 92.89%. Comparing base [(`2b8c7fa`)](https://app.codecov.io/gh/google/go-github/commit/2b8c7fa86fcd1cb4a89a44c8e7b5a49fe4be8a45?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) to head [(`2c8a998`)](https://app.codecov.io/gh/google/go-github/pull/3155?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).
> Report is 44 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #3155      +/-   ##
==========================================
- Coverage   97.72%   92.89%   -4.84%     
==========================================
  Files         153      170      +17     
  Lines       13390    11436    -1954     
==========================================
- Hits        13085    10623    -2462     
- Misses        215      723     +508     
  Partials       90       90              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/google/go-github/pull/3155?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).

gmlewis: Thank you, @be0x74a !
Merging.

Patch:
diff --git a/github/apps.go b/github/apps.go
index 2ebfee50..6969daba 100644
--- a/github/apps.go
+++ b/github/apps.go
@@ -56,6 +56,20 @@ type InstallationTokenOptions struct {
 	Permissions *InstallationPermissions `json:"permissions,omitempty"`
 }
 
+type InstallationTokenListRepoOptions struct {
+	// The IDs of the repositories that the installation token can access.
+	// Providing repository IDs restricts the access of an installation token to specific repositories.
+	RepositoryIDs []int64 `json:"repository_ids"`
+
+	// The names of the repositories that the installation token can access.
+	// Providing repository names restricts the access of an installation token to specific repositories.
+	Repositories []string `json:"repositories,omitempty"`
+
+	// The permissions granted to the access token.
+	// The permissions object includes the permission names and their access type.
+	Permissions *InstallationPermissions `json:"permissions,omitempty"`
+}
+
 // InstallationPermissions lists the repository and organization permissions for an installation.
 //
 // Permission names taken from:
@@ -344,6 +358,30 @@ func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opt
 	return t, resp, nil
 }
 
+// CreateInstallationTokenListRepos creates a new installation token with a list of all repositories in an installation which is not possible with CreateInstallationToken.
+//
+// It differs from CreateInstallationToken by taking InstallationTokenListRepoOptions as a parameter which does not omit RepositoryIDs if that field is nil or an empty array.
+//
+// GitHub API docs: https://docs.github.com/rest/apps/apps#create-an-installation-access-token-for-an-app
+//
+//meta:operation POST /app/installations/{installation_id}/access_tokens
+func (s *AppsService) CreateInstallationTokenListRepos(ctx context.Context, id int64, opts *InstallationTokenListRepoOptions) (*InstallationToken, *Response, error) {
+	u := fmt.Sprintf("app/installations/%v/access_tokens", id)
+
+	req, err := s.client.NewRequest("POST", u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	t := new(InstallationToken)
+	resp, err := s.client.Do(ctx, req, t)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return t, resp, nil
+}
+
 // CreateAttachment creates a new attachment on user comment containing a url.
 //
 // GitHub API docs: https://docs.github.com/enterprise-server@3.3/rest/reference/apps#create-a-content-attachment
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 13bf7d66..390ae086 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -9062,6 +9062,14 @@ func (i *InstallationToken) GetToken() string {
 	return *i.Token
 }
 
+// GetPermissions returns the Permissions field.
+func (i *InstallationTokenListRepoOptions) GetPermissions() *InstallationPermissions {
+	if i == nil {
+		return nil
+	}
+	return i.Permissions
+}
+
 // GetPermissions returns the Permissions field.
 func (i *InstallationTokenOptions) GetPermissions() *InstallationPermissions {
 	if i == nil {


Test patch:
diff --git a/github/apps_test.go b/github/apps_test.go
index a58326ea..ea670344 100644
--- a/github/apps_test.go
+++ b/github/apps_test.go
@@ -469,6 +469,77 @@ func TestAppsService_CreateInstallationTokenWithOptions(t *testing.T) {
 	}
 }
 
+func TestAppsService_CreateInstallationTokenListReposWithOptions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	installationTokenListRepoOptions := &InstallationTokenListRepoOptions{
+		Repositories: []string{"foo"},
+		Permissions: &InstallationPermissions{
+			Contents: String("write"),
+			Issues:   String("read"),
+		},
+	}
+
+	mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
+		v := new(InstallationTokenListRepoOptions)
+		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+
+		if !cmp.Equal(v, installationTokenListRepoOptions) {
+			t.Errorf("request sent %+v, want %+v", v, installationTokenListRepoOptions)
+		}
+
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{"token":"t"}`)
+	})
+
+	ctx := context.Background()
+	token, _, err := client.Apps.CreateInstallationTokenListRepos(ctx, 1, installationTokenListRepoOptions)
+	if err != nil {
+		t.Errorf("Apps.CreateInstallationTokenListRepos returned error: %v", err)
+	}
+
+	want := &InstallationToken{Token: String("t")}
+	if !cmp.Equal(token, want) {
+		t.Errorf("Apps.CreateInstallationTokenListRepos returned %+v, want %+v", token, want)
+	}
+}
+
+func TestAppsService_CreateInstallationTokenListReposWithNoOptions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{"token":"t"}`)
+	})
+
+	ctx := context.Background()
+	token, _, err := client.Apps.CreateInstallationTokenListRepos(ctx, 1, nil)
+	if err != nil {
+		t.Errorf("Apps.CreateInstallationTokenListRepos returned error: %v", err)
+	}
+
+	want := &InstallationToken{Token: String("t")}
+	if !cmp.Equal(token, want) {
+		t.Errorf("Apps.CreateInstallationTokenListRepos returned %+v, want %+v", token, want)
+	}
+
+	const methodName = "CreateInstallationTokenListRepos"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Apps.CreateInstallationTokenListRepos(ctx, -1, nil)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Apps.CreateInstallationTokenListRepos(ctx, 1, nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
 func TestAppsService_CreateAttachement(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 313e92c0..8fafe9a2 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -10608,6 +10608,13 @@ func TestInstallationToken_GetToken(tt *testing.T) {
 	i.GetToken()
 }
 
+func TestInstallationTokenListRepoOptions_GetPermissions(tt *testing.T) {
+	i := &InstallationTokenListRepoOptions{}
+	i.GetPermissions()
+	i = nil
+	i.GetPermissions()
+}
+
 func TestInstallationTokenOptions_GetPermissions(tt *testing.T) {
 	i := &InstallationTokenOptions{}
 	i.GetPermissions()