diff --git a/github/migrate_github_actions_organization_secret.go b/github/migrate_github_actions_organization_secret.go new file mode 100644 index 0000000000..56c80fecd5 --- /dev/null +++ b/github/migrate_github_actions_organization_secret.go @@ -0,0 +1,36 @@ +package github + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func resourceGithubActionsOrganizationSecretMigrateState(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { + switch v { + case 0: + log.Printf("[INFO] Found GitHub Actions Organization Secret State v0; migrating to v1") + return migrateGithubActionsOrganizationSecretStateV0toV1(is) + default: + return is, fmt.Errorf("unexpected schema version: %d", v) + } +} + +func migrateGithubActionsOrganizationSecretStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) { + if is.Empty() { + log.Printf("[DEBUG] Empty InstanceState; nothing to migrate.") + return is, nil + } + + log.Printf("[DEBUG] GitHub Actions Organization Secret Attributes before migration: %#v", is.Attributes) + + // Add the destroy_on_drift field with default value true if it doesn't exist + if _, ok := is.Attributes["destroy_on_drift"]; !ok { + is.Attributes["destroy_on_drift"] = "true" + } + + log.Printf("[DEBUG] GitHub Actions Organization Secret Attributes after State Migration: %#v", is.Attributes) + + return is, nil +} diff --git a/github/migrate_github_actions_organization_secret_test.go b/github/migrate_github_actions_organization_secret_test.go new file mode 100644 index 0000000000..ef6f032963 --- /dev/null +++ b/github/migrate_github_actions_organization_secret_test.go @@ -0,0 +1,69 @@ +package github + +import ( + "reflect" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestMigrateGithubActionsOrganizationSecretStateV0toV1(t *testing.T) { + // Secret without destroy_on_drift should get default value + oldAttributes := map[string]string{ + "id": "test-secret", + "secret_name": "test-secret", + "visibility": "private", + "created_at": "2023-01-01T00:00:00Z", + "updated_at": "2023-01-01T00:00:00Z", + "plaintext_value": "secret-value", + } + + newState, err := migrateGithubActionsOrganizationSecretStateV0toV1(&terraform.InstanceState{ + ID: "test-secret", + Attributes: oldAttributes, + }) + if err != nil { + t.Fatal(err) + } + + expectedAttributes := map[string]string{ + "id": "test-secret", + "secret_name": "test-secret", + "visibility": "private", + "created_at": "2023-01-01T00:00:00Z", + "updated_at": "2023-01-01T00:00:00Z", + "plaintext_value": "secret-value", + "destroy_on_drift": "true", + } + if !reflect.DeepEqual(newState.Attributes, expectedAttributes) { + t.Fatalf("Expected attributes:\n%#v\n\nGiven:\n%#v\n", + expectedAttributes, newState.Attributes) + } + + // Secret with existing destroy_on_drift should be preserved + oldAttributesWithDrift := map[string]string{ + "id": "test-secret", + "secret_name": "test-secret", + "visibility": "private", + "destroy_on_drift": "false", + } + + newState2, err := migrateGithubActionsOrganizationSecretStateV0toV1(&terraform.InstanceState{ + ID: "test-secret", + Attributes: oldAttributesWithDrift, + }) + if err != nil { + t.Fatal(err) + } + + expectedAttributesWithDrift := map[string]string{ + "id": "test-secret", + "secret_name": "test-secret", + "visibility": "private", + "destroy_on_drift": "false", + } + if !reflect.DeepEqual(newState2.Attributes, expectedAttributesWithDrift) { + t.Fatalf("Expected attributes:\n%#v\n\nGiven:\n%#v\n", + expectedAttributesWithDrift, newState2.Attributes) + } +} diff --git a/github/resource_github_actions_organization_secret.go b/github/resource_github_actions_organization_secret.go index 2f9e78d4fd..0b7f63e0fb 100644 --- a/github/resource_github_actions_organization_secret.go +++ b/github/resource_github_actions_organization_secret.go @@ -27,6 +27,11 @@ func resourceGithubActionsOrganizationSecret() *schema.Resource { }, }, + // Schema migration added in v6.7.1 to handle the addition of destroy_on_drift field + // Resources created before v6.7.0 need the field populated with default value + SchemaVersion: 1, + MigrateState: resourceGithubActionsOrganizationSecretMigrateState, + Schema: map[string]*schema.Schema{ "secret_name": { Type: schema.TypeString,