code.gitea.io/gitea@v1.21.7/tests/integration/api_releases_test.go (about)

     1  // Copyright 2018 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package integration
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io"
    10  	"mime/multipart"
    11  	"net/http"
    12  	"net/url"
    13  	"strings"
    14  	"testing"
    15  
    16  	auth_model "code.gitea.io/gitea/models/auth"
    17  	repo_model "code.gitea.io/gitea/models/repo"
    18  	"code.gitea.io/gitea/models/unittest"
    19  	user_model "code.gitea.io/gitea/models/user"
    20  	"code.gitea.io/gitea/modules/git"
    21  	api "code.gitea.io/gitea/modules/structs"
    22  	"code.gitea.io/gitea/tests"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestAPIListReleases(t *testing.T) {
    28  	defer tests.PrepareTestEnv(t)()
    29  
    30  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
    31  	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
    32  	token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeReadRepository)
    33  
    34  	link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name))
    35  	link.RawQuery = url.Values{"token": {token}}.Encode()
    36  	resp := MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
    37  	var apiReleases []*api.Release
    38  	DecodeJSON(t, resp, &apiReleases)
    39  	if assert.Len(t, apiReleases, 3) {
    40  		for _, release := range apiReleases {
    41  			switch release.ID {
    42  			case 1:
    43  				assert.False(t, release.IsDraft)
    44  				assert.False(t, release.IsPrerelease)
    45  				assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/1/assets"), release.UploadURL)
    46  			case 4:
    47  				assert.True(t, release.IsDraft)
    48  				assert.False(t, release.IsPrerelease)
    49  				assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/4/assets"), release.UploadURL)
    50  			case 5:
    51  				assert.False(t, release.IsDraft)
    52  				assert.True(t, release.IsPrerelease)
    53  				assert.True(t, strings.HasSuffix(release.UploadURL, "/api/v1/repos/user2/repo1/releases/5/assets"), release.UploadURL)
    54  			default:
    55  				assert.NoError(t, fmt.Errorf("unexpected release: %v", release))
    56  			}
    57  		}
    58  	}
    59  
    60  	// test filter
    61  	testFilterByLen := func(auth bool, query url.Values, expectedLength int, msgAndArgs ...string) {
    62  		if auth {
    63  			query.Set("token", token)
    64  		}
    65  		link.RawQuery = query.Encode()
    66  		resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
    67  		DecodeJSON(t, resp, &apiReleases)
    68  		assert.Len(t, apiReleases, expectedLength, msgAndArgs)
    69  	}
    70  
    71  	testFilterByLen(false, url.Values{"draft": {"true"}}, 0, "anon should not see drafts")
    72  	testFilterByLen(true, url.Values{"draft": {"true"}}, 1, "repo owner should see drafts")
    73  	testFilterByLen(true, url.Values{"draft": {"false"}}, 2, "exclude drafts")
    74  	testFilterByLen(true, url.Values{"draft": {"false"}, "pre-release": {"false"}}, 1, "exclude drafts and pre-releases")
    75  	testFilterByLen(true, url.Values{"pre-release": {"true"}}, 1, "only get pre-release")
    76  	testFilterByLen(true, url.Values{"draft": {"true"}, "pre-release": {"true"}}, 0, "there is no pre-release draft")
    77  }
    78  
    79  func createNewReleaseUsingAPI(t *testing.T, session *TestSession, token string, owner *user_model.User, repo *repo_model.Repository, name, target, title, desc string) *api.Release {
    80  	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases?token=%s",
    81  		owner.Name, repo.Name, token)
    82  	req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateReleaseOption{
    83  		TagName:      name,
    84  		Title:        title,
    85  		Note:         desc,
    86  		IsDraft:      false,
    87  		IsPrerelease: false,
    88  		Target:       target,
    89  	})
    90  	resp := MakeRequest(t, req, http.StatusCreated)
    91  
    92  	var newRelease api.Release
    93  	DecodeJSON(t, resp, &newRelease)
    94  	rel := &repo_model.Release{
    95  		ID:      newRelease.ID,
    96  		TagName: newRelease.TagName,
    97  		Title:   newRelease.Title,
    98  	}
    99  	unittest.AssertExistsAndLoadBean(t, rel)
   100  	assert.EqualValues(t, newRelease.Note, rel.Note)
   101  
   102  	return &newRelease
   103  }
   104  
   105  func TestAPICreateAndUpdateRelease(t *testing.T) {
   106  	defer tests.PrepareTestEnv(t)()
   107  
   108  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   109  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   110  	session := loginUser(t, owner.LowerName)
   111  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
   112  
   113  	gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
   114  	assert.NoError(t, err)
   115  	defer gitRepo.Close()
   116  
   117  	err = gitRepo.CreateTag("v0.0.1", "master")
   118  	assert.NoError(t, err)
   119  
   120  	target, err := gitRepo.GetTagCommitID("v0.0.1")
   121  	assert.NoError(t, err)
   122  
   123  	newRelease := createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", target, "v0.0.1", "test")
   124  
   125  	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d?token=%s",
   126  		owner.Name, repo.Name, newRelease.ID, token)
   127  	req := NewRequest(t, "GET", urlStr)
   128  	resp := MakeRequest(t, req, http.StatusOK)
   129  
   130  	var release api.Release
   131  	DecodeJSON(t, resp, &release)
   132  
   133  	assert.Equal(t, newRelease.TagName, release.TagName)
   134  	assert.Equal(t, newRelease.Title, release.Title)
   135  	assert.Equal(t, newRelease.Note, release.Note)
   136  
   137  	req = NewRequestWithJSON(t, "PATCH", urlStr, &api.EditReleaseOption{
   138  		TagName:      release.TagName,
   139  		Title:        release.Title,
   140  		Note:         "updated",
   141  		IsDraft:      &release.IsDraft,
   142  		IsPrerelease: &release.IsPrerelease,
   143  		Target:       release.Target,
   144  	})
   145  	resp = MakeRequest(t, req, http.StatusOK)
   146  
   147  	DecodeJSON(t, resp, &newRelease)
   148  	rel := &repo_model.Release{
   149  		ID:      newRelease.ID,
   150  		TagName: newRelease.TagName,
   151  		Title:   newRelease.Title,
   152  	}
   153  	unittest.AssertExistsAndLoadBean(t, rel)
   154  	assert.EqualValues(t, rel.Note, newRelease.Note)
   155  }
   156  
   157  func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
   158  	defer tests.PrepareTestEnv(t)()
   159  
   160  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   161  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   162  	session := loginUser(t, owner.LowerName)
   163  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
   164  
   165  	createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
   166  }
   167  
   168  func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
   169  	defer tests.PrepareTestEnv(t)()
   170  
   171  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   172  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   173  	session := loginUser(t, owner.LowerName)
   174  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
   175  
   176  	gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath())
   177  	assert.NoError(t, err)
   178  	defer gitRepo.Close()
   179  
   180  	err = gitRepo.CreateTag("v0.0.1", "master")
   181  	assert.NoError(t, err)
   182  
   183  	createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test")
   184  }
   185  
   186  func TestAPIGetLatestRelease(t *testing.T) {
   187  	defer tests.PrepareTestEnv(t)()
   188  
   189  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   190  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   191  
   192  	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/latest",
   193  		owner.Name, repo.Name)
   194  
   195  	req := NewRequestf(t, "GET", urlStr)
   196  	resp := MakeRequest(t, req, http.StatusOK)
   197  
   198  	var release *api.Release
   199  	DecodeJSON(t, resp, &release)
   200  
   201  	assert.Equal(t, "testing-release", release.Title)
   202  }
   203  
   204  func TestAPIGetReleaseByTag(t *testing.T) {
   205  	defer tests.PrepareTestEnv(t)()
   206  
   207  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   208  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   209  
   210  	tag := "v1.1"
   211  
   212  	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s",
   213  		owner.Name, repo.Name, tag)
   214  
   215  	req := NewRequestf(t, "GET", urlStr)
   216  	resp := MakeRequest(t, req, http.StatusOK)
   217  
   218  	var release *api.Release
   219  	DecodeJSON(t, resp, &release)
   220  
   221  	assert.Equal(t, "testing-release", release.Title)
   222  
   223  	nonexistingtag := "nonexistingtag"
   224  
   225  	urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s",
   226  		owner.Name, repo.Name, nonexistingtag)
   227  
   228  	req = NewRequestf(t, "GET", urlStr)
   229  	resp = MakeRequest(t, req, http.StatusNotFound)
   230  
   231  	var err *api.APIError
   232  	DecodeJSON(t, resp, &err)
   233  	assert.NotEmpty(t, err.Message)
   234  }
   235  
   236  func TestAPIDeleteReleaseByTagName(t *testing.T) {
   237  	defer tests.PrepareTestEnv(t)()
   238  
   239  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   240  	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
   241  	session := loginUser(t, owner.LowerName)
   242  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
   243  
   244  	createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
   245  
   246  	// delete release
   247  	req := NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag?token=%s", owner.Name, repo.Name, token))
   248  	_ = MakeRequest(t, req, http.StatusNoContent)
   249  
   250  	// make sure release is deleted
   251  	req = NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag?token=%s", owner.Name, repo.Name, token))
   252  	_ = MakeRequest(t, req, http.StatusNotFound)
   253  
   254  	// delete release tag too
   255  	req = NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/tags/release-tag?token=%s", owner.Name, repo.Name, token))
   256  	_ = MakeRequest(t, req, http.StatusNoContent)
   257  }
   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  }