Skip to content

Commit 2407ae3

Browse files
committed
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=mterwill \ GITHUB_OWNER=mterwill \ 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 (11.65s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID (11.65s) --- SKIP: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_anonymous_account (0.00s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_individual_account (8.90s) --- PASS: TestAccGithubReleaseAssetDataSource/queries_specified_asset_ID/with_an_organization_account (2.75s) PASS ok github.com/integrations/terraform-provider-github/v6/github 12.434s ``` Signed-off-by: Mike Ball <mikedball@gmail.com>
1 parent 972ef3b commit 2407ae3

File tree

5 files changed

+335
-1
lines changed

5 files changed

+335
-1
lines changed

github/config.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ func (injector *previewHeaderInjectorTransport) RoundTrip(req *http.Request) (*h
189189
header := req.Header.Get(name)
190190
if header == "" {
191191
header = value
192-
} else {
192+
// NOTE: Some API endpoints expect a single Accept: application/octet-stream header.
193+
// If one has been set, it's necessary to preserve it as-is, without
194+
// appending previewHeaders value.
195+
// See https://github.com/google/go-github/pull/3392
196+
} else if !(strings.ToLower(name) == "accept" && header == "application/octet-stream") {
193197
header = strings.Join([]string{header, value}, ",")
194198
}
195199
req.Header.Set(name, header)
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"io"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/google/go-github/v67/github"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
)
13+
14+
func dataSourceGithubReleaseAsset() *schema.Resource {
15+
return &schema.Resource{
16+
Description: "Retrieve information about a GitHub release asset.",
17+
ReadContext: dataSourceGithubReleaseAssetRead,
18+
19+
Schema: map[string]*schema.Schema{
20+
"asset_id": {
21+
Type: schema.TypeInt,
22+
Required: true,
23+
Description: "ID of the release asset to retrieve",
24+
},
25+
"owner": {
26+
Type: schema.TypeString,
27+
Required: true,
28+
Description: "Owner of the repository",
29+
},
30+
"repository": {
31+
Type: schema.TypeString,
32+
Required: true,
33+
Description: "Name of the repository to retrieve the release asset from",
34+
},
35+
"body": {
36+
Type: schema.TypeString,
37+
Computed: true,
38+
Description: "The release asset body",
39+
},
40+
"url": {
41+
Type: schema.TypeString,
42+
Computed: true,
43+
Description: "URL of the asset",
44+
},
45+
"node_id": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
Description: "Node ID of the asset",
49+
},
50+
"name": {
51+
Type: schema.TypeString,
52+
Computed: true,
53+
Description: "File name of the asset",
54+
},
55+
"label": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
Description: "Label for the asset",
59+
},
60+
"content_type": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
Description: "MIME type of the asset",
64+
},
65+
"size": {
66+
Type: schema.TypeInt,
67+
Computed: true,
68+
Description: "Asset size in bytes",
69+
},
70+
"created_at": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
Description: "Date the asset was created",
74+
},
75+
"updated_at": {
76+
Type: schema.TypeString,
77+
Computed: true,
78+
Description: "Date the asset was updated",
79+
},
80+
"browser_download_url": {
81+
Type: schema.TypeString,
82+
Computed: true,
83+
Description: "Browser URL from which the release asset can be downloaded",
84+
},
85+
},
86+
}
87+
}
88+
89+
func dataSourceGithubReleaseAssetRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
90+
repository := d.Get("repository").(string)
91+
owner := d.Get("owner").(string)
92+
93+
client := meta.(*Owner).v3client
94+
95+
var err error
96+
var asset *github.ReleaseAsset
97+
98+
assetID := int64(d.Get("asset_id").(int))
99+
asset, _, err = client.Repositories.GetReleaseAsset(ctx, owner, repository, assetID)
100+
if err != nil {
101+
return diag.FromErr(err)
102+
}
103+
104+
var respBody io.ReadCloser
105+
clientCopy := client.Client()
106+
respBody, _, err = client.Repositories.DownloadReleaseAsset(ctx, owner, repository, assetID, clientCopy)
107+
if err != nil {
108+
return diag.FromErr(err)
109+
}
110+
defer respBody.Close()
111+
112+
buf := new(strings.Builder)
113+
_, err = io.Copy(buf, respBody)
114+
if err != nil {
115+
return diag.FromErr(err)
116+
}
117+
118+
d.SetId(strconv.FormatInt(asset.GetID(), 10))
119+
err = d.Set("body", buf.String())
120+
if err != nil {
121+
return diag.FromErr(err)
122+
}
123+
err = d.Set("url", asset.URL)
124+
if err != nil {
125+
return diag.FromErr(err)
126+
}
127+
err = d.Set("node_id", asset.NodeID)
128+
if err != nil {
129+
return diag.FromErr(err)
130+
}
131+
err = d.Set("name", asset.Name)
132+
if err != nil {
133+
return diag.FromErr(err)
134+
}
135+
err = d.Set("label", asset.Label)
136+
if err != nil {
137+
return diag.FromErr(err)
138+
}
139+
err = d.Set("content_type", asset.ContentType)
140+
if err != nil {
141+
return diag.FromErr(err)
142+
}
143+
err = d.Set("size", asset.Size)
144+
if err != nil {
145+
return diag.FromErr(err)
146+
}
147+
err = d.Set("created_at", asset.CreatedAt.String())
148+
if err != nil {
149+
return diag.FromErr(err)
150+
}
151+
err = d.Set("created_at", asset.UpdatedAt.String())
152+
if err != nil {
153+
return diag.FromErr(err)
154+
}
155+
err = d.Set("browser_download_url", asset.BrowserDownloadURL)
156+
if err != nil {
157+
return diag.FromErr(err)
158+
}
159+
160+
return nil
161+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package github
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
)
10+
11+
func TestAccGithubReleaseAssetDataSource(t *testing.T) {
12+
13+
testReleaseRepository := "go-github-issue-demo-1"
14+
if os.Getenv("GITHUB_TEMPLATE_REPOSITORY") != "" {
15+
testReleaseRepository = os.Getenv("GITHUB_TEMPLATE_REPOSITORY")
16+
}
17+
18+
testReleaseAssetID := "151970555"
19+
if os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_ID") != "" {
20+
testReleaseAssetID = os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_ID")
21+
}
22+
23+
testReleaseAssetName := "foo.txt"
24+
if os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_NAME") != "" {
25+
testReleaseAssetName = os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_NAME")
26+
}
27+
28+
testReleaseAssetContent := "Hello, world!\n"
29+
if os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_CONTENT") != "" {
30+
testReleaseAssetContent = os.Getenv("GITHUB_TEMPLATE_REPOSITORY_RELEASE_ASSET_CONTENT")
31+
}
32+
33+
testReleaseOwner := testOrganizationFunc()
34+
35+
t.Run("queries specified asset ID", func(t *testing.T) {
36+
37+
config := fmt.Sprintf(`
38+
data "github_release_asset" "test" {
39+
repository = "%s"
40+
owner = "%s"
41+
asset_id = "%s"
42+
}
43+
`, testReleaseRepository, testReleaseOwner, testReleaseAssetID)
44+
45+
check := resource.ComposeTestCheckFunc(
46+
resource.TestCheckResourceAttr(
47+
"data.github_release_asset.test", "asset_id", testReleaseAssetID,
48+
),
49+
resource.TestCheckResourceAttr(
50+
"data.github_release_asset.test", "name", testReleaseAssetName,
51+
),
52+
resource.TestCheckResourceAttr(
53+
"data.github_release_asset.test", "body", testReleaseAssetContent,
54+
),
55+
)
56+
57+
testCase := func(t *testing.T, mode string) {
58+
resource.Test(t, resource.TestCase{
59+
PreCheck: func() { skipUnlessMode(t, mode) },
60+
Providers: testAccProviders,
61+
Steps: []resource.TestStep{
62+
{
63+
Config: config,
64+
Check: check,
65+
},
66+
},
67+
})
68+
}
69+
70+
t.Run("with an anonymous account", func(t *testing.T) {
71+
testCase(t, anonymous)
72+
})
73+
74+
t.Run("with an individual account", func(t *testing.T) {
75+
testCase(t, individual)
76+
})
77+
78+
t.Run("with an organization account", func(t *testing.T) {
79+
testCase(t, organization)
80+
})
81+
82+
})
83+
84+
}

github/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ func Provider() *schema.Provider {
264264
"github_organization_webhooks": dataSourceGithubOrganizationWebhooks(),
265265
"github_ref": dataSourceGithubRef(),
266266
"github_release": dataSourceGithubRelease(),
267+
"github_release_asset": dataSourceGithubReleaseAsset(),
267268
"github_repositories": dataSourceGithubRepositories(),
268269
"github_repository": dataSourceGithubRepository(),
269270
"github_repository_autolink_references": dataSourceGithubRepositoryAutolinkReferences(),
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
layout: "github"
3+
page_title: "GitHub: github_release_asset"
4+
description: |-
5+
Get information on a GitHub release asset.
6+
---
7+
8+
# github\_release\_asset
9+
10+
Use this data source to retrieve information about a GitHub release asset.
11+
12+
## Example Usage
13+
To retrieve the latest release that is present in a repository:
14+
15+
```hcl
16+
data "github_release" "example" {
17+
repository = "example-repository"
18+
owner = "example-owner"
19+
retrieve_by = "latest"
20+
}
21+
```
22+
23+
To retrieve a specific release asset from a repository based on its ID:
24+
25+
```hcl
26+
data "github_release_asset" "example" {
27+
repository = "example-repository"
28+
owner = "example-owner"
29+
asset_id = 12345
30+
}
31+
```
32+
33+
To retrieve the first release asset associated with the the latest release in a repository:
34+
35+
```hcl
36+
data "github_release" "example" {
37+
repository = "example-repository"
38+
owner = "example-owner"
39+
retrieve_by = "latest"
40+
}
41+
42+
data "github_release_asset" "example" {
43+
repository = "example-repository"
44+
owner = "example-owner"
45+
asset_id = data.github_release.example.assets[0].id
46+
}
47+
```
48+
49+
To retrieve all release assets associated with the the latest release in a repository:
50+
51+
```hcl
52+
data "github_release" "example" {
53+
repository = "example-repository"
54+
owner = "example-owner"
55+
retrieve_by = "latest"
56+
}
57+
58+
data "github_release_asset" "example" {
59+
count = length(data.github_release.example.assets)
60+
repository = "example-repository"
61+
owner = "example-owner"
62+
asset_id = data.github_release.example.assets[count.index].id
63+
}
64+
```
65+
66+
## Argument Reference
67+
68+
* `repository` - (Required) Name of the repository to retrieve the release from
69+
* `owner` - (Required) Owner of the repository
70+
* `asset_id` - (Required) ID of the release asset to retrieve
71+
72+
## Attributes Reference
73+
74+
* `id` - ID of the asset
75+
* `url` - URL of the asset
76+
* `node_id` - Node ID of the asset
77+
* `name` - The file name of the asset
78+
* `label` - Label for the asset
79+
* `content_type` - MIME type of the asset
80+
* `size` - Asset size in bytes
81+
* `created_at` - Date the asset was created
82+
* `updated_at` - Date the asset was last updated
83+
* `browser_download_url` - Browser URL from which the release asset can be downloaded
84+
* `body` - The release asset body

0 commit comments

Comments
 (0)