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

Add support for repository alphanumeric autolinks (Fixes #1270) #1314

Merged
merged 8 commits into from Oct 31, 2022
30 changes: 19 additions & 11 deletions github/resource_github_repository_autolink_reference.go
Expand Up @@ -2,10 +2,8 @@ package github

import (
"context"
"fmt"
"regexp"
"strconv"
"strings"

"github.com/google/go-github/v47/github"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand All @@ -20,12 +18,12 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {

Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid ID specified. Supplied ID must be written as <repository>/<autolink_reference_id>")
repoName, autolinkRefID, err := parseTwoPartID(d.Id(), "repository", "autolink_reference_id")
if err != nil {
return nil, err
}
d.Set("repository", parts[0])
d.SetId(parts[1])
d.Set("repository", repoName)
d.SetId(autolinkRefID)
douglascayers marked this conversation as resolved.
Show resolved Hide resolved
return []*schema.ResourceData{d}, nil
},
},
Expand All @@ -41,15 +39,22 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
"key_prefix": {
Type: schema.TypeString,
Required: true,
Description: "This prefix appended by a number will generate a link any time it is found in an issue, pull request, or commit",
ForceNew: true,
Description: "This prefix appended by a number will generate a link any time it is found in an issue, pull request, or commit",
},
"target_url_template": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The template of the target URL used for the links; must be a valid URL and contain `<num>` for the reference number",
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^http[s]?:\/\/[a-z0-9-.]*\/.*?<num>.*?$`), "must be a valid URL and contain <num> token"),
ForceNew: true,
},
"is_alphanumeric": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_alphanumeric is optional in the API and defaults to true

Description: "Whether this autolink reference matches alphanumeric characters. If false, this autolink reference only matches numeric characters.",
},
"etag": {
Type: schema.TypeString,
Expand All @@ -66,11 +71,13 @@ func resourceGithubRepositoryAutolinkReferenceCreate(d *schema.ResourceData, met
repoName := d.Get("repository").(string)
keyPrefix := d.Get("key_prefix").(string)
targetURLTemplate := d.Get("target_url_template").(string)
isAlphanumeric := d.Get("is_alphanumeric").(bool)
ctx := context.Background()

opts := &github.AutolinkOptions{
KeyPrefix: &keyPrefix,
URLTemplate: &targetURLTemplate,
KeyPrefix: &keyPrefix,
URLTemplate: &targetURLTemplate,
IsAlphanumeric: &isAlphanumeric,
}

autolinkRef, _, err := client.Repositories.AddAutolink(ctx, owner, repoName, opts)
Expand Down Expand Up @@ -106,6 +113,7 @@ func resourceGithubRepositoryAutolinkReferenceRead(d *schema.ResourceData, meta
d.Set("repository", repoName)
d.Set("key_prefix", autolinkRef.KeyPrefix)
d.Set("target_url_template", autolinkRef.URLTemplate)
d.Set("is_alphanumeric", autolinkRef.IsAlphanumeric)

return nil
}
Expand Down
155 changes: 130 additions & 25 deletions github/resource_github_repository_autolink_reference_test.go
Expand Up @@ -15,25 +15,65 @@ func TestAccGithubRepositoryAutolinkReference(t *testing.T) {
t.Run("creates repository autolink reference without error", func(t *testing.T) {

config := fmt.Sprintf(`
resource "github_repository" "oof" {
name = "oof-%s"
description = "Test autolink creation"
resource "github_repository" "test" {
name = "test-%s"
description = "Test autolink creation"
}

resource "github_repository_autolink_reference" "autolink" {
repository = github_repository.oof.name
resource "github_repository_autolink_reference" "autolink_default" {
repository = github_repository.test.name

key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
key_prefix = "TEST1-"
target_url_template = "https://example.com/TEST-<num>"
}

resource "github_repository_autolink_reference" "autolink_alphanumeric" {
repository = github_repository.test.name

key_prefix = "TEST2-"
target_url_template = "https://example.com/TEST-<num>"
is_alphanumeric = true
}

resource "github_repository_autolink_reference" "autolink_numeric" {
repository = github_repository.test.name

key_prefix = "TEST3-"
target_url_template = "https://example.com/TEST-<num>"
is_alphanumeric = false
}
`, randomID)

check := resource.ComposeTestCheckFunc(
// autolink_default
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "key_prefix", "TEST1-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "is_alphanumeric", "true",
),
// autolink_alphanumeric
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_alphanumeric", "key_prefix", "TEST2-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink", "key_prefix", "OOF-",
"github_repository_autolink_reference.autolink_alphanumeric", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink", "target_url_template", "https://awesome.com/find/OOF-<num>",
"github_repository_autolink_reference.autolink_alphanumeric", "is_alphanumeric", "true",
),
// autolink_numeric
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "key_prefix", "TEST3-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "is_alphanumeric", "false",
),
)

Expand Down Expand Up @@ -67,32 +107,97 @@ func TestAccGithubRepositoryAutolinkReference(t *testing.T) {
t.Run("imports repository autolink reference without error", func(t *testing.T) {

config := fmt.Sprintf(`
resource "github_repository" "oof" {
name = "oof-%s"
description = "Test autolink creation"
resource "github_repository" "test" {
name = "test-%s"
description = "Test autolink creation"
}

resource "github_repository_autolink_reference" "autolink_default" {
repository = github_repository.test.name

key_prefix = "TEST1-"
target_url_template = "https://example.com/TEST-<num>"
}

resource "github_repository_autolink_reference" "autolink" {
repository = github_repository.oof.name
resource "github_repository_autolink_reference" "autolink_alphanumeric" {
repository = github_repository.test.name

key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
key_prefix = "TEST2-"
target_url_template = "https://example.com/TEST-<num>"
is_alphanumeric = true
}

resource "github_repository_autolink_reference" "autolink_numeric" {
repository = github_repository.test.name

key_prefix = "TEST3-"
target_url_template = "https://example.com/TEST-<num>"
is_alphanumeric = false
}
`, randomID)

check := resource.ComposeTestCheckFunc(
// autolink_default
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "key_prefix", "TEST1-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_default", "is_alphanumeric", "true",
),
// autolink_alphanumeric
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_alphanumeric", "key_prefix", "TEST2-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_alphanumeric", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_alphanumeric", "is_alphanumeric", "true",
),
// autolink_numeric
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "key_prefix", "TEST3-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "target_url_template", "https://example.com/TEST-<num>",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink_numeric", "is_alphanumeric", "false",
),
)

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: check,
},
// autolink_default
{
ResourceName: "github_repository_autolink_reference.autolink_default",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("test-%s:", randomID),
},
// autolink_alphanumeric
{
ResourceName: "github_repository_autolink_reference.autolink_alphanumeric",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("test-%s:", randomID),
},
// autolink_numeric
{
ResourceName: "github_repository_autolink_reference.autolink",
ResourceName: "github_repository_autolink_reference.autolink_numeric",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("oof-%s/", randomID),
ImportStateIdPrefix: fmt.Sprintf("test-%s:", randomID),
},
},
})
Expand All @@ -115,16 +220,16 @@ func TestAccGithubRepositoryAutolinkReference(t *testing.T) {
t.Run("deletes repository autolink reference without error", func(t *testing.T) {

config := fmt.Sprintf(`
resource "github_repository" "oof" {
name = "oof-%s"
description = "Test autolink creation"
resource "github_repository" "test" {
name = "test-%s"
description = "Test autolink creation"
}

resource "github_repository_autolink_reference" "autolink" {
repository = github_repository.oof.name
resource "github_repository_autolink_reference" "autolink_default" {
repository = github_repository.test.name

key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
key_prefix = "TEST1-"
target_url_template = "https://example.com/TEST-<num>"
}
`, randomID)

Expand Down
14 changes: 9 additions & 5 deletions website/docs/r/repository_autolink_reference.html.markdown
Expand Up @@ -13,18 +13,18 @@ This resource allows you to create and manage an autolink reference for a single

```hcl
resource "github_repository" "repo" {
name = "oof"
name = "my-repo"
description = "GitHub repo managed by Terraform"

private = false
}

resource "github_repository_autolink_reference" "auto" {
resource "github_repository_autolink_reference" "autolink" {
repository = github_repository.repo.name

key_prefix = "TICKET-"

target_url_template = "https://hello.there/TICKET?query=<num>"
target_url_template = "https://example.com/TICKET?query=<num>"
}
```

Expand All @@ -38,6 +38,8 @@ The following arguments are supported:

* `target_url_template` - (Required) The template of the target URL used for the links; must be a valid URL and contain `<num>` for the reference number

* `is_alphanumeric` - (Optional) Whether this autolink reference matches alphanumeric characters. If false, this autolink reference only matches numeric characters. Default is true.

## Attributes Reference

The following additional attributes are exported:
Expand All @@ -46,8 +48,10 @@ The following additional attributes are exported:

## Import

Autolink references can be imported using the `name` of the repository, combined with the `id` of the autolink reference and a `/` character for separating components, e.g.
Autolink references can be imported using the `name` of the repository, combined with the `id` of the autolink reference and a `:` character for separating components, e.g.

```sh
terraform import github_repository_autolink_reference.auto oof/123
terraform import github_repository_autolink_reference.auto my-repo:123
```

See the GitHub documentation for how to [list all autolinks of a repository](https://docs.github.com/en/rest/repos/autolinks#list-all-autolinks-of-a-repository) to learn the autolink ids to use with the import command.