Skip to content

Commit 2a8e4e2

Browse files
Gustedearl-warren
authored andcommitted
add Upload URL to release API
- Resolves https://codeberg.org/forgejo/forgejo/issues/580 - Return a `upload_field` to any release API response, which points to the API URL for uploading new assets. - Adds unit test. - Adds integration testing to verify URL is returned correctly and that upload endpoint actually works
1 parent bd8a253 commit 2a8e4e2

File tree

6 files changed

+80
-0
lines changed

6 files changed

+80
-0
lines changed

models/repo/release.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ func (r *Release) HTMLURL() string {
133133
return r.Repo.HTMLURL() + "/releases/tag/" + util.PathEscapeSegments(r.TagName)
134134
}
135135

136+
// APIUploadURL the api url to upload assets to a release. release must have attributes loaded
137+
func (r *Release) APIUploadURL() string {
138+
return r.APIURL() + "/assets"
139+
}
140+
136141
// Link the relative url for a release on the web UI. release must have attributes loaded
137142
func (r *Release) Link() string {
138143
return r.Repo.Link() + "/releases/tag/" + util.PathEscapeSegments(r.TagName)

modules/structs/release.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Release struct {
1818
HTMLURL string `json:"html_url"`
1919
TarURL string `json:"tarball_url"`
2020
ZipURL string `json:"zipball_url"`
21+
UploadURL string `json:"upload_url"`
2122
IsDraft bool `json:"draft"`
2223
IsPrerelease bool `json:"prerelease"`
2324
// swagger:strfmt date-time

services/convert/release.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func ToAPIRelease(ctx context.Context, repo *repo_model.Repository, r *repo_mode
2222
HTMLURL: r.HTMLURL(),
2323
TarURL: r.TarURL(),
2424
ZipURL: r.ZipURL(),
25+
UploadURL: r.APIUploadURL(),
2526
IsDraft: r.IsDraft,
2627
IsPrerelease: r.IsPrerelease,
2728
CreatedAt: r.CreatedUnix.AsTime(),

services/convert/release_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// Copyright 2023 The Forgejo Authors. All rights reserved.
3+
// SPDX-License-Identifier: MIT
4+
5+
package convert
6+
7+
import (
8+
"testing"
9+
10+
"code.gitea.io/gitea/models/db"
11+
repo_model "code.gitea.io/gitea/models/repo"
12+
"code.gitea.io/gitea/models/unittest"
13+
14+
"github.com/stretchr/testify/assert"
15+
)
16+
17+
func TestRelease_ToRelease(t *testing.T) {
18+
assert.NoError(t, unittest.PrepareTestDatabase())
19+
20+
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
21+
release1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 1})
22+
release1.LoadAttributes(db.DefaultContext)
23+
24+
apiRelease := ToAPIRelease(db.DefaultContext, repo1, release1)
25+
assert.NotNil(t, apiRelease)
26+
assert.EqualValues(t, 1, apiRelease.ID)
27+
assert.EqualValues(t, "https://try.gitea.io/api/v1/repos/user2/repo1/releases/1", apiRelease.URL)
28+
assert.EqualValues(t, "https://try.gitea.io/api/v1/repos/user2/repo1/releases/1/assets", apiRelease.UploadURL)
29+
}

templates/swagger/v1_json.tmpl

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/api_releases_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44
package integration
55

66
import (
7+
"bytes"
78
"fmt"
9+
"io"
10+
"mime/multipart"
811
"net/http"
912
"net/url"
13+
"strings"
1014
"testing"
1115

1216
auth_model "code.gitea.io/gitea/models/auth"
@@ -38,12 +42,15 @@ func TestAPIListReleases(t *testing.T) {
3842
case 1:
3943
assert.False(t, release.IsDraft)
4044
assert.False(t, release.IsPrerelease)
45+
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/1/assets"), release.UploadURL)
4146
case 4:
4247
assert.True(t, release.IsDraft)
4348
assert.False(t, release.IsPrerelease)
49+
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/4/assets"), release.UploadURL)
4450
case 5:
4551
assert.False(t, release.IsDraft)
4652
assert.True(t, release.IsPrerelease)
53+
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/5/assets"), release.UploadURL)
4754
default:
4855
assert.NoError(t, fmt.Errorf("unexpected release: %v", release))
4956
}
@@ -248,3 +255,36 @@ func TestAPIDeleteReleaseByTagName(t *testing.T) {
248255
req = NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/tags/release-tag?token=%s", owner.Name, repo.Name, token))
249256
_ = MakeRequest(t, req, http.StatusNoContent)
250257
}
258+
259+
func TestAPIUploadAssetRelease(t *testing.T) {
260+
defer tests.PrepareTestEnv(t)()
261+
262+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
263+
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
264+
session := loginUser(t, owner.LowerName)
265+
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
266+
267+
r := createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
268+
269+
filename := "image.png"
270+
buff := generateImg()
271+
body := &bytes.Buffer{}
272+
273+
writer := multipart.NewWriter(body)
274+
part, err := writer.CreateFormFile("attachment", filename)
275+
assert.NoError(t, err)
276+
_, err = io.Copy(part, &buff)
277+
assert.NoError(t, err)
278+
err = writer.Close()
279+
assert.NoError(t, err)
280+
281+
req := NewRequestWithBody(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d/assets?name=test-asset&token=%s", owner.Name, repo.Name, r.ID, token), body)
282+
req.Header.Add("Content-Type", writer.FormDataContentType())
283+
resp := MakeRequest(t, req, http.StatusCreated)
284+
285+
var attachment *api.Attachment
286+
DecodeJSON(t, resp, &attachment)
287+
288+
assert.EqualValues(t, "test-asset", attachment.Name)
289+
assert.EqualValues(t, 104, attachment.Size)
290+
}

0 commit comments

Comments
 (0)