Skip to content

Commit

Permalink
New resource github_repository_autolink_reference (#924)
Browse files Browse the repository at this point in the history
* Add resource github_repository_autolink_reference

* Add resource to provider main file

* Use correct resource name, thanks to @mrwacky42
  • Loading branch information
Rene Schach authored Oct 17, 2021
1 parent 9f305fb commit 534f002
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 0 deletions.
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func Provider() terraform.ResourceProvider {
"github_organization_webhook": resourceGithubOrganizationWebhook(),
"github_project_card": resourceGithubProjectCard(),
"github_project_column": resourceGithubProjectColumn(),
"github_repository_autolink_reference": resourceGithubRepositoryAutolinkReference(),
"github_repository_collaborator": resourceGithubRepositoryCollaborator(),
"github_repository_deploy_key": resourceGithubRepositoryDeployKey(),
"github_repository_environment": resourceGithubRepositoryEnvironment(),
Expand Down
128 changes: 128 additions & 0 deletions github/resource_github_repository_autolink_reference.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package github

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

"github.com/google/go-github/v39/github"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceGithubRepositoryAutolinkReference() *schema.Resource {
return &schema.Resource{
Create: resourceGithubRepositoryAutolinkReferenceCreate,
Read: resourceGithubRepositoryAutolinkReferenceRead,
Delete: resourceGithubRepositoryAutolinkReferenceDelete,

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>")
}
d.Set("repository", parts[0])
d.SetId(parts[1])
return []*schema.ResourceData{d}, nil
},
},

SchemaVersion: 1,
Schema: map[string]*schema.Schema{
"repository": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The repository name",
},
"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",
},
"target_url_template": {
Type: schema.TypeString,
Required: 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"),
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceGithubRepositoryAutolinkReferenceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client

owner := meta.(*Owner).name
repoName := d.Get("repository").(string)
keyPrefix := d.Get("key_prefix").(string)
targetURLTemplate := d.Get("target_url_template").(string)
ctx := context.Background()

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

log.Printf("[DEBUG] Creating repository autolink reference: %s -> %s (%s/%s)", keyPrefix, targetURLTemplate, owner, repoName)
autolinkRef, _, err := client.Repositories.AddAutolink(ctx, owner, repoName, opts)
if err != nil {
return err
}
d.SetId(strconv.FormatInt(autolinkRef.GetID(), 10))

return resourceGithubRepositoryAutolinkReferenceRead(d, meta)
}

func resourceGithubRepositoryAutolinkReferenceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client

owner := meta.(*Owner).name
repoName := d.Get("repository").(string)
autolinkRefID, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}
ctx := context.WithValue(context.Background(), ctxId, d.Id())
if !d.IsNewResource() {
ctx = context.WithValue(ctx, ctxEtag, d.Get("etag").(string))
}

log.Printf("[DEBUG] Reading repository autolink reference: %s (%s/%s)", d.Id(), owner, repoName)
autolinkRef, _, err := client.Repositories.GetAutolink(ctx, owner, repoName, autolinkRefID)
if err != nil {
return err
}

// Set resource fields
d.SetId(strconv.FormatInt(autolinkRef.GetID(), 10))
d.Set("repository", repoName)
d.Set("key_prefix", autolinkRef.KeyPrefix)
d.Set("target_url_template", autolinkRef.URLTemplate)

return nil
}

func resourceGithubRepositoryAutolinkReferenceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v3client

owner := meta.(*Owner).name
repoName := d.Get("repository").(string)
autolinkRefID, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}
ctx := context.WithValue(context.Background(), ctxId, d.Id())

log.Printf("[DEBUG] Deleting repository autolink reference: %s (%s/%s)", d.Id(), owner, repoName)
_, err = client.Repositories.DeleteAutolink(ctx, owner, repoName, autolinkRefID)
return err
}
156 changes: 156 additions & 0 deletions github/resource_github_repository_autolink_reference_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package github

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestAccGithubRepositoryAutolinkReference(t *testing.T) {

randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)

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_autolink_reference" "autolink" {
repository = github_repository.oof.name
key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
}
`, randomID)

check := resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink", "key_prefix", "OOF-",
),
resource.TestCheckResourceAttr(
"github_repository_autolink_reference.autolink", "target_url_template", "https://awesome.com/find/OOF-<num>",
),
)

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

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("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_autolink_reference" "autolink" {
repository = github_repository.oof.name
key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
}
`, randomID)

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_repository_autolink_reference.autolink",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("oof-%s/", randomID),
},
},
})
}

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 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_autolink_reference" "autolink" {
repository = github_repository.oof.name
key_prefix = "OOF-"
target_url_template = "https://awesome.com/find/OOF-<num>"
}
`, randomID)

testCase := func(t *testing.T, mode string) {
resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, mode) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Destroy: 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)
})
})
}
53 changes: 53 additions & 0 deletions website/docs/r/repository_autolink_reference.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
layout: "github"
page_title: "GitHub: github_repository_autolink_reference"
description: |-
Creates and manages autolink references for a single repository
---

# github_repository_autolink_reference

This resource allows you to create and manage an autolink reference for a single repository.

## Example Usage

```hcl
resource "github_repository" "repo" {
name = "oof"
description = "GitHub repo managed by Terraform"
private = false
}
resource "github_repository_autolink_reference" "auto" {
repository = github_repository.repo.name
key_prefix = "TICKET-"
target_url_template = "https://hello.there/TICKET?query=<num>"
}
```

## Argument Reference

The following arguments are supported:

* `repository` - (Required) The repository of the autolink reference.

* `key_prefix` - (Required) 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` - (Required) The template of the target URL used for the links; must be a valid URL and contain `<num>` for the reference number

## Attributes Reference

The following additional attributes are exported:

* `etag` - An etag representing the autolink reference object.

## 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.

```sh
terraform import github_repository_autolink_reference.auto oof/123
```
3 changes: 3 additions & 0 deletions website/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@
<li>
<a href="/docs/providers/github/r/repository.html">github_repository</a>
</li>
<li>
<a href="/docs/providers/github/r/repository_autolink_reference.html">github_repository_autolink_reference</a>
</li>
<li>
<a href="/docs/providers/github/r/repository_collaborator.html">github_repository_collaborator</a>
</li>
Expand Down

0 comments on commit 534f002

Please sign in to comment.