Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ func Provider() *schema.Provider {
"github_actions_organization_oidc_subject_claim_customization_template": resourceGithubActionsOrganizationOIDCSubjectClaimCustomizationTemplate(),
"github_actions_organization_permissions": resourceGithubActionsOrganizationPermissions(),
"github_actions_organization_secret": resourceGithubActionsOrganizationSecret(),
"github_actions_organization_variable": resourceGithubActionsOrganizationVariable(),
"github_actions_organization_secret_repositories": resourceGithubActionsOrganizationSecretRepositories(),
"github_actions_organization_secret_repository": resourceGithubActionsOrganizationSecretRepository(),
"github_actions_organization_variable": resourceGithubActionsOrganizationVariable(),
"github_actions_organization_variable_repositories": resourceGithubActionsOrganizationVariableRepositories(),
"github_actions_organization_variable_repository": resourceGithubActionsOrganizationVariableRepository(),
"github_actions_repository_access_level": resourceGithubActionsRepositoryAccessLevel(),
"github_actions_repository_oidc_subject_claim_customization_template": resourceGithubActionsRepositoryOIDCSubjectClaimCustomizationTemplate(),
"github_actions_repository_permissions": resourceGithubActionsRepositoryPermissions(),
Expand All @@ -161,6 +163,7 @@ func Provider() *schema.Provider {
"github_codespaces_user_secret": resourceGithubCodespacesUserSecret(),
"github_dependabot_organization_secret": resourceGithubDependabotOrganizationSecret(),
"github_dependabot_organization_secret_repositories": resourceGithubDependabotOrganizationSecretRepositories(),
"github_dependabot_organization_secret_repository": resourceGithubDependabotOrganizationSecretRepository(),
"github_dependabot_secret": resourceGithubDependabotSecret(),
"github_emu_group_mapping": resourceGithubEMUGroupMapping(),
"github_issue": resourceGithubIssue(),
Expand Down
39 changes: 21 additions & 18 deletions github/resource_github_actions_organization_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func resourceGithubActionsOrganizationSecret() *schema.Resource {
},
Optional: true,
Description: "An array of repository IDs that can access the organization secret.",
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.",
},
"created_at": {
Type: schema.TypeString,
Expand Down Expand Up @@ -225,32 +226,34 @@ func resourceGithubActionsOrganizationSecretRead(ctx context.Context, d *schema.
return diag.FromErr(err)
}

repoIDs := []int64{}
if secret.Visibility == "selected" {
opt := &github.ListOptions{
PerPage: maxPerPage,
}
for {
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
if err != nil {
return diag.FromErr(err)
if _, ok := d.GetOk("selected_repository_ids"); ok {
repoIDs := []int64{}
opt := &github.ListOptions{
PerPage: maxPerPage,
}

for _, repo := range results.Repositories {
repoIDs = append(repoIDs, repo.GetID())
for {
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
if err != nil {
return diag.FromErr(err)
}

for _, repo := range results.Repositories {
repoIDs = append(repoIDs, repo.GetID())
}

if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}

if resp.NextPage == 0 {
break
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
return diag.FromErr(err)
}
opt.Page = resp.NextPage
}
}

if err := d.Set("selected_repository_ids", repoIDs); err != nil {
return diag.FromErr(err)
}

return nil
}

Expand Down
138 changes: 87 additions & 51 deletions github/resource_github_actions_organization_secret_repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,91 @@ import (
"context"

"github.com/google/go-github/v82/github"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceGithubActionsOrganizationSecretRepositories() *schema.Resource {
return &schema.Resource{
Create: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
Read: resourceGithubActionsOrganizationSecretRepositoriesRead,
Update: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
Delete: resourceGithubActionsOrganizationSecretRepositoriesDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"secret_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Name of the existing secret.",
ValidateDiagFunc: validateSecretNameFunc,
Description: "Name of the existing secret.",
},
"selected_repository_ids": {
Type: schema.TypeSet,
Set: schema.HashInt,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Set: schema.HashInt,
Required: true,
Description: "An array of repository ids that can access the organization secret.",
},
},

CreateContext: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
ReadContext: resourceGithubActionsOrganizationSecretRepositoriesRead,
UpdateContext: resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate,
DeleteContext: resourceGithubActionsOrganizationSecretRepositoriesDelete,
Importer: &schema.ResourceImporter{
StateContext: resourceGithubActionsOrganizationSecretRepositoriesImport,
},
}
}

func resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
owner := meta.(*Owner).name
ctx := context.Background()

err := checkOrganization(meta)
if err != nil {
return err
func resourceGithubActionsOrganizationSecretRepositoriesCreateOrUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
if err := checkOrganization(m); err != nil {
return diag.FromErr(err)
}

secretName := d.Get("secret_name").(string)
selectedRepositories := d.Get("selected_repository_ids")
meta := m.(*Owner)
client := meta.v3client
owner := meta.name

selectedRepositoryIDs := []int64{}
secretName := d.Get("secret_name").(string)
repoIDs := []int64{}

ids := selectedRepositories.(*schema.Set).List()
ids := d.Get("selected_repository_ids").(*schema.Set).List()
for _, id := range ids {
selectedRepositoryIDs = append(selectedRepositoryIDs, int64(id.(int)))
repoIDs = append(repoIDs, int64(id.(int)))
}

_, err = client.Actions.SetSelectedReposForOrgSecret(ctx, owner, secretName, selectedRepositoryIDs)
_, err := client.Actions.SetSelectedReposForOrgSecret(ctx, owner, secretName, repoIDs)
if err != nil {
return err
return diag.FromErr(err)
}

d.SetId(secretName)
return resourceGithubActionsOrganizationSecretRepositoriesRead(d, meta)
}

func resourceGithubActionsOrganizationSecretRepositoriesRead(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
owner := meta.(*Owner).name
ctx := context.Background()
return nil
}

err := checkOrganization(meta)
if err != nil {
return err
func resourceGithubActionsOrganizationSecretRepositoriesRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
if err := checkOrganization(m); err != nil {
return diag.FromErr(err)
}

selectedRepositoryIDs := []int64{}
meta := m.(*Owner)
client := meta.v3client
owner := meta.name

secretName := d.Get("secret_name").(string)

repoIDs := []int64{}
opt := &github.ListOptions{
PerPage: maxPerPage,
}
for {
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, d.Id(), opt)
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
if err != nil {
return err
return diag.FromErr(err)
}

for _, repo := range results.Repositories {
selectedRepositoryIDs = append(selectedRepositoryIDs, repo.GetID())
repoIDs = append(repoIDs, repo.GetID())
}

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

if err = d.Set("selected_repository_ids", selectedRepositoryIDs); err != nil {
return err
if err := d.Set("selected_repository_ids", repoIDs); err != nil {
return diag.FromErr(err)
}

return nil
}

func resourceGithubActionsOrganizationSecretRepositoriesDelete(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
owner := meta.(*Owner).name
ctx := context.WithValue(context.Background(), ctxId, d.Id())

err := checkOrganization(meta)
if err != nil {
return err
func resourceGithubActionsOrganizationSecretRepositoriesDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
if err := checkOrganization(m); err != nil {
return diag.FromErr(err)
}

selectedRepositoryIDs := []int64{}
_, err = client.Actions.SetSelectedReposForOrgSecret(ctx, owner, d.Id(), selectedRepositoryIDs)
meta := m.(*Owner)
client := meta.v3client
owner := meta.name

_, err := client.Actions.SetSelectedReposForOrgSecret(ctx, owner, d.Id(), []int64{})
if err != nil {
return err
return diag.FromErr(err)
}

return nil
}

func resourceGithubActionsOrganizationSecretRepositoriesImport(ctx context.Context, d *schema.ResourceData, m any) ([]*schema.ResourceData, error) {
meta := m.(*Owner)
client := meta.v3client
owner := meta.name

secretName := d.Id()

if err := d.Set("secret_name", secretName); err != nil {
return nil, err
}

repoIDs := []int64{}
opt := &github.ListOptions{
PerPage: maxPerPage,
}
for {
results, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, owner, secretName, opt)
if err != nil {
return nil, err
}

for _, repo := range results.Repositories {
repoIDs = append(repoIDs, repo.GetID())
}

if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}

if err := d.Set("selected_repository_ids", repoIDs); err != nil {
return nil, err
}

return []*schema.ResourceData{d}, nil
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package github

import (
"encoding/base64"
"fmt"
"testing"

Expand All @@ -9,53 +10,49 @@ import (
)

func TestAccGithubActionsOrganizationSecretRepositories(t *testing.T) {
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
repoName1 := fmt.Sprintf("%srepo-act-org-secret-%s-1", testResourcePrefix, randomID)
repoName2 := fmt.Sprintf("%srepo-act-org-secret-%s-2", testResourcePrefix, randomID)

t.Run("set repository allowlist for a organization secret", func(t *testing.T) {
if len(testAccConf.testOrgSecretName) == 0 {
t.Skipf("'GH_TEST_ORG_SECRET_NAME' environment variable is missing")
}
t.Run("create", func(t *testing.T) {
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
secretName := fmt.Sprintf("test_%s", randomID)
secretValue := base64.StdEncoding.EncodeToString([]byte("foo"))
repoName0 := fmt.Sprintf("%s%s-0", testResourcePrefix, randomID)
repoName1 := fmt.Sprintf("%s%s-1", testResourcePrefix, randomID)

config := fmt.Sprintf(`
resource "github_repository" "test_repo_1" {
name = "%s"
visibility = "internal"
vulnerability_alerts = "true"
}

resource "github_repository" "test_repo_2" {
name = "%s"
visibility = "internal"
vulnerability_alerts = "true"
}

resource "github_actions_organization_secret_repositories" "org_secret_repos" {
secret_name = "%s"
selected_repository_ids = [
github_repository.test_repo_1.repo_id,
github_repository.test_repo_2.repo_id
]
}
`, repoName1, repoName2, testAccConf.testOrgSecretName)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(
"github_actions_organization_secret_repositories.org_secret_repos", "secret_name",
),
resource.TestCheckResourceAttr(
"github_actions_organization_secret_repositories.org_secret_repos", "selected_repository_ids.#", "2",
),
)
resource "github_actions_organization_secret" "test" {
secret_name = "%s"
encrypted_value = "%s"
visibility = "selected"
}

resource "github_repository" "test_0" {
name = "%s"
visibility = "public"
}

resource "github_repository" "test_1" {
name = "%s"
visibility = "public"
}

resource "github_actions_organization_secret_repositories" "test" {
secret_name = github_actions_organization_secret.test.secret_name
selected_repository_ids = [
github_repository.test_0.repo_id,
github_repository.test_1.repo_id
]
}
`, secretName, secretValue, repoName0, repoName1)

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessHasOrgs(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: config,
Check: check,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair("github_actions_organization_secret_repositories.test", "secret_name", "github_actions_organization_secret.test", "secret_name"),
resource.TestCheckResourceAttr("github_actions_organization_secret_repositories.test", "selected_repository_ids.#", "2"),
),
},
},
})
Expand Down
Loading