Skip to content

Commit 932e047

Browse files
committed
feat: Add data source for listing GitHub App installations in an organization
1 parent 935246a commit 932e047

4 files changed

Lines changed: 316 additions & 0 deletions
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
package github
2+
3+
import (
4+
"context"
5+
6+
"github.com/google/go-github/v82/github"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
)
10+
11+
func dataSourceGithubOrganizationAppInstallations() *schema.Resource {
12+
return &schema.Resource{
13+
ReadContext: dataSourceGithubOrganizationAppInstallationsRead,
14+
Description: "Use this data source to retrieve all GitHub App installations of the organization.",
15+
16+
Schema: map[string]*schema.Schema{
17+
"installations": {
18+
Type: schema.TypeList,
19+
Computed: true,
20+
Description: "List of GitHub App installations in the organization.",
21+
Elem: &schema.Resource{
22+
Schema: map[string]*schema.Schema{
23+
"id": {
24+
Type: schema.TypeInt,
25+
Computed: true,
26+
Description: "The ID of the GitHub App installation.",
27+
},
28+
"slug": {
29+
Type: schema.TypeString,
30+
Computed: true,
31+
Description: "The URL-friendly name of the GitHub App.",
32+
},
33+
"app_id": {
34+
Type: schema.TypeInt,
35+
Computed: true,
36+
Description: "The ID of the GitHub App.",
37+
},
38+
"repository_selection": {
39+
Type: schema.TypeString,
40+
Computed: true,
41+
Description: "Whether the installation has access to all repositories or only selected ones. Possible values are 'all' or 'selected'.",
42+
},
43+
"permissions": {
44+
Type: schema.TypeMap,
45+
Computed: true,
46+
Elem: &schema.Schema{Type: schema.TypeString},
47+
Description: "The permissions granted to the GitHub App installation.",
48+
},
49+
"events": {
50+
Type: schema.TypeList,
51+
Computed: true,
52+
Elem: &schema.Schema{Type: schema.TypeString},
53+
Description: "The list of events the GitHub App installation subscribes to.",
54+
},
55+
"html_url": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
Description: "The URL to the GitHub App installation's settings page.",
59+
},
60+
"client_id": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
Description: "The OAuth client ID of the GitHub App.",
64+
},
65+
"target_id": {
66+
Type: schema.TypeInt,
67+
Computed: true,
68+
Description: "The ID of the account the GitHub App is installed on.",
69+
},
70+
"target_type": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
Description: "The type of account the GitHub App is installed on. Possible values are 'Organization' or 'User'.",
74+
},
75+
"suspended": {
76+
Type: schema.TypeBool,
77+
Computed: true,
78+
Description: "Whether the GitHub App installation is currently suspended.",
79+
},
80+
},
81+
},
82+
},
83+
},
84+
}
85+
}
86+
87+
func dataSourceGithubOrganizationAppInstallationsRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
88+
owner := meta.(*Owner).name
89+
90+
client := meta.(*Owner).v3client
91+
92+
options := &github.ListOptions{
93+
PerPage: maxPerPage,
94+
}
95+
96+
results := make([]map[string]any, 0)
97+
for {
98+
appInstallations, resp, err := client.Organizations.ListInstallations(ctx, owner, options)
99+
if err != nil {
100+
return diag.FromErr(err)
101+
}
102+
103+
results = append(results, flattenGitHubAppInstallations(appInstallations.Installations)...)
104+
if resp.NextPage == 0 {
105+
break
106+
}
107+
108+
options.Page = resp.NextPage
109+
}
110+
111+
d.SetId(owner)
112+
err := d.Set("installations", results)
113+
if err != nil {
114+
return diag.FromErr(err)
115+
}
116+
117+
return nil
118+
}
119+
120+
func flattenGitHubAppInstallations(orgAppInstallations []*github.Installation) []map[string]any {
121+
results := make([]map[string]any, 0)
122+
123+
if orgAppInstallations == nil {
124+
return results
125+
}
126+
127+
for _, appInstallation := range orgAppInstallations {
128+
result := make(map[string]any)
129+
130+
result["id"] = appInstallation.GetID()
131+
result["slug"] = appInstallation.GetAppSlug()
132+
result["app_id"] = appInstallation.GetAppID()
133+
result["repository_selection"] = appInstallation.GetRepositorySelection()
134+
result["html_url"] = appInstallation.GetHTMLURL()
135+
result["client_id"] = appInstallation.GetClientID()
136+
result["target_id"] = appInstallation.GetTargetID()
137+
result["target_type"] = appInstallation.GetTargetType()
138+
result["suspended"] = !appInstallation.GetSuspendedAt().IsZero()
139+
if appInstallation.Events != nil {
140+
result["events"] = appInstallation.Events
141+
} else {
142+
result["events"] = []string{}
143+
}
144+
145+
result["permissions"] = flattenInstallationPermissions(appInstallation.Permissions)
146+
147+
results = append(results, result)
148+
}
149+
150+
return results
151+
}
152+
153+
func flattenInstallationPermissions(perms *github.InstallationPermissions) map[string]string {
154+
permissions := make(map[string]string)
155+
if perms == nil {
156+
return permissions
157+
}
158+
159+
if v := perms.GetActions(); v != "" {
160+
permissions["actions"] = v
161+
}
162+
if v := perms.GetAdministration(); v != "" {
163+
permissions["administration"] = v
164+
}
165+
if v := perms.GetChecks(); v != "" {
166+
permissions["checks"] = v
167+
}
168+
if v := perms.GetContents(); v != "" {
169+
permissions["contents"] = v
170+
}
171+
if v := perms.GetDeployments(); v != "" {
172+
permissions["deployments"] = v
173+
}
174+
if v := perms.GetEnvironments(); v != "" {
175+
permissions["environments"] = v
176+
}
177+
if v := perms.GetIssues(); v != "" {
178+
permissions["issues"] = v
179+
}
180+
if v := perms.GetMetadata(); v != "" {
181+
permissions["metadata"] = v
182+
}
183+
if v := perms.GetMembers(); v != "" {
184+
permissions["members"] = v
185+
}
186+
if v := perms.GetOrganizationAdministration(); v != "" {
187+
permissions["organization_administration"] = v
188+
}
189+
if v := perms.GetOrganizationHooks(); v != "" {
190+
permissions["organization_hooks"] = v
191+
}
192+
if v := perms.GetOrganizationPlan(); v != "" {
193+
permissions["organization_plan"] = v
194+
}
195+
if v := perms.GetOrganizationProjects(); v != "" {
196+
permissions["organization_projects"] = v
197+
}
198+
if v := perms.GetOrganizationSecrets(); v != "" {
199+
permissions["organization_secrets"] = v
200+
}
201+
if v := perms.GetOrganizationSelfHostedRunners(); v != "" {
202+
permissions["organization_self_hosted_runners"] = v
203+
}
204+
if v := perms.GetOrganizationUserBlocking(); v != "" {
205+
permissions["organization_user_blocking"] = v
206+
}
207+
if v := perms.GetPackages(); v != "" {
208+
permissions["packages"] = v
209+
}
210+
if v := perms.GetPages(); v != "" {
211+
permissions["pages"] = v
212+
}
213+
if v := perms.GetPullRequests(); v != "" {
214+
permissions["pull_requests"] = v
215+
}
216+
if v := perms.GetRepositoryHooks(); v != "" {
217+
permissions["repository_hooks"] = v
218+
}
219+
if v := perms.GetRepositoryProjects(); v != "" {
220+
permissions["repository_projects"] = v
221+
}
222+
if v := perms.GetRepositoryPreReceiveHooks(); v != "" {
223+
permissions["repository_pre_receive_hooks"] = v
224+
}
225+
if v := perms.GetSecrets(); v != "" {
226+
permissions["secrets"] = v
227+
}
228+
if v := perms.GetSecretScanningAlerts(); v != "" {
229+
permissions["secret_scanning_alerts"] = v
230+
}
231+
if v := perms.GetSecurityEvents(); v != "" {
232+
permissions["security_events"] = v
233+
}
234+
if v := perms.GetSingleFile(); v != "" {
235+
permissions["single_file"] = v
236+
}
237+
if v := perms.GetStatuses(); v != "" {
238+
permissions["statuses"] = v
239+
}
240+
if v := perms.GetTeamDiscussions(); v != "" {
241+
permissions["team_discussions"] = v
242+
}
243+
if v := perms.GetVulnerabilityAlerts(); v != "" {
244+
permissions["vulnerability_alerts"] = v
245+
}
246+
if v := perms.GetWorkflows(); v != "" {
247+
permissions["workflows"] = v
248+
}
249+
250+
return permissions
251+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package github
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
)
8+
9+
func TestAccGithubOrganizationAppInstallations(t *testing.T) {
10+
config := `data "github_organization_app_installations" "test" {}`
11+
12+
resource.Test(t, resource.TestCase{
13+
PreCheck: func() { skipUnlessHasOrgs(t) },
14+
ProviderFactories: providerFactories,
15+
Steps: []resource.TestStep{
16+
{
17+
Config: config,
18+
Check: resource.ComposeAggregateTestCheckFunc(
19+
resource.TestCheckResourceAttrSet("data.github_organization_app_installations.test", "installations.0.id"),
20+
resource.TestCheckResourceAttrSet("data.github_organization_app_installations.test", "installations.0.slug"),
21+
resource.TestCheckResourceAttrSet("data.github_organization_app_installations.test", "installations.0.app_id"),
22+
),
23+
},
24+
},
25+
})
26+
}

github/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ func Provider() *schema.Provider {
265265
"github_organization_team_sync_groups": dataSourceGithubOrganizationTeamSyncGroups(),
266266
"github_organization_teams": dataSourceGithubOrganizationTeams(),
267267
"github_organization_webhooks": dataSourceGithubOrganizationWebhooks(),
268+
"github_organization_app_installations": dataSourceGithubOrganizationAppInstallations(),
268269
"github_ref": dataSourceGithubRef(),
269270
"github_release": dataSourceGithubRelease(),
270271
"github_release_asset": dataSourceGithubReleaseAsset(),
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
layout: "github"
3+
page_title: "GitHub: github_organization_app_installations"
4+
description: |-
5+
Get information on all GitHub App installations of the organization.
6+
---
7+
8+
# github\_organization\_app_installations
9+
10+
Use this data source to retrieve all GitHub App installations of the organization.
11+
12+
## Example Usage
13+
14+
To retrieve *all* GitHub App installations of the organization:
15+
16+
```hcl
17+
data "github_organization_app_installations" "all" {}
18+
```
19+
20+
## Attributes Reference
21+
22+
* `installations` - List of GitHub App installations in the organization. Each `installation` block consists of the fields documented below.
23+
24+
---
25+
26+
The `installation` block consists of:
27+
28+
* `id` - The ID of the GitHub App installation.
29+
* `slug` - The URL-friendly name of the GitHub App.
30+
* `app_id` - The ID of the GitHub App.
31+
* `repository_selection` - Whether the installation has access to all repositories or only selected ones. Possible values are `all` or `selected`.
32+
* `permissions` - A map of the permissions granted to the GitHub App installation.
33+
* `events` - The list of events the GitHub App installation subscribes to.
34+
* `html_url` - The URL to the GitHub App installation's settings page.
35+
* `client_id` - The OAuth client ID of the GitHub App.
36+
* `target_id` - The ID of the account the GitHub App is installed on.
37+
* `target_type` - The type of account the GitHub App is installed on. Possible values are `Organization` or `User`.
38+
* `suspended` - Whether the GitHub App installation is currently suspended.

0 commit comments

Comments
 (0)