From 91f38413db5706d401878e1d494d9bcde7e7f4ca Mon Sep 17 00:00:00 2001 From: Alex Dancho Date: Fri, 25 Mar 2022 17:16:58 -0400 Subject: [PATCH] Add a data source for refs. (#1084) Co-authored-by: Keegan Campbell --- github/data_source_github_ref.go | 67 ++++++++++++++++ github/data_source_github_ref_test.go | 109 ++++++++++++++++++++++++++ github/provider.go | 1 + website/docs/d/ref.html.markdown | 35 +++++++++ website/github.erb | 3 + 5 files changed, 215 insertions(+) create mode 100644 github/data_source_github_ref.go create mode 100644 github/data_source_github_ref_test.go create mode 100644 website/docs/d/ref.html.markdown diff --git a/github/data_source_github_ref.go b/github/data_source_github_ref.go new file mode 100644 index 0000000000..3fcca6b453 --- /dev/null +++ b/github/data_source_github_ref.go @@ -0,0 +1,67 @@ +package github + +import ( + "context" + "log" + "net/http" + + "github.com/google/go-github/v42/github" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceGithubRef() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGithubRefRead, + + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "branch": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "etag": { + Type: schema.TypeString, + Computed: true, + }, + "ref": { + Type: schema.TypeString, + Computed: true, + }, + "sha": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGithubRefRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*Owner).v3client + orgName := meta.(*Owner).name + repoName := d.Get("repository").(string) + ref := d.Get("ref").(string) + + refData, resp, err := client.Git.GetRef(context.TODO(), orgName, repoName, ref) + if err != nil { + if err, ok := err.(*github.ErrorResponse); ok { + if err.Response.StatusCode == http.StatusNotFound { + log.Printf("[DEBUG] Missing GitHub ref %s/%s (%s)", orgName, repoName, ref) + d.SetId("") + return nil + } + } + return err + } + + d.SetId(buildTwoPartID(repoName, ref)) + d.Set("etag", resp.Header.Get("ETag")) + d.Set("ref", *refData.Ref) + d.Set("sha", *refData.Object.SHA) + + return nil +} diff --git a/github/data_source_github_ref_test.go b/github/data_source_github_ref_test.go new file mode 100644 index 0000000000..0928e05866 --- /dev/null +++ b/github/data_source_github_ref_test.go @@ -0,0 +1,109 @@ +package github + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccGithubRefDataSource(t *testing.T) { + + randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum) + + t.Run("queries an existing ref without error", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-%[1]s" + auto_init = true + } + + data "github_ref" "test" { + repository = github_repository.test.id + ref = "/heads/main" + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestMatchResourceAttr( + "data.github_ref.test", "id", regexp.MustCompile(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, + 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("queries an invalid ref without error", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-%[1]s" + auto_init = true + } + + data "github_ref" "test" { + repository = github_repository.test.id + ref = "heads/xxxxxx" + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr( + "data.github_ref.test", "id", + ), + ) + + 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) + }) + + }) +} diff --git a/github/provider.go b/github/provider.go index 84d54f67d6..243dcf8bdb 100644 --- a/github/provider.go +++ b/github/provider.go @@ -137,6 +137,7 @@ func Provider() terraform.ResourceProvider { "github_organization": dataSourceGithubOrganization(), "github_organization_team_sync_groups": dataSourceGithubOrganizationTeamSyncGroups(), "github_organization_teams": dataSourceGithubOrganizationTeams(), + "github_ref": dataSourceGithubRef(), "github_release": dataSourceGithubRelease(), "github_repositories": dataSourceGithubRepositories(), "github_repositories_v2": dataSourceGithubRepositoriesV2(), diff --git a/website/docs/d/ref.html.markdown b/website/docs/d/ref.html.markdown new file mode 100644 index 0000000000..b8dcde89b3 --- /dev/null +++ b/website/docs/d/ref.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "github" +page_title: "GitHub: github_ref" +description: |- + Get information about a repository ref. +--- + +# github\ref + +Use this data source to retrieve information about a repository ref. + +## Example Usage + +```hcl +data "github_ref" "development" { + repository = "example" + ref = "heads/development" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `repository` - (Required) The GitHub repository name. + +* `ref` - (Required) The repository ref to look up. Must be formatted `heads/` for branches, and `tags/` for tags. + +## Attribute Reference + +The following additional attributes are exported: + +* `etag` - An etag representing the ref. + +* `sha` - A string storing the reference's `HEAD` commit's SHA1. diff --git a/website/github.erb b/website/github.erb index fb679d860f..4e971bff46 100644 --- a/website/github.erb +++ b/website/github.erb @@ -37,6 +37,9 @@
  • github_organization_teams
  • +
  • + github_ref +
  • github_release