Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add environment secret import capabilities #2462

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
41 changes: 41 additions & 0 deletions github/resource_github_actions_environment_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package github
import (
"context"
"encoding/base64"
"fmt"
"log"
"net/http"
"net/url"
"strings"

"github.com/google/go-github/v65/github"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand All @@ -17,6 +19,9 @@ func resourceGithubActionsEnvironmentSecret() *schema.Resource {
Create: resourceGithubActionsEnvironmentSecretCreateOrUpdate,
Read: resourceGithubActionsEnvironmentSecretRead,
Delete: resourceGithubActionsEnvironmentSecretDelete,
Importer: &schema.ResourceImporter{
State: resourceGithubActionsEnvironmentSecretImport,
},

Schema: map[string]*schema.Schema{
"repository": {
Expand Down Expand Up @@ -211,6 +216,42 @@ func resourceGithubActionsEnvironmentSecretDelete(d *schema.ResourceData, meta i
return err
}

func resourceGithubActionsEnvironmentSecretImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client := meta.(*Owner).v3client
owner := meta.(*Owner).name
ctx := context.Background()

parts := strings.Split(d.Id(), "/")
if len(parts) != 3 {
return nil, fmt.Errorf("invalid ID specified: supplied ID must be written as <repository>/<environment>/<secret_name>")
}

d.SetId(buildThreePartID(parts[0], parts[1], parts[2]))

repoName, envName, secretName, err := parseThreePartID(d.Id(), "repository", "environment", "secret_name")
if err != nil {
return nil, err
}

repo, _, err := client.Repositories.Get(ctx, owner, repoName)

secret, _, err := client.Actions.GetEnvSecret(ctx, int(repo.GetID()), escapedEnvName, secretName)
if err != nil {
return nil, err
}

d.Set("repository", repoName)
d.Set("secret_name", secretName)
d.Set("environment", envName)

// encrypted_value or plaintext_value can not be imported

d.Set("created_at", secret.CreatedAt.String())
d.Set("updated_at", secret.UpdatedAt.String())

return []*schema.ResourceData{d}, nil
}

func getEnvironmentPublicKeyDetails(repoID int64, envName string, meta interface{}) (keyId, pkValue string, err error) {
client := meta.(*Owner).v3client
ctx := context.Background()
Expand Down
55 changes: 55 additions & 0 deletions github/resource_github_actions_environment_secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,59 @@ func TestAccGithubActionsEnvironmentSecret(t *testing.T) {

})

t.Run("imports secret without error", func(t *testing.T) {
secretValue := "super_secret_value"
envName := "environment / test"
secretName := "test_plaintext_secret_name"
secretValue := "secret_value"

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "tf-acc-test-%s"
}

resource "github_repository_environment" "test" {
repository = github_repository.test.name
environment = "%s"
}

resource "github_actions_environment_secret" "secret" {
repository = github_repository.test.name
environment = github_repository_environment.test.environment
secret_name = "%s"
plaintext_value = "%s"
}
`, randomID, envName, secretName, secretValue)

testCase := func(t *testing.T, mode string) {
resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, mode) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
},
{
ResourceName: "github_actions_environment_secret.secret",
ImportStateId: fmt.Sprintf(`tf-acc-test-%s:%s:%s`, randomID, envName, secretName),
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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)
})

})
}
24 changes: 15 additions & 9 deletions website/docs/r/actions_environment_secret.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,24 @@ resource "github_actions_environment_secret" "test_secret" {

The following arguments are supported:


* `repository` - (Required) Name of the repository.
* `environment` - (Required) Name of the environment.
* `secret_name` - (Required) Name of the secret.
* `encrypted_value` - (Optional) Encrypted value of the secret using the GitHub public key in Base64 format.
* `plaintext_value` - (Optional) Plaintext value of the secret to be encrypted.
- `repository` - (Required) Name of the repository.
- `environment` - (Required) Name of the environment.
- `secret_name` - (Required) Name of the secret.
- `encrypted_value` - (Optional) Encrypted value of the secret using the GitHub public key in Base64 format.
- `plaintext_value` - (Optional) Plaintext value of the secret to be encrypted.

## Attributes Reference

* `created_at` - Date of actions_environment_secret creation.
* `updated_at` - Date of actions_environment_secret update.
- `created_at` - Date of actions_environment_secret creation.
- `updated_at` - Date of actions_environment_secret update.

## Import

This resource does not support importing. If you'd like to help contribute it, please visit our [GitHub page](https://github.com/integrations/terraform-provider-github)!
This resource can be imported using an ID made up of the `repository`, `environment` and `secret_name`:

```
$ terraform import github_actions_secret.example_secret <repository>/<environment>/<secret_name>
```

NOTE: the implementation is limited in that it won't fetch the value of the
`plaintext_value` or `encrypted_value` fields when importing. You may need to ignore changes for these as a workaround.