From 182faef042b2ce1cb0dc1120748ec8fd472f04a4 Mon Sep 17 00:00:00 2001 From: Alex Dancho Date: Sun, 13 Feb 2022 16:24:22 -0500 Subject: [PATCH] Allow for retrieving latest prerelease as data source. --- github/data_source_github_release.go | 33 ++++++++++++++++- github/data_source_github_release_test.go | 44 +++++++++++++++++++++++ github/provider_utils.go | 3 ++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/github/data_source_github_release.go b/github/data_source_github_release.go index 08f790b3ea..97b8db9322 100644 --- a/github/data_source_github_release.go +++ b/github/data_source_github_release.go @@ -30,6 +30,7 @@ func dataSourceGithubRelease() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ + "latest_prerelease", "latest", "id", "tag", @@ -108,8 +109,38 @@ func dataSourceGithubReleaseRead(d *schema.ResourceData, meta interface{}) error var err error var release *github.RepositoryRelease - switch retrieveBy := strings.ToLower(d.Get("retrieve_by").(string)); retrieveBy { + case "latest_prerelease": + // The GitHub API doesn't specify a way to just load the most recent prerelease, + // so we'll load all releases and determine which one is the most recent + // prerelease after. + log.Printf("[INFO] Refreshing GitHub latest prerelease from repository %s", repository) + var releases []*github.RepositoryRelease + nextPage := 1 + // TODO: 10 is sort of arbitrary here -- what's the best way to allow configurability + // for this to prevent the provider from becoming glacially slow on large repos? + for nextPage < 10 { + opt := &github.ListOptions{Page: nextPage} + var response *github.Response + releases, response, err = client.Repositories.ListReleases(ctx, owner, repository, opt) + for _, rel := range releases { + if *rel.Prerelease != true || *rel.Draft == true { + continue + } + if release == nil { + release = rel + } else { + if rel.PublishedAt.After(release.PublishedAt.Time) { + release = rel + } + } + } + if response.NextPage > nextPage { + nextPage = response.NextPage + } else { + break + } + } case "latest": log.Printf("[INFO] Refreshing GitHub latest release from repository %s", repository) release, _, err = client.Repositories.GetLatestRelease(ctx, owner, repository) diff --git a/github/data_source_github_release_test.go b/github/data_source_github_release_test.go index eae10c0f0a..5179684228 100644 --- a/github/data_source_github_release_test.go +++ b/github/data_source_github_release_test.go @@ -13,6 +13,7 @@ func TestAccGithubReleaseDataSource(t *testing.T) { testReleaseRepository := os.Getenv("GITHUB_TEMPLATE_REPOSITORY") testReleaseID := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ID") + testPrereleaseID := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_PRERELEASE_ID") testReleaseOwner := testOrganizationFunc() t.Run("queries latest release", func(t *testing.T) { @@ -58,6 +59,49 @@ func TestAccGithubReleaseDataSource(t *testing.T) { }) + t.Run("queries latest prerelease", func(t *testing.T) { + + config := fmt.Sprintf(` + data "github_release" "test" { + repository = "%s" + owner = "%s" + retrieve_by = "latest_prerelease" + } + `, testReleaseRepository, testReleaseOwner) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.github_release.test", "id", testPrereleaseID, + ), + ) + + 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) { + testCase(t, anonymous) + }) + + 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 release by ID or tag", func(t *testing.T) { config := fmt.Sprintf(` diff --git a/github/provider_utils.go b/github/provider_utils.go index 3672c7508d..b79e46570a 100644 --- a/github/provider_utils.go +++ b/github/provider_utils.go @@ -33,6 +33,9 @@ func testAccPreCheck(t *testing.T) { if v := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ID"); v == "" { t.Fatal("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ID must be set for acceptance tests") } + if v := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_PRERELEASE_ID"); v == "" { + t.Fatal("GITHUB_TEMPLATE_REPOSITORY_PRERELEASE_ID must be set for acceptance tests") + } } func skipUnlessMode(t *testing.T, providerMode string) {