From da2d6b9c43bff987930251f1f88b3e5f14b87ed8 Mon Sep 17 00:00:00 2001 From: Mars Hall Date: Tue, 25 Jul 2023 20:15:33 -0700 Subject: [PATCH] App data source gets last successful Release & Slug IDs (#376) * App data source now provides the app's last successful Release ID & Slug ID * Fix broken add-on tests to use Heroku add-on instead of 3rd party --- docs/data-sources/app.md | 4 +++ heroku/data_source_heroku_app.go | 33 ++++++++++++++++++ heroku/data_source_heroku_app_test.go | 49 +++++++++++++++++++++++++++ heroku/resource_heroku_addon_test.go | 16 ++++----- 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/docs/data-sources/app.md b/docs/data-sources/app.md index d91082a6..576040a9 100644 --- a/docs/data-sources/app.md +++ b/docs/data-sources/app.md @@ -53,6 +53,10 @@ The following attributes are exported: * `heroku_hostname` - The hostname for the Heroku application, suitable for pointing DNS records. +* `last_release_id` - The last successful Release ID for the app. May be empty. + +* `last_slug_id` - The Slug ID from the last successful release. May be empty. + * `config_vars` - A map of all configuration variables for the app. * `acm` - True if Heroku ACM is enabled for this app, false otherwise. diff --git a/heroku/data_source_heroku_app.go b/heroku/data_source_heroku_app.go index 5ce81b9b..99527782 100644 --- a/heroku/data_source_heroku_app.go +++ b/heroku/data_source_heroku_app.go @@ -1,7 +1,11 @@ package heroku import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + heroku "github.com/heroku/heroku-go/v5" ) func dataSourceHerokuApp() *schema.Resource { @@ -69,6 +73,16 @@ func dataSourceHerokuApp() *schema.Resource { Computed: true, }, + "last_release_id": { + Type: schema.TypeString, + Computed: true, + }, + + "last_slug_id": { + Type: schema.TypeString, + Computed: true, + }, + "organization": { Type: schema.TypeList, Computed: true, @@ -126,5 +140,24 @@ func dataSourceHerokuAppRead(d *schema.ResourceData, m interface{}) error { d.Set("buildpacks", app.Buildpacks) d.Set("config_vars", app.Vars) + releaseRange := heroku.ListRange{ + Field: "version", + Max: 200, + Descending: true, + } + releases, err := client.ReleaseList(context.Background(), app.App.ID, &releaseRange) + if err != nil { + return fmt.Errorf("Failed to fetch releases for app '%s': %s", name, err) + } + for _, r := range releases { + if r.Status == "succeeded" { + d.Set("last_release_id", r.ID) + if r.Slug != nil { + d.Set("last_slug_id", r.Slug.ID) + } + break + } + } + return nil } diff --git a/heroku/data_source_heroku_app_test.go b/heroku/data_source_heroku_app_test.go index a911ade4..6332241f 100644 --- a/heroku/data_source_heroku_app_test.go +++ b/heroku/data_source_heroku_app_test.go @@ -40,6 +40,26 @@ func TestAccDatasourceHerokuApp_Basic(t *testing.T) { }) } +func TestAccDatasourceHerokuApp_ReleaseIDAndSlugID(t *testing.T) { + appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckHerokuAppWithDatasource_slugRelease(appName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.heroku_app.foobar", "last_release_id"), + resource.TestCheckResourceAttrSet( + "data.heroku_app.foobar", "last_slug_id"), + ), + }, + }, + }) +} + func TestAccDatasourceHerokuApp_Organization(t *testing.T) { appName := fmt.Sprintf("tftest-%s", acctest.RandString(10)) org := os.Getenv("HEROKU_SPACES_ORGANIZATION") @@ -108,6 +128,35 @@ data "heroku_app" "foobar" { `, appName) } +func testAccCheckHerokuAppWithDatasource_slugRelease(appName string) string { + return fmt.Sprintf(` +resource "heroku_app" "foobar" { + name = "%s" + region = "us" +} + +resource "heroku_slug" "foobar" { + app_id = heroku_app.foobar.id + buildpack_provided_description = "Ruby" + file_path = "test-fixtures/slug.tgz" + process_types = { + web = "ruby server.rb" + } +} + +resource "heroku_app_release" "foobar" { + app_id = heroku_app.foobar.id + slug_id = heroku_slug.foobar.id +} + +data "heroku_app" "foobar" { + name = "${heroku_app.foobar.name}" + + depends_on = [heroku_app_release.foobar] +} +`, appName) +} + func testAccCheckHerokuApp_organization(appName, orgName string) string { return fmt.Sprintf(` resource "heroku_app" "foobar" { diff --git a/heroku/resource_heroku_addon_test.go b/heroku/resource_heroku_addon_test.go index a8c2a963..0e1e166e 100644 --- a/heroku/resource_heroku_addon_test.go +++ b/heroku/resource_heroku_addon_test.go @@ -50,22 +50,22 @@ func TestAccHerokuAddon_noPlan(t *testing.T) { Config: testAccCheckHerokuAddonConfig_no_plan(appName), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuAddonExists("heroku_addon.foobar", &addon), - testAccCheckHerokuAddonPlan(&addon, "memcachier:dev"), + testAccCheckHerokuAddonPlan(&addon, "heroku-postgresql:mini"), resource.TestCheckResourceAttrSet( "heroku_addon.foobar", "app_id"), resource.TestCheckResourceAttr( - "heroku_addon.foobar", "plan", "memcachier"), + "heroku_addon.foobar", "plan", "heroku-postgresql:mini"), ), }, { Config: testAccCheckHerokuAddonConfig_no_plan(appName), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuAddonExists("heroku_addon.foobar", &addon), - testAccCheckHerokuAddonPlan(&addon, "memcachier:dev"), + testAccCheckHerokuAddonPlan(&addon, "heroku-postgresql:mini"), resource.TestCheckResourceAttrSet( "heroku_addon.foobar", "app_id"), resource.TestCheckResourceAttr( - "heroku_addon.foobar", "plan", "memcachier"), + "heroku_addon.foobar", "plan", "heroku-postgresql:mini"), ), }, }, @@ -123,11 +123,11 @@ func TestAccHerokuAddon_CustomName(t *testing.T) { Config: testAccCheckHerokuAddonConfig_CustomName(appName, customName), Check: resource.ComposeTestCheckFunc( testAccCheckHerokuAddonExists("heroku_addon.foobar", &addon), - testAccCheckHerokuAddonPlan(&addon, "memcachier:dev"), + testAccCheckHerokuAddonPlan(&addon, "heroku-postgresql:mini"), resource.TestCheckResourceAttrSet( "heroku_addon.foobar", "app_id"), resource.TestCheckResourceAttr( - "heroku_addon.foobar", "plan", "memcachier"), + "heroku_addon.foobar", "plan", "heroku-postgresql:mini"), resource.TestCheckResourceAttr( "heroku_addon.foobar", "name", customName), ), @@ -357,7 +357,7 @@ resource "heroku_app" "foobar" { resource "heroku_addon" "foobar" { app_id = heroku_app.foobar.id - plan = "memcachier" + plan = "heroku-postgresql:mini" }`, appName) } @@ -370,7 +370,7 @@ resource "heroku_app" "foobar" { resource "heroku_addon" "foobar" { app_id = heroku_app.foobar.id - plan = "memcachier" + plan = "heroku-postgresql:mini" name = "%s" }`, appName, customAddonName) }