mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-26 06:16:56 +09:00
Supports migrating from Gitea-compatible forges like Forgejo and fixes many migration bugs. 1. Pre-release and `+gitea-` suffixed server versions no longer drop reviews, reactions and pagination. 2. Review states, dismissals, scoped and archived labels and merge bases are migrated. 3. Disabled units, external trackers, unavailable release assets, and GitLab confidential issues and internal notes are skipped. 4. Credentials are only sent to the source host, and `Retry-After` rate limits are waited out. 5. GitHub migrations of only issues or pull requests, basic auth clones and dismissed reviews work again. 6. The API returns 404 for releases of a disabled unit and shows migrated authors as mannequins, replacing the never populated `original_author` and `original_author_id` fields. Fixes: https://github.com/go-gitea/gitea/issues/19533 Fixes: https://github.com/go-gitea/gitea/issues/35885 Fixes: https://github.com/go-gitea/gitea/issues/18275 Fixes: https://github.com/go-gitea/gitea/issues/35069 Fixes: https://github.com/go-gitea/gitea/issues/17763 Fixes: https://github.com/go-gitea/gitea/issues/39548 Co-authored-by: bircni <bircni@icloud.com>
461 lines
19 KiB
Go
461 lines
19 KiB
Go
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
auth_model "gitea.dev/models/auth"
|
|
"gitea.dev/models/db"
|
|
access_model "gitea.dev/models/perm/access"
|
|
repo_model "gitea.dev/models/repo"
|
|
unit_model "gitea.dev/models/unit"
|
|
"gitea.dev/models/unittest"
|
|
user_model "gitea.dev/models/user"
|
|
"gitea.dev/modules/git"
|
|
"gitea.dev/modules/setting"
|
|
api "gitea.dev/modules/structs"
|
|
"gitea.dev/modules/test"
|
|
repo_service "gitea.dev/services/repository"
|
|
"gitea.dev/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestAPIReleaseRead(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
t.Run("DraftReleaseAttachmentAccess", testAPIDraftReleaseAttachmentAccess)
|
|
t.Run("ListReleasesWithWriteToken", testAPIListReleasesWithWriteToken)
|
|
t.Run("ListReleasesWithReadToken", testAPIListReleasesWithReadToken)
|
|
t.Run("GetDraftRelease", testAPIGetDraftRelease)
|
|
t.Run("GetLatestRelease", testAPIGetLatestRelease)
|
|
t.Run("GetReleaseByTag", testAPIGetReleaseByTag)
|
|
t.Run("GetDraftReleaseByTag", testAPIGetDraftReleaseByTag)
|
|
t.Run("EditReleaseAttachmentWithUnallowedFile", testAPIEditReleaseAttachmentWithUnallowedFile) // failed attempt, so it is also a read test
|
|
}
|
|
|
|
func testAPIListReleasesTagNames(t *testing.T, queryURL, authToken string, expectedTagNames []string, msgAndArgs ...string) {
|
|
t.Helper()
|
|
resp := MakeRequest(t, NewRequest(t, "GET", queryURL).AddTokenAuth(authToken), http.StatusOK)
|
|
apiReleases := DecodeJSON(t, resp, []*api.Release{})
|
|
tagNames := make([]string, 0, len(apiReleases))
|
|
for _, release := range apiReleases {
|
|
tagNames = append(tagNames, release.TagName)
|
|
}
|
|
assert.ElementsMatch(t, expectedTagNames, tagNames, msgAndArgs)
|
|
}
|
|
|
|
func testAPIListReleasesWithWriteToken(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
link := fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name)
|
|
resp := MakeRequest(t, NewRequest(t, "GET", link).AddTokenAuth(token), http.StatusOK)
|
|
apiReleases := DecodeJSON(t, resp, []*api.Release{})
|
|
if assert.Len(t, apiReleases, 3) {
|
|
for _, release := range apiReleases {
|
|
switch release.ID {
|
|
case 1:
|
|
assert.False(t, release.IsDraft)
|
|
assert.False(t, release.IsPrerelease)
|
|
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/1/assets"), release.UploadURL)
|
|
case 4:
|
|
assert.True(t, release.IsDraft)
|
|
assert.False(t, release.IsPrerelease)
|
|
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/4/assets"), release.UploadURL)
|
|
case 5:
|
|
assert.False(t, release.IsDraft)
|
|
assert.True(t, release.IsPrerelease)
|
|
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/5/assets"), release.UploadURL)
|
|
default:
|
|
assert.NoError(t, fmt.Errorf("unexpected release: %v", release))
|
|
}
|
|
}
|
|
}
|
|
|
|
testAPIListReleasesTagNames(t, link+"?draft=true", "", nil, "anon should not see drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=true", token, []string{"draft-release"}, "repo owner should see drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=false", token, []string{"v1.0", "v1.1"}, "exclude drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=false&pre-release=false", token, []string{"v1.1"}, "exclude drafts and pre-releases")
|
|
testAPIListReleasesTagNames(t, link+"?pre-release=true", token, []string{"v1.0"}, "only get pre-release")
|
|
testAPIListReleasesTagNames(t, link+"?draft=true&pre-release=true", token, nil, "there is no pre-release draft")
|
|
testAPIListReleasesTagNames(t, link+"?tag_filter=v1*", token, []string{"v1.0", "v1.1"}, "prefix tag filter")
|
|
testAPIListReleasesTagNames(t, link+"?tag_filter=*1.0", token, []string{"v1.0"}, "suffix tag filter")
|
|
testAPIListReleasesTagNames(t, link+"?tag_filter=*raft*", token, []string{"draft-release"}, "substring tag filter")
|
|
testAPIListReleasesTagNames(t, link+"?tag_filter=v1._", token, nil, "underscore is not a wildcard")
|
|
}
|
|
|
|
func testAPIListReleasesWithReadToken(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeReadRepository)
|
|
|
|
link := fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name)
|
|
resp := MakeRequest(t, NewRequest(t, "GET", link).AddTokenAuth(token), http.StatusOK)
|
|
apiReleases := DecodeJSON(t, resp, []*api.Release{})
|
|
if assert.Len(t, apiReleases, 2) {
|
|
for _, release := range apiReleases {
|
|
switch release.ID {
|
|
case 1:
|
|
assert.False(t, release.IsDraft)
|
|
assert.False(t, release.IsPrerelease)
|
|
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/1/assets"), release.UploadURL)
|
|
case 5:
|
|
assert.False(t, release.IsDraft)
|
|
assert.True(t, release.IsPrerelease)
|
|
assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/5/assets"), release.UploadURL)
|
|
default:
|
|
assert.NoError(t, fmt.Errorf("unexpected release: %v", release))
|
|
}
|
|
}
|
|
}
|
|
|
|
testAPIListReleasesTagNames(t, link+"?draft=true", "", nil, "anon should not see drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=true", token, nil, "repo owner with read token should not see drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=false", token, []string{"v1.0", "v1.1"}, "exclude drafts")
|
|
testAPIListReleasesTagNames(t, link+"?draft=false&pre-release=false", token, []string{"v1.1"}, "exclude drafts and pre-releases")
|
|
testAPIListReleasesTagNames(t, link+"?pre-release=true", token, []string{"v1.0"}, "only get pre-release")
|
|
testAPIListReleasesTagNames(t, link+"?draft=true&pre-release=true", token, nil, "there is no pre-release draft")
|
|
|
|
require.NoError(t, repo_service.UpdateRepositoryUnits(t.Context(), unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}), nil, []unit_model.Type{unit_model.TypeReleases}))
|
|
MakeRequest(t, NewRequest(t, "GET", "/api/v1/repos/user2/repo2/releases").AddTokenAuth(token), http.StatusNotFound)
|
|
}
|
|
|
|
func testAPIGetDraftRelease(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 4})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
reader := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d", owner.Name, repo.Name, release.ID)
|
|
|
|
MakeRequest(t, NewRequest(t, "GET", urlStr), http.StatusNotFound)
|
|
|
|
readerToken := getUserToken(t, reader.LowerName, auth_model.AccessTokenScopeReadRepository)
|
|
MakeRequest(t, NewRequest(t, "GET", urlStr).AddTokenAuth(readerToken), http.StatusNotFound)
|
|
|
|
ownerToken := getUserToken(t, owner.LowerName, auth_model.AccessTokenScopeWriteRepository)
|
|
resp := MakeRequest(t, NewRequest(t, "GET", urlStr).AddTokenAuth(ownerToken), http.StatusOK)
|
|
apiRelease := DecodeJSON(t, resp, &api.Release{})
|
|
assert.Equal(t, release.Title, apiRelease.Title)
|
|
}
|
|
|
|
func createNewReleaseUsingAPI(t *testing.T, token string, owner *user_model.User, repo *repo_model.Repository, name, target, title, desc string) *api.Release {
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases", owner.Name, repo.Name)
|
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateReleaseOption{
|
|
TagName: name,
|
|
Title: title,
|
|
Note: desc,
|
|
IsDraft: false,
|
|
IsPrerelease: false,
|
|
Target: target,
|
|
}).AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusCreated)
|
|
|
|
newRelease := DecodeJSON(t, resp, &api.Release{})
|
|
rel := &repo_model.Release{
|
|
ID: newRelease.ID,
|
|
TagName: newRelease.TagName,
|
|
Title: newRelease.Title,
|
|
}
|
|
unittest.AssertExistsAndLoadBean(t, rel)
|
|
assert.Equal(t, newRelease.Note, rel.Note)
|
|
|
|
return newRelease
|
|
}
|
|
|
|
func TestAPICreateAndUpdateRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
gitRepo, err := git.OpenRepository(t.Context(), repo)
|
|
assert.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
|
|
err = gitRepo.CreateTag(t.Context(), "v0.0.1", "master")
|
|
assert.NoError(t, err)
|
|
|
|
target, err := gitRepo.GetTagCommitID(t.Context(), "v0.0.1")
|
|
assert.NoError(t, err)
|
|
|
|
newRelease := createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", target, "v0.0.1", "test")
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d", owner.Name, repo.Name, newRelease.ID)
|
|
req := NewRequest(t, "GET", urlStr).
|
|
AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
release := DecodeJSON(t, resp, &api.Release{})
|
|
|
|
assert.Equal(t, newRelease.TagName, release.TagName)
|
|
assert.Equal(t, newRelease.Title, release.Title)
|
|
assert.Equal(t, newRelease.Note, release.Note)
|
|
|
|
req = NewRequestWithJSON(t, "PATCH", urlStr, &api.EditReleaseOption{
|
|
TagName: release.TagName,
|
|
Title: release.Title,
|
|
Note: "updated",
|
|
IsDraft: &release.IsDraft,
|
|
IsPrerelease: &release.IsPrerelease,
|
|
Target: release.Target,
|
|
}).AddTokenAuth(token)
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
newRelease = DecodeJSON(t, resp, &api.Release{})
|
|
rel := &repo_model.Release{
|
|
ID: newRelease.ID,
|
|
TagName: newRelease.TagName,
|
|
Title: newRelease.Title,
|
|
}
|
|
unittest.AssertExistsAndLoadBean(t, rel)
|
|
assert.Equal(t, rel.Note, newRelease.Note)
|
|
}
|
|
|
|
func TestAPICreateProtectedTagRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
|
writer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
|
session := loginUser(t, writer.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
gitRepo, err := git.OpenRepository(t.Context(), repo)
|
|
assert.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
|
|
commit, err := gitRepo.GetBranchCommit(t.Context(), "master")
|
|
assert.NoError(t, err)
|
|
|
|
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/releases", repo.OwnerName, repo.Name), &api.CreateReleaseOption{
|
|
TagName: "v0.0.1",
|
|
Title: "v0.0.1",
|
|
IsDraft: false,
|
|
IsPrerelease: false,
|
|
Target: commit.ID.String(),
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusUnprocessableEntity)
|
|
}
|
|
|
|
func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
|
|
}
|
|
|
|
func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
gitRepo, err := git.OpenRepository(t.Context(), repo)
|
|
assert.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
|
|
err = gitRepo.CreateTag(t.Context(), "v0.0.1", "master")
|
|
assert.NoError(t, err)
|
|
|
|
createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
|
|
}
|
|
|
|
func TestAPICreateReleaseGivenInvalidTarget(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases", owner.Name, repo.Name)
|
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateReleaseOption{
|
|
TagName: "i-point-to-an-invalid-target",
|
|
Title: "Invalid Target",
|
|
Target: "invalid-target",
|
|
}).AddTokenAuth(token)
|
|
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
}
|
|
|
|
func testAPIGetLatestRelease(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
|
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/latest", owner.Name, repo.Name))
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
release := DecodeJSON(t, resp, &api.Release{})
|
|
|
|
assert.Equal(t, "testing-release", release.Title)
|
|
}
|
|
|
|
func testAPIGetReleaseByTag(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
|
|
tag := "v1.1"
|
|
|
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, tag))
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
release := DecodeJSON(t, resp, &api.Release{})
|
|
|
|
assert.Equal(t, "testing-release", release.Title)
|
|
|
|
nonexistingtag := "nonexistingtag"
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, nonexistingtag))
|
|
resp = MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
err := DecodeJSON(t, resp, &api.APIError{})
|
|
assert.NotEmpty(t, err.Message)
|
|
}
|
|
|
|
func testAPIGetDraftReleaseByTag(t *testing.T) {
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
|
|
tag := "draft-release"
|
|
// anonymous should not be able to get draft release
|
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, tag))
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
// user 40 should be able to get draft release because he has write access to the repository
|
|
token := getUserToken(t, "user40", auth_model.AccessTokenScopeReadRepository)
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, tag)).AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
release := DecodeJSON(t, resp, &api.Release{})
|
|
assert.Equal(t, "draft-release", release.Title)
|
|
|
|
// remove user 40 access from the repository
|
|
_, err := db.DeleteByID[access_model.Access](t.Context(), 30)
|
|
assert.NoError(t, err)
|
|
|
|
// user 40 should not be able to get draft release
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, tag)).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
// user 2 should be able to get draft release because he is the publisher
|
|
user2Token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository)
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, tag)).AddTokenAuth(user2Token)
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
release = DecodeJSON(t, resp, &api.Release{})
|
|
assert.Equal(t, "draft-release", release.Title)
|
|
}
|
|
|
|
func TestAPIDeleteReleaseByTagName(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
createNewReleaseUsingAPI(t, token, owner, repo, "release-tag", "", "Release Tag", "test")
|
|
|
|
// delete release
|
|
req := NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/%s/releases/tags/release-tag", owner.Name, repo.Name).
|
|
AddTokenAuth(token)
|
|
_ = MakeRequest(t, req, http.StatusNoContent)
|
|
|
|
// make sure release is deleted
|
|
req = NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/%s/releases/tags/release-tag", owner.Name, repo.Name).
|
|
AddTokenAuth(token)
|
|
_ = MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
// delete release tag too
|
|
req = NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/%s/tags/release-tag", owner.Name, repo.Name).
|
|
AddTokenAuth(token)
|
|
_ = MakeRequest(t, req, http.StatusNoContent)
|
|
}
|
|
|
|
func TestAPIUploadAssetRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
defer test.MockVariableValue(&setting.Repository.Release.FileMaxSize, 1)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
|
session := loginUser(t, owner.LowerName)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
bufImageBytes := testGeneratePngBytes()
|
|
bufLargeBytes := bytes.Repeat([]byte{' '}, 2*1024*1024)
|
|
|
|
release := createNewReleaseUsingAPI(t, token, owner, repo, "release-tag", "", "Release Tag", "test")
|
|
assetURL := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d/assets", owner.Name, repo.Name, release.ID)
|
|
|
|
t.Run("multipart/form-data", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
const filename = "image.png"
|
|
|
|
performUpload := func(t *testing.T, uploadURL string, _ []byte, _ int) *httptest.ResponseRecorder {
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
part, err := writer.CreateFormFile("attachment", filename)
|
|
assert.NoError(t, err)
|
|
_, err = io.Copy(part, bytes.NewReader(bufImageBytes))
|
|
assert.NoError(t, err)
|
|
err = writer.Close()
|
|
assert.NoError(t, err)
|
|
|
|
req := NewRequestWithBody(t, http.MethodPost, uploadURL, bytes.NewReader(body.Bytes())).
|
|
AddTokenAuth(token).
|
|
SetHeader("Content-Type", writer.FormDataContentType())
|
|
return MakeRequest(t, req, http.StatusCreated)
|
|
}
|
|
|
|
performUpload(t, assetURL, bufLargeBytes, http.StatusRequestEntityTooLarge)
|
|
|
|
t.Run("UploadDefaultName", func(t *testing.T) {
|
|
resp := performUpload(t, assetURL, bufImageBytes, http.StatusCreated)
|
|
attachment := DecodeJSON(t, resp, &api.Attachment{})
|
|
assert.Equal(t, filename, attachment.Name)
|
|
assert.EqualValues(t, len(bufImageBytes), attachment.Size)
|
|
})
|
|
t.Run("UploadWithName", func(t *testing.T) {
|
|
resp := performUpload(t, assetURL+"?name=test-asset", bufImageBytes, http.StatusCreated)
|
|
attachment := DecodeJSON(t, resp, &api.Attachment{})
|
|
assert.Equal(t, "test-asset", attachment.Name)
|
|
assert.EqualValues(t, len(bufImageBytes), attachment.Size)
|
|
})
|
|
})
|
|
|
|
t.Run("application/octet-stream", func(t *testing.T) {
|
|
defer tests.PrintCurrentTest(t)()
|
|
|
|
req := NewRequestWithBody(t, http.MethodPost, assetURL, bytes.NewReader(bufImageBytes)).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusBadRequest)
|
|
|
|
req = NewRequestWithBody(t, http.MethodPost, assetURL+"?name=stream.bin", bytes.NewReader(bufLargeBytes)).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusRequestEntityTooLarge)
|
|
|
|
req = NewRequestWithBody(t, http.MethodPost, assetURL+"?name=stream.bin", bytes.NewReader(bufImageBytes)).AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusCreated)
|
|
|
|
attachment := DecodeJSON(t, resp, &api.Attachment{})
|
|
|
|
assert.Equal(t, "stream.bin", attachment.Name)
|
|
assert.EqualValues(t, len(bufImageBytes), attachment.Size)
|
|
})
|
|
}
|