Skip to content

Commit 41c3ace

Browse files
authored
feat: Consistent secret and variable selected repos (integrations#3155)
Signed-off-by: Steve Hipwell <steve.hipwell@gmail.com>
1 parent 22d4be2 commit 41c3ace

File tree

26 files changed

+1478
-359
lines changed

26 files changed

+1478
-359
lines changed

github/provider.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ func Provider() *schema.Provider {
139139
"github_actions_organization_oidc_subject_claim_customization_template": resourceGithubActionsOrganizationOIDCSubjectClaimCustomizationTemplate(),
140140
"github_actions_organization_permissions": resourceGithubActionsOrganizationPermissions(),
141141
"github_actions_organization_secret": resourceGithubActionsOrganizationSecret(),
142-
"github_actions_organization_variable": resourceGithubActionsOrganizationVariable(),
143142
"github_actions_organization_secret_repositories": resourceGithubActionsOrganizationSecretRepositories(),
144143
"github_actions_organization_secret_repository": resourceGithubActionsOrganizationSecretRepository(),
144+
"github_actions_organization_variable": resourceGithubActionsOrganizationVariable(),
145+
"github_actions_organization_variable_repositories": resourceGithubActionsOrganizationVariableRepositories(),
146+
"github_actions_organization_variable_repository": resourceGithubActionsOrganizationVariableRepository(),
145147
"github_actions_repository_access_level": resourceGithubActionsRepositoryAccessLevel(),
146148
"github_actions_repository_oidc_subject_claim_customization_template": resourceGithubActionsRepositoryOIDCSubjectClaimCustomizationTemplate(),
147149
"github_actions_repository_permissions": resourceGithubActionsRepositoryPermissions(),
@@ -161,6 +163,7 @@ func Provider() *schema.Provider {
161163
"github_codespaces_user_secret": resourceGithubCodespacesUserSecret(),
162164
"github_dependabot_organization_secret": resourceGithubDependabotOrganizationSecret(),
163165
"github_dependabot_organization_secret_repositories": resourceGithubDependabotOrganizationSecretRepositories(),
166+
"github_dependabot_organization_secret_repository": resourceGithubDependabotOrganizationSecretRepository(),
164167
"github_dependabot_secret": resourceGithubDependabotSecret(),
165168
"github_emu_group_mapping": resourceGithubEMUGroupMapping(),
166169
"github_issue": resourceGithubIssue(),

github/resource_github_actions_organization_secret.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func resourceGithubActionsOrganizationSecret() *schema.Resource {
6969
},
7070
Optional: true,
7171
Description: "An array of repository IDs that can access the organization secret.",
72+
Deprecated: "This field is deprecated and will be removed in a future release. Please use the `github_actions_organization_secret_repositories` or `github_actions_organization_secret_repository` resources to manage repository access to organization secrets.",
7273
},
7374
"created_at": {
7475
Type: schema.TypeString,
@@ -225,32 +226,34 @@ func resourceGithubActionsOrganizationSecretRead(ctx context.Context, d *schema.
225226
return diag.FromErr(err)
226227
}
227228

228-
repoIDs := []int64{}
229229
if secret.Visibility == "selected" {
230-
opt := &github.ListOptions{
231-
PerPage: maxPerPage,
232-
}
233-
for {
234-
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
235-
if err != nil {
236-
return diag.FromErr(err)
230+
if _, ok := d.GetOk("selected_repository_ids"); ok {
231+
repoIDs := []int64{}
232+
opt := &github.ListOptions{
233+
PerPage: maxPerPage,
237234
}
238-
239-
for _, repo := range results.Repositories {
240-
repoIDs = append(repoIDs, repo.GetID())
235+
for {
236+
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
237+
if err != nil {
238+
return diag.FromErr(err)
239+
}
240+
241+
for _, repo := range results.Repositories {
242+
repoIDs = append(repoIDs, repo.GetID())
243+
}
244+
245+
if resp.NextPage == 0 {
246+
break
247+
}
248+
opt.Page = resp.NextPage
241249
}
242250

243-
if resp.NextPage == 0 {
244-
break
251+
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
252+
return diag.FromErr(err)
245253
}
246-
opt.Page = resp.NextPage
247254
}
248255
}
249256

250-
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
251-
return diag.FromErr(err)
252-
}
253-
254257
return nil
255258
}
256259

github/resource_github_actions_organization_secret_repositories.go

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,91 +4,91 @@ import (
44
"context"
55

66
"github.com/google/go-github/v82/github"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
78
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
89
)
910

1011
func resourceGithubActionsOrganizationSecretRepositories() *schema.Resource {
1112
return &schema.Resource{
12-
Create: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
13-
Read: resourceGithubActionsOrganizationSecretRepositoriesRead,
14-
Update: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
15-
Delete: resourceGithubActionsOrganizationSecretRepositoriesDelete,
16-
Importer: &schema.ResourceImporter{
17-
StateContext: schema.ImportStatePassthroughContext,
18-
},
19-
2013
Schema: map[string]*schema.Schema{
2114
"secret_name": {
2215
Type: schema.TypeString,
2316
Required: true,
2417
ForceNew: true,
25-
Description: "Name of the existing secret.",
2618
ValidateDiagFunc: validateSecretNameFunc,
19+
Description: "Name of the existing secret.",
2720
},
2821
"selected_repository_ids": {
2922
Type: schema.TypeSet,
23+
Set: schema.HashInt,
3024
Elem: &schema.Schema{
3125
Type: schema.TypeInt,
3226
},
33-
Set: schema.HashInt,
3427
Required: true,
3528
Description: "An array of repository ids that can access the organization secret.",
3629
},
3730
},
31+
32+
CreateContext: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
33+
ReadContext: resourceGithubActionsOrganizationSecretRepositoriesRead,
34+
UpdateContext: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
35+
DeleteContext: resourceGithubActionsOrganizationSecretRepositoriesDelete,
36+
Importer: &schema.ResourceImporter{
37+
StateContext: resourceGithubActionsOrganizationSecretRepositoriesImport,
38+
},
3839
}
3940
}
4041

41-
func resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate(d *schema.ResourceData, meta any) error {
42-
client := meta.(*Owner).v3client
43-
owner := meta.(*Owner).name
44-
ctx := context.Background()
45-
46-
err := checkOrganization(meta)
47-
if err != nil {
48-
return err
42+
func resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
43+
if err := checkOrganization(m); err != nil {
44+
return diag.FromErr(err)
4945
}
5046

51-
secretName := d.Get("secret_name").(string)
52-
selectedRepositories := d.Get("selected_repository_ids")
47+
meta := m.(*Owner)
48+
client := meta.v3client
49+
owner := meta.name
5350

54-
selectedRepositoryIDs := []int64{}
51+
secretName := d.Get("secret_name").(string)
52+
repoIDs := []int64{}
5553

56-
ids := selectedRepositories.(*schema.Set).List()
54+
ids := d.Get("selected_repository_ids").(*schema.Set).List()
5755
for _, id := range ids {
58-
selectedRepositoryIDs = append(selectedRepositoryIDs, int64(id.(int)))
56+
repoIDs = append(repoIDs, int64(id.(int)))
5957
}
6058

61-
_, err = client.Actions.SetSelectedReposForOrgSecret(ctx, owner, secretName, selectedRepositoryIDs)
59+
_, err := client.Actions.SetSelectedReposForOrgSecret(ctx, owner, secretName, repoIDs)
6260
if err != nil {
63-
return err
61+
return diag.FromErr(err)
6462
}
6563

6664
d.SetId(secretName)
67-
return resourceGithubActionsOrganizationSecretRepositoriesRead(d, meta)
68-
}
6965

70-
func resourceGithubActionsOrganizationSecretRepositoriesRead(d *schema.ResourceData, meta any) error {
71-
client := meta.(*Owner).v3client
72-
owner := meta.(*Owner).name
73-
ctx := context.Background()
66+
return nil
67+
}
7468

75-
err := checkOrganization(meta)
76-
if err != nil {
77-
return err
69+
func resourceGithubActionsOrganizationSecretRepositoriesRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
70+
if err := checkOrganization(m); err != nil {
71+
return diag.FromErr(err)
7872
}
7973

80-
selectedRepositoryIDs := []int64{}
74+
meta := m.(*Owner)
75+
client := meta.v3client
76+
owner := meta.name
77+
78+
secretName := d.Get("secret_name").(string)
79+
80+
repoIDs := []int64{}
8181
opt := &github.ListOptions{
8282
PerPage: maxPerPage,
8383
}
8484
for {
85-
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, d.Id(), opt)
85+
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
8686
if err != nil {
87-
return err
87+
return diag.FromErr(err)
8888
}
8989

9090
for _, repo := range results.Repositories {
91-
selectedRepositoryIDs = append(selectedRepositoryIDs, repo.GetID())
91+
repoIDs = append(repoIDs, repo.GetID())
9292
}
9393

9494
if resp.NextPage == 0 {
@@ -97,28 +97,64 @@ func resourceGithubActionsOrganizationSecretRepositoriesRead(d *schema.ResourceD
9797
opt.Page = resp.NextPage
9898
}
9999

100-
if err = d.Set("selected_repository_ids", selectedRepositoryIDs); err != nil {
101-
return err
100+
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
101+
return diag.FromErr(err)
102102
}
103103

104104
return nil
105105
}
106106

107-
func resourceGithubActionsOrganizationSecretRepositoriesDelete(d *schema.ResourceData, meta any) error {
108-
client := meta.(*Owner).v3client
109-
owner := meta.(*Owner).name
110-
ctx := context.WithValue(context.Background(), ctxId, d.Id())
111-
112-
err := checkOrganization(meta)
113-
if err != nil {
114-
return err
107+
func resourceGithubActionsOrganizationSecretRepositoriesDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
108+
if err := checkOrganization(m); err != nil {
109+
return diag.FromErr(err)
115110
}
116111

117-
selectedRepositoryIDs := []int64{}
118-
_, err = client.Actions.SetSelectedReposForOrgSecret(ctx, owner, d.Id(), selectedRepositoryIDs)
112+
meta := m.(*Owner)
113+
client := meta.v3client
114+
owner := meta.name
115+
116+
_, err := client.Actions.SetSelectedReposForOrgSecret(ctx, owner, d.Id(), []int64{})
119117
if err != nil {
120-
return err
118+
return diag.FromErr(err)
121119
}
122120

123121
return nil
124122
}
123+
124+
func resourceGithubActionsOrganizationSecretRepositoriesImport(ctx context.Context, d *schema.ResourceData, m any) ([]*schema.ResourceData, error) {
125+
meta := m.(*Owner)
126+
client := meta.v3client
127+
owner := meta.name
128+
129+
secretName := d.Id()
130+
131+
if err := d.Set("secret_name", secretName); err != nil {
132+
return nil, err
133+
}
134+
135+
repoIDs := []int64{}
136+
opt := &github.ListOptions{
137+
PerPage: maxPerPage,
138+
}
139+
for {
140+
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
for _, repo := range results.Repositories {
146+
repoIDs = append(repoIDs, repo.GetID())
147+
}
148+
149+
if resp.NextPage == 0 {
150+
break
151+
}
152+
opt.Page = resp.NextPage
153+
}
154+
155+
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
156+
return nil, err
157+
}
158+
159+
return []*schema.ResourceData{d}, nil
160+
}

github/resource_github_actions_organization_secret_repositories_test.go

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package github
22

33
import (
4+
"encoding/base64"
45
"fmt"
56
"testing"
67

@@ -9,53 +10,49 @@ import (
910
)
1011

1112
func TestAccGithubActionsOrganizationSecretRepositories(t *testing.T) {
12-
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
13-
repoName1 := fmt.Sprintf("%srepo-act-org-secret-%s-1", testResourcePrefix, randomID)
14-
repoName2 := fmt.Sprintf("%srepo-act-org-secret-%s-2", testResourcePrefix, randomID)
15-
16-
t.Run("set repository allowlist for a organization secret", func(t *testing.T) {
17-
if len(testAccConf.testOrgSecretName) == 0 {
18-
t.Skipf("'GH_TEST_ORG_SECRET_NAME' environment variable is missing")
19-
}
13+
t.Run("create", func(t *testing.T) {
14+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
15+
secretName := fmt.Sprintf("test_%s", randomID)
16+
secretValue := base64.StdEncoding.EncodeToString([]byte("foo"))
17+
repoName0 := fmt.Sprintf("%s%s-0", testResourcePrefix, randomID)
18+
repoName1 := fmt.Sprintf("%s%s-1", testResourcePrefix, randomID)
2019

2120
config := fmt.Sprintf(`
22-
resource "github_repository" "test_repo_1" {
23-
name = "%s"
24-
visibility = "internal"
25-
vulnerability_alerts = "true"
26-
}
27-
28-
resource "github_repository" "test_repo_2" {
29-
name = "%s"
30-
visibility = "internal"
31-
vulnerability_alerts = "true"
32-
}
33-
34-
resource "github_actions_organization_secret_repositories" "org_secret_repos" {
35-
secret_name = "%s"
36-
selected_repository_ids = [
37-
github_repository.test_repo_1.repo_id,
38-
github_repository.test_repo_2.repo_id
39-
]
40-
}
41-
`, repoName1, repoName2, testAccConf.testOrgSecretName)
42-
43-
check := resource.ComposeTestCheckFunc(
44-
resource.TestCheckResourceAttrSet(
45-
"github_actions_organization_secret_repositories.org_secret_repos", "secret_name",
46-
),
47-
resource.TestCheckResourceAttr(
48-
"github_actions_organization_secret_repositories.org_secret_repos", "selected_repository_ids.#", "2",
49-
),
50-
)
21+
resource "github_actions_organization_secret" "test" {
22+
secret_name = "%s"
23+
encrypted_value = "%s"
24+
visibility = "selected"
25+
}
26+
27+
resource "github_repository" "test_0" {
28+
name = "%s"
29+
visibility = "public"
30+
}
31+
32+
resource "github_repository" "test_1" {
33+
name = "%s"
34+
visibility = "public"
35+
}
36+
37+
resource "github_actions_organization_secret_repositories" "test" {
38+
secret_name = github_actions_organization_secret.test.secret_name
39+
selected_repository_ids = [
40+
github_repository.test_0.repo_id,
41+
github_repository.test_1.repo_id
42+
]
43+
}
44+
`, secretName, secretValue, repoName0, repoName1)
5145

5246
resource.Test(t, resource.TestCase{
5347
PreCheck: func() { skipUnlessHasOrgs(t) },
5448
ProviderFactories: providerFactories,
5549
Steps: []resource.TestStep{
5650
{
5751
Config: config,
58-
Check: check,
52+
Check: resource.ComposeTestCheckFunc(
53+
resource.TestCheckResourceAttrPair("github_actions_organization_secret_repositories.test", "secret_name", "github_actions_organization_secret.test", "secret_name"),
54+
resource.TestCheckResourceAttr("github_actions_organization_secret_repositories.test", "selected_repository_ids.#", "2"),
55+
),
5956
},
6057
},
6158
})

0 commit comments

Comments
 (0)