From 9e09aee09a1afb2491ae575ac073d61dc4640b7b Mon Sep 17 00:00:00 2001 From: Ken Spur Date: Wed, 28 Jun 2023 20:44:03 +0200 Subject: [PATCH] [Bug]: Repository name updates break dependent repository secrets (#1754) * fix rename issue & add tests * fix rename issue & add tests * fix rename issue & add tests * remove main.tf --------- Co-authored-by: Keegan Campbell --- github/resource_github_actions_secret.go | 2 +- github/resource_github_actions_secret_test.go | 98 +++++++++++++++++++ github/resource_github_codespaces_secret.go | 2 +- .../resource_github_codespaces_secret_test.go | 96 ++++++++++++++++++ github/resource_github_dependabot_secret.go | 2 +- .../resource_github_dependabot_secret_test.go | 98 +++++++++++++++++++ 6 files changed, 295 insertions(+), 3 deletions(-) diff --git a/github/resource_github_actions_secret.go b/github/resource_github_actions_secret.go index 2253521428..551a0073ee 100644 --- a/github/resource_github_actions_secret.go +++ b/github/resource_github_actions_secret.go @@ -17,7 +17,6 @@ func resourceGithubActionsSecret() *schema.Resource { return &schema.Resource{ Create: resourceGithubActionsSecretCreateOrUpdate, Read: resourceGithubActionsSecretRead, - Update: resourceGithubActionsSecretCreateOrUpdate, Delete: resourceGithubActionsSecretDelete, Importer: &schema.ResourceImporter{ State: resourceGithubActionsSecretImport, @@ -27,6 +26,7 @@ func resourceGithubActionsSecret() *schema.Resource { "repository": { Type: schema.TypeString, Required: true, + ForceNew: true, Description: "Name of the repository.", }, "secret_name": { diff --git a/github/resource_github_actions_secret_test.go b/github/resource_github_actions_secret_test.go index a8e6c65237..7b80f4b916 100644 --- a/github/resource_github_actions_secret_test.go +++ b/github/resource_github_actions_secret_test.go @@ -154,6 +154,104 @@ func TestAccGithubActionsSecret(t *testing.T) { }) }) + t.Run("creates and updates repository name without error", func(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-%s", randomID) + updatedRepoName := fmt.Sprintf("tf-acc-test-%s-updated", randomID) + secretValue := base64.StdEncoding.EncodeToString([]byte("super_secret_value")) + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + } + + resource "github_actions_secret" "plaintext_secret" { + repository = github_repository.test.name + secret_name = "test_plaintext_secret" + plaintext_value = "%s" + } + + resource "github_actions_secret" "encrypted_secret" { + repository = github_repository.test.name + secret_name = "test_encrypted_secret" + encrypted_value = "%s" + } + `, repoName, secretValue, secretValue) + + checks := map[string]resource.TestCheckFunc{ + "before": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_actions_secret.plaintext_secret", "repository", + repoName, + ), + resource.TestCheckResourceAttr( + "github_actions_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_actions_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_actions_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_actions_secret.plaintext_secret", "updated_at", + ), + ), + "after": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_actions_secret.plaintext_secret", "repository", + updatedRepoName, + ), + resource.TestCheckResourceAttr( + "github_actions_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_actions_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_actions_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_actions_secret.plaintext_secret", "updated_at", + ), + ), + } + + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: checks["before"], + }, + { + Config: strings.Replace(config, + repoName, + updatedRepoName, 2), + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + t.Run("deletes secrets without error", func(t *testing.T) { config := fmt.Sprintf(` resource "github_repository" "test" { diff --git a/github/resource_github_codespaces_secret.go b/github/resource_github_codespaces_secret.go index c059ce2b14..9d8d729606 100644 --- a/github/resource_github_codespaces_secret.go +++ b/github/resource_github_codespaces_secret.go @@ -16,7 +16,6 @@ func resourceGithubCodespacesSecret() *schema.Resource { return &schema.Resource{ Create: resourceGithubCodespacesSecretCreateOrUpdate, Read: resourceGithubCodespacesSecretRead, - Update: resourceGithubCodespacesSecretCreateOrUpdate, Delete: resourceGithubCodespacesSecretDelete, Importer: &schema.ResourceImporter{ State: resourceGithubCodespacesSecretImport, @@ -26,6 +25,7 @@ func resourceGithubCodespacesSecret() *schema.Resource { "repository": { Type: schema.TypeString, Required: true, + ForceNew: true, Description: "Name of the repository.", }, "secret_name": { diff --git a/github/resource_github_codespaces_secret_test.go b/github/resource_github_codespaces_secret_test.go index 01baaaa190..c4cef95376 100644 --- a/github/resource_github_codespaces_secret_test.go +++ b/github/resource_github_codespaces_secret_test.go @@ -154,6 +154,102 @@ func TestAccGithubCodespacesSecret(t *testing.T) { }) }) + t.Run("creates and updates repository name without error", func(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-%s", randomID) + updatedRepoName := fmt.Sprintf("tf-acc-test-%s-updated", randomID) + secretValue := base64.StdEncoding.EncodeToString([]byte("super_secret_value")) + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + } + resource "github_codespaces_secret" "plaintext_secret" { + repository = github_repository.test.name + secret_name = "test_plaintext_secret" + plaintext_value = "%s" + } + resource "github_codespaces_secret" "encrypted_secret" { + repository = github_repository.test.name + secret_name = "test_encrypted_secret" + encrypted_value = "%s" + } + `, repoName, secretValue, secretValue) + + checks := map[string]resource.TestCheckFunc{ + "before": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_codespaces_secret.plaintext_secret", "repository", + repoName, + ), + resource.TestCheckResourceAttr( + "github_codespaces_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_codespaces_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_codespaces_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_codespaces_secret.plaintext_secret", "updated_at", + ), + ), + "after": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_codespaces_secret.plaintext_secret", "repository", + updatedRepoName, + ), + resource.TestCheckResourceAttr( + "github_codespaces_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_codespaces_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_codespaces_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_codespaces_secret.plaintext_secret", "updated_at", + ), + ), + } + + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: checks["before"], + }, + { + Config: strings.Replace(config, + repoName, + updatedRepoName, 2), + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + t.Run("deletes secrets without error", func(t *testing.T) { config := fmt.Sprintf(` resource "github_repository" "test" { diff --git a/github/resource_github_dependabot_secret.go b/github/resource_github_dependabot_secret.go index ae2c0118fb..5760d3b551 100644 --- a/github/resource_github_dependabot_secret.go +++ b/github/resource_github_dependabot_secret.go @@ -17,7 +17,6 @@ func resourceGithubDependabotSecret() *schema.Resource { return &schema.Resource{ Create: resourceGithubDependabotSecretCreateOrUpdate, Read: resourceGithubDependabotSecretRead, - Update: resourceGithubDependabotSecretCreateOrUpdate, Delete: resourceGithubDependabotSecretDelete, Importer: &schema.ResourceImporter{ State: resourceGithubDependabotSecretImport, @@ -27,6 +26,7 @@ func resourceGithubDependabotSecret() *schema.Resource { "repository": { Type: schema.TypeString, Required: true, + ForceNew: true, Description: "Name of the repository.", }, "secret_name": { diff --git a/github/resource_github_dependabot_secret_test.go b/github/resource_github_dependabot_secret_test.go index 710c09e806..4cd636a777 100644 --- a/github/resource_github_dependabot_secret_test.go +++ b/github/resource_github_dependabot_secret_test.go @@ -154,6 +154,104 @@ func TestAccGithubDependabotSecret(t *testing.T) { }) }) + t.Run("creates and updates repository name without error", func(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-%s", randomID) + updatedRepoName := fmt.Sprintf("tf-acc-test-%s-updated", randomID) + secretValue := base64.StdEncoding.EncodeToString([]byte("super_secret_value")) + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + } + + resource "github_dependabot_secret" "plaintext_secret" { + repository = github_repository.test.name + secret_name = "test_plaintext_secret" + plaintext_value = "%s" + } + + resource "github_dependabot_secret" "encrypted_secret" { + repository = github_repository.test.name + secret_name = "test_encrypted_secret" + encrypted_value = "%s" + } + `, repoName, secretValue, secretValue) + + checks := map[string]resource.TestCheckFunc{ + "before": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_dependabot_secret.plaintext_secret", "repository", + repoName, + ), + resource.TestCheckResourceAttr( + "github_dependabot_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_dependabot_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_dependabot_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_dependabot_secret.plaintext_secret", "updated_at", + ), + ), + "after": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_dependabot_secret.plaintext_secret", "repository", + updatedRepoName, + ), + resource.TestCheckResourceAttr( + "github_dependabot_secret.plaintext_secret", "plaintext_value", + secretValue, + ), + resource.TestCheckResourceAttr( + "github_dependabot_secret.encrypted_secret", "encrypted_value", + secretValue, + ), + resource.TestCheckResourceAttrSet( + "github_dependabot_secret.plaintext_secret", "created_at", + ), + resource.TestCheckResourceAttrSet( + "github_dependabot_secret.plaintext_secret", "updated_at", + ), + ), + } + + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: checks["before"], + }, + { + Config: strings.Replace(config, + repoName, + updatedRepoName, 2), + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + t.Run("deletes secrets without error", func(t *testing.T) { config := fmt.Sprintf(` resource "github_repository" "test" {