From dac6b1b4676c071de22b31673348b3cb40f58541 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 14 Dec 2024 06:48:55 -0500 Subject: [PATCH] feat: add github_release_asset data source This addresses issue #2513 and adds support for a `github_release_asset` data source. Example of passing acceptance tests: ``` $ GITHUB_ORGANIZATION=mdb GITHUB_OWNER=mdb GITHUB_TEMPLATE_REPOSITORY=terraputs GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_ID=206493547 GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_NAME=checksums.txt TF_ACC=1 go test -v ./... -run ^TestAccGithubReleaseAssetDataSource ? github.com/integrations/terraform-provider-github/v6 [no test files] === RUN TestAccGithubReleaseAssetDataSource === RUN TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID === RUN TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_anonymous_account provider_utils.go:51: GITHUB_TOKEN environment variable should be empty provider_utils.go:74: Skipping TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_anonymous_account which requires anonymous mode === RUN TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_individual_account === RUN TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_organization_account --- PASS: TestAccGithubReleaseAssetDataSource (5.20s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID (5.20s) --- SKIP: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_anonymous_account (0.00s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_individual_account (2.57s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_organization_account (2.62s) PASS ok github.com/integrations/terraform-provider-github/v6/github 5.688s ``` Signed-off-by: Mike Ball --- github/data_source_github_release_asset.go | 146 ++++++++++++++++++ .../data_source_github_release_asset_test.go | 64 ++++++++ github/provider.go | 1 + website/docs/d/release_asset.html.markdown | 84 ++++++++++ 4 files changed, 295 insertions(+) create mode 100644 github/data_source_github_release_asset.go create mode 100644 github/data_source_github_release_asset_test.go create mode 100644 website/docs/d/release_asset.html.markdown diff --git a/github/data_source_github_release_asset.go b/github/data_source_github_release_asset.go new file mode 100644 index 0000000000..8b6d76868f --- /dev/null +++ b/github/data_source_github_release_asset.go @@ -0,0 +1,146 @@ +package github + +import ( + "context" + "io" + "net/http" + "strconv" + "strings" + + "github.com/google/go-github/v66/github" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceGithubReleaseAsset() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGithubReleaseAssetRead, + + Schema: map[string]*schema.Schema{ + "asset_id": { + Type: schema.TypeInt, + Required: true, + }, + "owner": { + Type: schema.TypeString, + Required: true, + }, + "repository": { + Type: schema.TypeString, + Required: true, + }, + "body": { + Type: schema.TypeString, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + "node_id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "label": { + Type: schema.TypeString, + Computed: true, + }, + "content_type": { + Type: schema.TypeString, + Computed: true, + }, + "size": { + Type: schema.TypeInt, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + }, + "browser_download_url": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGithubReleaseAssetRead(d *schema.ResourceData, meta interface{}) error { + repository := d.Get("repository").(string) + owner := d.Get("owner").(string) + + client := meta.(*Owner).v3client + ctx := context.Background() + + var err error + var asset *github.ReleaseAsset + + assetID := int64(d.Get("asset_id").(int)) + asset, _, err = client.Repositories.GetReleaseAsset(ctx, owner, repository, assetID) + if err != nil { + return err + } + + var respBody io.ReadCloser + respBody, _, err = client.Repositories.DownloadReleaseAsset(ctx, owner, repository, assetID, http.DefaultClient) + if err != nil { + return err + } + + buf := new(strings.Builder) + _, err = io.Copy(buf, respBody) + if err != nil { + return err + } + + d.SetId(strconv.FormatInt(asset.GetID(), 10)) + err = d.Set("body", buf.String()) + if err != nil { + return err + } + err = d.Set("url", asset.URL) + if err != nil { + return err + } + err = d.Set("node_id", asset.NodeID) + if err != nil { + return err + } + err = d.Set("name", asset.Name) + if err != nil { + return err + } + err = d.Set("label", asset.Label) + if err != nil { + return err + } + err = d.Set("content_type", asset.ContentType) + if err != nil { + return err + } + err = d.Set("size", asset.Size) + if err != nil { + return err + } + err = d.Set("created_at", asset.CreatedAt.String()) + if err != nil { + return err + } + err = d.Set("created_at", asset.UpdatedAt.String()) + if err != nil { + return err + } + err = d.Set("browser_download_url", asset.BrowserDownloadURL) + if err != nil { + return err + } + + return nil +} diff --git a/github/data_source_github_release_asset_test.go b/github/data_source_github_release_asset_test.go new file mode 100644 index 0000000000..eb821184a7 --- /dev/null +++ b/github/data_source_github_release_asset_test.go @@ -0,0 +1,64 @@ +package github + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccGithubReleaseAssetDataSource(t *testing.T) { + + testReleaseRepository := os.Getenv("GITHUB_TEMPLATE_REPOSITORY") + testReleaseAssetID := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_ID") + testReleaseAssetName := os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_NAME") + testReleaseOwner := testOrganizationFunc() + + t.Run("queries specified asset ID", func(t *testing.T) { + + config := fmt.Sprintf(` + data "github_release_asset" "test" { + repository = "%s" + owner = "%s" + asset_id = "%s" + } + `, testReleaseRepository, testReleaseOwner, testReleaseAssetID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.github_release_asset.test", "asset_id", testReleaseAssetID, + ), + resource.TestCheckResourceAttr( + "data.github_release_asset.test", "name", testReleaseAssetName, + ), + ) + + 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) + }) + + }) + +} diff --git a/github/provider.go b/github/provider.go index a9a04d0474..d05eddff54 100644 --- a/github/provider.go +++ b/github/provider.go @@ -237,6 +237,7 @@ func Provider() *schema.Provider { "github_organization_webhooks": dataSourceGithubOrganizationWebhooks(), "github_ref": dataSourceGithubRef(), "github_release": dataSourceGithubRelease(), + "github_release_asset": dataSourceGithubReleaseAsset(), "github_repositories": dataSourceGithubRepositories(), "github_repository": dataSourceGithubRepository(), "github_repository_autolink_references": dataSourceGithubRepositoryAutolinkReferences(), diff --git a/website/docs/d/release_asset.html.markdown b/website/docs/d/release_asset.html.markdown new file mode 100644 index 0000000000..ee2dd6ba94 --- /dev/null +++ b/website/docs/d/release_asset.html.markdown @@ -0,0 +1,84 @@ +--- +layout: "github" +page_title: "GitHub: github_release_asset" +description: |- + Get information on a GitHub release asset. +--- + +# github\_release\_asset + +Use this data source to retrieve information about a GitHub release asset associated with a specific GitHub release. + +## Example Usage +To retrieve the latest release that is present in a repository: + +```hcl +data "github_release" "example" { + repository = "example-repository" + owner = "example-owner" + retrieve_by = "latest" +} +``` + +To retrieve a specific release asset from a repository based on its ID: + +```hcl +data "github_release_asset" "example" { + repository = "example-repository" + owner = "example-owner" + asset_id = 12345 +} +``` + +To retrieve the first release asset associated with the the latest release in a repository: + +```hcl +data "github_release" "example" { + repository = "example-repository" + owner = "example-owner" + retrieve_by = "latest" +} + +data "github_release_asset" "example" { + repository = "example-repository" + owner = "example-owner" + asset_id = data.github_release.example.assets[0].id +} +``` + +To retrieve all release assets associated with the the latest release in a repository: + +```hcl +data "github_release" "example" { + repository = "example-repository" + owner = "example-owner" + retrieve_by = "latest" +} + +data "github_release_asset" "example" { + count = length(data.github_release.example.assets) + repository = "example-repository" + owner = "example-owner" + asset_id = data.github_release.example.assets[count.index].id +} +``` + +## Argument Reference + +* `repository` - (Required) Name of the repository to retrieve the release from. +* `owner` - (Required) Owner of the repository. +* `asset_id` - (Required) ID of the release asset to retrieve. + +## Attributes Reference + +* `id` - ID of the asset +* `url` - URL of the asset +* `node_id` - Node ID of the asset +* `name` - The file name of the asset +* `label` - Label for the asset +* `content_type` - MIME type of the asset +* `size` - Size in byte +* `created_at` - Date the asset was created +* `updated_at` - Date the asset was last updated +* `browser_download_url` - Browser download URL +* `body` - The release asset body