You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api_releases_test.go 10KB

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