Skip to content
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
114 changes: 80 additions & 34 deletions github/resource_github_repository_autolink_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ import (
"context"
"errors"
"fmt"
"log"
"net/http"
"regexp"
"strconv"
"strings"

"github.com/google/go-github/v83/github"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func resourceGithubRepositoryAutolinkReference() *schema.Resource {
return &schema.Resource{
Create: resourceGithubRepositoryAutolinkReferenceCreate,
Read: resourceGithubRepositoryAutolinkReferenceRead,
Delete: resourceGithubRepositoryAutolinkReferenceDelete,
CreateContext: resourceGithubRepositoryAutolinkReferenceCreate,
UpdateContext: resourceGithubRepositoryAutolinkReferenceUpdate,
ReadContext: resourceGithubRepositoryAutolinkReferenceRead,
DeleteContext: resourceGithubRepositoryAutolinkReferenceDelete,

Importer: &schema.ResourceImporter{
StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {
Expand All @@ -31,15 +33,15 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
repository := parts[0]
id := parts[1]

client := meta.(*Owner).v3client
owner := meta.(*Owner).name

// If the second part of the provided ID isn't an integer, assume that the
// caller provided the key prefix for the autolink reference, and look up
// the autolink by the key prefix.

_, err := strconv.Atoi(id)
if err != nil {
client := meta.(*Owner).v3client
owner := meta.(*Owner).name

autolink, err := getAutolinkByKeyPrefix(ctx, client, owner, repository, id)
if err != nil {
return nil, err
Expand All @@ -48,22 +50,38 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
id = strconv.FormatInt(*autolink.ID, 10)
}

d.SetId(id)

repo, _, err := client.Repositories.Get(ctx, owner, repository)
if err != nil {
return nil, fmt.Errorf("failed to retrieve repository %s: %w", repository, err)
}

if err = d.Set("repository", repository); err != nil {
return nil, err
}
d.SetId(id)
if err = d.Set("repository_id", int(repo.GetID())); err != nil {
return nil, err
}

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

CustomizeDiff: diffRepository,

SchemaVersion: 1,
Schema: map[string]*schema.Schema{
"repository": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The repository name",
},
"repository_id": {
Type: schema.TypeInt,
Computed: true,
Description: "The ID of the GitHub repository.",
},
"key_prefix": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -92,15 +110,15 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
}
}

func resourceGithubRepositoryAutolinkReferenceCreate(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
func resourceGithubRepositoryAutolinkReferenceCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client
owner := meta.name

owner := meta.(*Owner).name
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,
Expand All @@ -110,23 +128,35 @@ func resourceGithubRepositoryAutolinkReferenceCreate(d *schema.ResourceData, met

autolinkRef, _, err := client.Repositories.AddAutolink(ctx, owner, repoName, opts)
if err != nil {
return err
return diag.FromErr(err)
}
d.SetId(strconv.FormatInt(autolinkRef.GetID(), 10))

return resourceGithubRepositoryAutolinkReferenceRead(d, meta)
repo, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return diag.FromErr(err)
}

if err := d.Set("repository_id", int(repo.GetID())); err != nil {
return diag.FromErr(err)
}

return resourceGithubRepositoryAutolinkReferenceRead(ctx, d, m)
}

func resourceGithubRepositoryAutolinkReferenceRead(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
func resourceGithubRepositoryAutolinkReferenceRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
ctx = tflog.SetField(ctx, "id", d.Id())

meta := m.(*Owner)
client := meta.v3client
owner := meta.name

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)
return diag.FromErr(unconvertibleIdErr(d.Id(), err))
}
ctx := context.WithValue(context.Background(), ctxId, d.Id())

if !d.IsNewResource() {
ctx = context.WithValue(ctx, ctxEtag, d.Get("etag").(string))
}
Expand All @@ -136,44 +166,60 @@ func resourceGithubRepositoryAutolinkReferenceRead(d *schema.ResourceData, meta
var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) {
if ghErr.Response.StatusCode == http.StatusNotFound {
log.Printf("[INFO] Removing autolink reference for repository %s/%s from state because it no longer exists in GitHub",
owner, repoName)
tflog.Info(ctx, "Autolink reference not found, removing from state.", map[string]any{
"owner": owner,
"repository": repoName,
})
d.SetId("")
return nil
}
}
return err
return diag.FromErr(err)
}

// Set resource fields
d.SetId(strconv.FormatInt(autolinkRef.GetID(), 10))
if err = d.Set("repository", repoName); err != nil {
return err
return diag.FromErr(err)
}
if err = d.Set("key_prefix", autolinkRef.KeyPrefix); err != nil {
return err
return diag.FromErr(err)
}
if err = d.Set("target_url_template", autolinkRef.URLTemplate); err != nil {
return err
return diag.FromErr(err)
}
if err = d.Set("is_alphanumeric", autolinkRef.IsAlphanumeric); err != nil {
return err
return diag.FromErr(err)
}

return nil
}

func resourceGithubRepositoryAutolinkReferenceDelete(d *schema.ResourceData, meta any) error {
client := meta.(*Owner).v3client
func resourceGithubRepositoryAutolinkReferenceUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
tflog.Warn(ctx, "Update function of autolink reference. This should not be called. But it's necessary when 'repository' doesn't have `ForceNew`", map[string]any{
"repository": d.Get("repository"),
"repository_id": d.Get("repository_id"),
"id": d.Id(),
})
return nil
}

func resourceGithubRepositoryAutolinkReferenceDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
ctx = tflog.SetField(ctx, "id", d.Id())

meta := m.(*Owner)
client := meta.v3client
owner := meta.name

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)
return diag.FromErr(unconvertibleIdErr(d.Id(), err))
}
ctx := context.WithValue(context.Background(), ctxId, d.Id())

_, err = client.Repositories.DeleteAutolink(ctx, owner, repoName, autolinkRefID)
return err
if err != nil {
return diag.FromErr(err)
}

return nil
}
Loading