[API] ListReleases add filter for draft and pre-releases (#16175)
* invent ctx.QueryOptionalBool * [API] ListReleases add draft and pre-release filter * Add X-Total-Count header * Add a release to fixtures * Add TEST for API ListReleases
This commit is contained in:
		
							parent
							
								
									c9d053f0ca
								
							
						
					
					
						commit
						6ad5d0a306
					
				
					 9 changed files with 158 additions and 22 deletions
				
			
		|  | @ -7,6 +7,7 @@ package integrations | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
|  | @ -16,6 +17,58 @@ import ( | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func TestAPIListReleases(t *testing.T) { | ||||||
|  | 	defer prepareTestEnv(t)() | ||||||
|  | 
 | ||||||
|  | 	repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) | ||||||
|  | 	user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) | ||||||
|  | 	session := loginUser(t, user2.LowerName) | ||||||
|  | 	token := getTokenForLoggedInUser(t, session) | ||||||
|  | 
 | ||||||
|  | 	link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/releases", user2.Name, repo.Name)) | ||||||
|  | 	link.RawQuery = url.Values{"token": {token}}.Encode() | ||||||
|  | 	resp := session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) | ||||||
|  | 	var apiReleases []*api.Release | ||||||
|  | 	DecodeJSON(t, resp, &apiReleases) | ||||||
|  | 	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) | ||||||
|  | 			case 4: | ||||||
|  | 				assert.True(t, release.IsDraft) | ||||||
|  | 				assert.False(t, release.IsPrerelease) | ||||||
|  | 			case 5: | ||||||
|  | 				assert.False(t, release.IsDraft) | ||||||
|  | 				assert.True(t, release.IsPrerelease) | ||||||
|  | 			default: | ||||||
|  | 				assert.NoError(t, fmt.Errorf("unexpected release: %v", release)) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// test filter
 | ||||||
|  | 	testFilterByLen := func(auth bool, query url.Values, expectedLength int, msgAndArgs ...string) { | ||||||
|  | 		link.RawQuery = query.Encode() | ||||||
|  | 		if auth { | ||||||
|  | 			query.Set("token", token) | ||||||
|  | 			resp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) | ||||||
|  | 		} else { | ||||||
|  | 			resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) | ||||||
|  | 		} | ||||||
|  | 		DecodeJSON(t, resp, &apiReleases) | ||||||
|  | 		assert.Len(t, apiReleases, expectedLength, msgAndArgs) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	testFilterByLen(false, url.Values{"draft": {"true"}}, 0, "anon should not see drafts") | ||||||
|  | 	testFilterByLen(true, url.Values{"draft": {"true"}}, 1, "repo owner should see drafts") | ||||||
|  | 	testFilterByLen(true, url.Values{"draft": {"false"}}, 2, "exclude drafts") | ||||||
|  | 	testFilterByLen(true, url.Values{"draft": {"false"}, "pre-release": {"false"}}, 1, "exclude drafts and pre-releases") | ||||||
|  | 	testFilterByLen(true, url.Values{"pre-release": {"true"}}, 1, "only get pre-release") | ||||||
|  | 	testFilterByLen(true, url.Values{"draft": {"true"}, "pre-release": {"true"}}, 0, "there is no pre-release draft") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func createNewReleaseUsingAPI(t *testing.T, session *TestSession, token string, owner *models.User, repo *models.Repository, name, target, title, desc string) *api.Release { | func createNewReleaseUsingAPI(t *testing.T, session *TestSession, token string, owner *models.User, repo *models.Repository, name, target, title, desc string) *api.Release { | ||||||
| 	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases?token=%s", | 	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases?token=%s", | ||||||
| 		owner.Name, repo.Name, token) | 		owner.Name, repo.Name, token) | ||||||
|  |  | ||||||
|  | @ -223,7 +223,7 @@ func TestAPIViewRepo(t *testing.T) { | ||||||
| 	DecodeJSON(t, resp, &repo) | 	DecodeJSON(t, resp, &repo) | ||||||
| 	assert.EqualValues(t, 1, repo.ID) | 	assert.EqualValues(t, 1, repo.ID) | ||||||
| 	assert.EqualValues(t, "repo1", repo.Name) | 	assert.EqualValues(t, "repo1", repo.Name) | ||||||
| 	assert.EqualValues(t, 2, repo.Releases) | 	assert.EqualValues(t, 3, repo.Releases) | ||||||
| 	assert.EqualValues(t, 1, repo.OpenIssues) | 	assert.EqualValues(t, 1, repo.OpenIssues) | ||||||
| 	assert.EqualValues(t, 3, repo.OpenPulls) | 	assert.EqualValues(t, 3, repo.OpenPulls) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ func TestCreateRelease(t *testing.T) { | ||||||
| 	session := loginUser(t, "user2") | 	session := loginUser(t, "user2") | ||||||
| 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false) | 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false) | ||||||
| 
 | 
 | ||||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.stable"), 3) | 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.stable"), 4) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestCreateReleasePreRelease(t *testing.T) { | func TestCreateReleasePreRelease(t *testing.T) { | ||||||
|  | @ -94,7 +94,7 @@ func TestCreateReleasePreRelease(t *testing.T) { | ||||||
| 	session := loginUser(t, "user2") | 	session := loginUser(t, "user2") | ||||||
| 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false) | 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false) | ||||||
| 
 | 
 | ||||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.prerelease"), 3) | 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.prerelease"), 4) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestCreateReleaseDraft(t *testing.T) { | func TestCreateReleaseDraft(t *testing.T) { | ||||||
|  | @ -103,7 +103,7 @@ func TestCreateReleaseDraft(t *testing.T) { | ||||||
| 	session := loginUser(t, "user2") | 	session := loginUser(t, "user2") | ||||||
| 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true) | 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true) | ||||||
| 
 | 
 | ||||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.draft"), 3) | 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.draft"), 4) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestCreateReleasePaging(t *testing.T) { | func TestCreateReleasePaging(t *testing.T) { | ||||||
|  | @ -142,7 +142,7 @@ func TestViewReleaseListNoLogin(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	htmlDoc := NewHTMLParser(t, rsp.Body) | 	htmlDoc := NewHTMLParser(t, rsp.Body) | ||||||
| 	releases := htmlDoc.Find("#release-list li.ui.grid") | 	releases := htmlDoc.Find("#release-list li.ui.grid") | ||||||
| 	assert.Equal(t, 1, releases.Length()) | 	assert.Equal(t, 2, releases.Length()) | ||||||
| 
 | 
 | ||||||
| 	links := make([]string, 0, 5) | 	links := make([]string, 0, 5) | ||||||
| 	releases.Each(func(i int, s *goquery.Selection) { | 	releases.Each(func(i int, s *goquery.Selection) { | ||||||
|  | @ -153,7 +153,7 @@ func TestViewReleaseListNoLogin(t *testing.T) { | ||||||
| 		links = append(links, link) | 		links = append(links, link) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	assert.EqualValues(t, []string{"/user2/repo1/releases/tag/v1.1"}, links) | 	assert.EqualValues(t, []string{"/user2/repo1/releases/tag/v1.0", "/user2/repo1/releases/tag/v1.1"}, links) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestViewReleaseListLogin(t *testing.T) { | func TestViewReleaseListLogin(t *testing.T) { | ||||||
|  | @ -169,7 +169,7 @@ func TestViewReleaseListLogin(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	htmlDoc := NewHTMLParser(t, rsp.Body) | 	htmlDoc := NewHTMLParser(t, rsp.Body) | ||||||
| 	releases := htmlDoc.Find("#release-list li.ui.grid") | 	releases := htmlDoc.Find("#release-list li.ui.grid") | ||||||
| 	assert.Equal(t, 2, releases.Length()) | 	assert.Equal(t, 3, releases.Length()) | ||||||
| 
 | 
 | ||||||
| 	links := make([]string, 0, 5) | 	links := make([]string, 0, 5) | ||||||
| 	releases.Each(func(i int, s *goquery.Selection) { | 	releases.Each(func(i int, s *goquery.Selection) { | ||||||
|  | @ -180,8 +180,11 @@ func TestViewReleaseListLogin(t *testing.T) { | ||||||
| 		links = append(links, link) | 		links = append(links, link) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	assert.EqualValues(t, []string{"/user2/repo1/releases/tag/draft-release", | 	assert.EqualValues(t, []string{ | ||||||
| 		"/user2/repo1/releases/tag/v1.1"}, links) | 		"/user2/repo1/releases/tag/draft-release", | ||||||
|  | 		"/user2/repo1/releases/tag/v1.0", | ||||||
|  | 		"/user2/repo1/releases/tag/v1.1", | ||||||
|  | 	}, links) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestViewTagsList(t *testing.T) { | func TestViewTagsList(t *testing.T) { | ||||||
|  | @ -197,12 +200,12 @@ func TestViewTagsList(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	htmlDoc := NewHTMLParser(t, rsp.Body) | 	htmlDoc := NewHTMLParser(t, rsp.Body) | ||||||
| 	tags := htmlDoc.Find(".tag-list tr") | 	tags := htmlDoc.Find(".tag-list tr") | ||||||
| 	assert.Equal(t, 2, tags.Length()) | 	assert.Equal(t, 3, tags.Length()) | ||||||
| 
 | 
 | ||||||
| 	tagNames := make([]string, 0, 5) | 	tagNames := make([]string, 0, 5) | ||||||
| 	tags.Each(func(i int, s *goquery.Selection) { | 	tags.Each(func(i int, s *goquery.Selection) { | ||||||
| 		tagNames = append(tagNames, s.Find(".tag a.df.ac").Text()) | 		tagNames = append(tagNames, s.Find(".tag a.df.ac").Text()) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	assert.EqualValues(t, []string{"delete-tag", "v1.1"}, tagNames) | 	assert.EqualValues(t, []string{"v1.0", "delete-tag", "v1.1"}, tagNames) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,4 @@ | ||||||
| - | - id: 1 | ||||||
|   id: 1 |  | ||||||
|   repo_id: 1 |   repo_id: 1 | ||||||
|   publisher_id: 2 |   publisher_id: 2 | ||||||
|   tag_name: "v1.1" |   tag_name: "v1.1" | ||||||
|  | @ -13,8 +12,7 @@ | ||||||
|   is_tag: false |   is_tag: false | ||||||
|   created_unix: 946684800 |   created_unix: 946684800 | ||||||
| 
 | 
 | ||||||
| - | - id: 2 | ||||||
|   id: 2 |  | ||||||
|   repo_id: 40 |   repo_id: 40 | ||||||
|   publisher_id: 2 |   publisher_id: 2 | ||||||
|   tag_name: "v1.1" |   tag_name: "v1.1" | ||||||
|  | @ -28,8 +26,7 @@ | ||||||
|   is_tag: false |   is_tag: false | ||||||
|   created_unix: 946684800 |   created_unix: 946684800 | ||||||
| 
 | 
 | ||||||
| - | - id: 3 | ||||||
|   id: 3 |  | ||||||
|   repo_id: 1 |   repo_id: 1 | ||||||
|   publisher_id: 2 |   publisher_id: 2 | ||||||
|   tag_name: "delete-tag" |   tag_name: "delete-tag" | ||||||
|  | @ -43,8 +40,7 @@ | ||||||
|   is_tag: true |   is_tag: true | ||||||
|   created_unix: 946684800 |   created_unix: 946684800 | ||||||
| 
 | 
 | ||||||
| - | - id: 4 | ||||||
|   id: 4 |  | ||||||
|   repo_id: 1 |   repo_id: 1 | ||||||
|   publisher_id: 2 |   publisher_id: 2 | ||||||
|   tag_name: "draft-release" |   tag_name: "draft-release" | ||||||
|  | @ -55,3 +51,18 @@ | ||||||
|   is_prerelease: false |   is_prerelease: false | ||||||
|   is_tag: false |   is_tag: false | ||||||
|   created_unix: 1619524806 |   created_unix: 1619524806 | ||||||
|  | 
 | ||||||
|  | - id: 5 | ||||||
|  |   repo_id: 1 | ||||||
|  |   publisher_id: 2 | ||||||
|  |   tag_name: "v1.0" | ||||||
|  |   lower_tag_name: "v1.0" | ||||||
|  |   target: "master" | ||||||
|  |   title: "pre-release" | ||||||
|  |   note: "some text for a pre release" | ||||||
|  |   sha1: "65f1bf27bc3bf70f64657658635e66094edbcb4d" | ||||||
|  |   num_commits: 1 | ||||||
|  |   is_draft: false | ||||||
|  |   is_prerelease: true | ||||||
|  |   is_tag: false | ||||||
|  |   created_unix: 946684800 | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/structs" | 	"code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/modules/timeutil" | 	"code.gitea.io/gitea/modules/timeutil" | ||||||
|  | 	"code.gitea.io/gitea/modules/util" | ||||||
| 
 | 
 | ||||||
| 	"xorm.io/builder" | 	"xorm.io/builder" | ||||||
| ) | ) | ||||||
|  | @ -173,6 +174,8 @@ type FindReleasesOptions struct { | ||||||
| 	ListOptions | 	ListOptions | ||||||
| 	IncludeDrafts bool | 	IncludeDrafts bool | ||||||
| 	IncludeTags   bool | 	IncludeTags   bool | ||||||
|  | 	IsPreRelease  util.OptionalBool | ||||||
|  | 	IsDraft       util.OptionalBool | ||||||
| 	TagNames      []string | 	TagNames      []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -189,6 +192,12 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { | ||||||
| 	if len(opts.TagNames) > 0 { | 	if len(opts.TagNames) > 0 { | ||||||
| 		cond = cond.And(builder.In("tag_name", opts.TagNames)) | 		cond = cond.And(builder.In("tag_name", opts.TagNames)) | ||||||
| 	} | 	} | ||||||
|  | 	if !opts.IsPreRelease.IsNone() { | ||||||
|  | 		cond = cond.And(builder.Eq{"is_prerelease": opts.IsPreRelease.IsTrue()}) | ||||||
|  | 	} | ||||||
|  | 	if !opts.IsDraft.IsNone() { | ||||||
|  | 		cond = cond.And(builder.Eq{"is_draft": opts.IsDraft.IsTrue()}) | ||||||
|  | 	} | ||||||
| 	return cond | 	return cond | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -206,6 +215,11 @@ func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, er | ||||||
| 	return rels, sess.Find(&rels) | 	return rels, sess.Find(&rels) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // CountReleasesByRepoID returns a number of releases matching FindReleaseOptions and RepoID.
 | ||||||
|  | func CountReleasesByRepoID(repoID int64, opts FindReleasesOptions) (int64, error) { | ||||||
|  | 	return x.Where(opts.toConds(repoID)).Count(new(Release)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // GetLatestReleaseByRepoID returns the latest release for a repository
 | // GetLatestReleaseByRepoID returns the latest release for a repository
 | ||||||
| func GetLatestReleaseByRepoID(repoID int64) (*Release, error) { | func GetLatestReleaseByRepoID(repoID int64) (*Release, error) { | ||||||
| 	cond := builder.NewCond(). | 	cond := builder.NewCond(). | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/templates" | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
|  | 	"code.gitea.io/gitea/modules/util" | ||||||
| 	"code.gitea.io/gitea/modules/web/middleware" | 	"code.gitea.io/gitea/modules/web/middleware" | ||||||
| 	"code.gitea.io/gitea/services/auth" | 	"code.gitea.io/gitea/services/auth" | ||||||
| 
 | 
 | ||||||
|  | @ -319,6 +320,11 @@ func (ctx *Context) QueryBool(key string, defaults ...bool) bool { | ||||||
| 	return (*Forms)(ctx.Req).MustBool(key, defaults...) | 	return (*Forms)(ctx.Req).MustBool(key, defaults...) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // QueryOptionalBool returns request form as OptionalBool with default
 | ||||||
|  | func (ctx *Context) QueryOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { | ||||||
|  | 	return (*Forms)(ctx.Req).MustOptionalBool(key, defaults...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // HandleText handles HTTP status code
 | // HandleText handles HTTP status code
 | ||||||
| func (ctx *Context) HandleText(status int, title string) { | func (ctx *Context) HandleText(status int, title string) { | ||||||
| 	if (status/100 == 4) || (status/100 == 5) { | 	if (status/100 == 4) || (status/100 == 5) { | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"text/template" | 	"text/template" | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
|  | 	"code.gitea.io/gitea/modules/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Forms a new enhancement of http.Request
 | // Forms a new enhancement of http.Request
 | ||||||
|  | @ -225,3 +226,16 @@ func (f *Forms) MustBool(key string, defaults ...bool) bool { | ||||||
| 	} | 	} | ||||||
| 	return v | 	return v | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // MustOptionalBool returns request form as OptionalBool with default
 | ||||||
|  | func (f *Forms) MustOptionalBool(key string, defaults ...util.OptionalBool) util.OptionalBool { | ||||||
|  | 	value := (*http.Request)(f).FormValue(key) | ||||||
|  | 	if len(value) == 0 { | ||||||
|  | 		return util.OptionalBoolNone | ||||||
|  | 	} | ||||||
|  | 	v, err := strconv.ParseBool((*http.Request)(f).FormValue(key)) | ||||||
|  | 	if len(defaults) > 0 && err != nil { | ||||||
|  | 		return defaults[0] | ||||||
|  | 	} | ||||||
|  | 	return util.OptionalBoolOf(v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| package repo | package repo | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
|  | @ -83,6 +84,14 @@ func ListReleases(ctx *context.APIContext) { | ||||||
| 	//   description: name of the repo
 | 	//   description: name of the repo
 | ||||||
| 	//   type: string
 | 	//   type: string
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
|  | 	// - name: draft
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: filter (exclude / include) drafts, if you dont have repo write access none will show
 | ||||||
|  | 	//   type: boolean
 | ||||||
|  | 	// - name: pre-release
 | ||||||
|  | 	//   in: query
 | ||||||
|  | 	//   description: filter (exclude / include) pre-releases
 | ||||||
|  | 	//   type: boolean
 | ||||||
| 	// - name: per_page
 | 	// - name: per_page
 | ||||||
| 	//   in: query
 | 	//   in: query
 | ||||||
| 	//   description: page size of results, deprecated - use limit
 | 	//   description: page size of results, deprecated - use limit
 | ||||||
|  | @ -100,15 +109,19 @@ func ListReleases(ctx *context.APIContext) { | ||||||
| 	//   "200":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/ReleaseList"
 | 	//     "$ref": "#/responses/ReleaseList"
 | ||||||
| 	listOptions := utils.GetListOptions(ctx) | 	listOptions := utils.GetListOptions(ctx) | ||||||
| 	if ctx.QueryInt("per_page") != 0 { | 	if listOptions.PageSize == 0 && ctx.QueryInt("per_page") != 0 { | ||||||
| 		listOptions.PageSize = ctx.QueryInt("per_page") | 		listOptions.PageSize = ctx.QueryInt("per_page") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ | 	opts := models.FindReleasesOptions{ | ||||||
| 		ListOptions:   listOptions, | 		ListOptions:   listOptions, | ||||||
| 		IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | 		IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite, | ||||||
| 		IncludeTags:   false, | 		IncludeTags:   false, | ||||||
| 	}) | 		IsDraft:       ctx.QueryOptionalBool("draft"), | ||||||
|  | 		IsPreRelease:  ctx.QueryOptionalBool("pre-release"), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | 		ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | ||||||
| 		return | 		return | ||||||
|  | @ -121,6 +134,16 @@ func ListReleases(ctx *context.APIContext) { | ||||||
| 		} | 		} | ||||||
| 		rels[i] = convert.ToRelease(release) | 		rels[i] = convert.ToRelease(release) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	filteredCount, err := models.CountReleasesByRepoID(ctx.Repo.Repository.ID, opts) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.InternalServerError(err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctx.SetLinkHeader(int(filteredCount), listOptions.PageSize) | ||||||
|  | 	ctx.Header().Set("X-Total-Count", fmt.Sprint(filteredCount)) | ||||||
|  | 	ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link") | ||||||
| 	ctx.JSON(http.StatusOK, rels) | 	ctx.JSON(http.StatusOK, rels) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8076,6 +8076,18 @@ | ||||||
|             "in": "path", |             "in": "path", | ||||||
|             "required": true |             "required": true | ||||||
|           }, |           }, | ||||||
|  |           { | ||||||
|  |             "type": "boolean", | ||||||
|  |             "description": "filter (exclude / include) drafts, if you dont have repo write access none will show", | ||||||
|  |             "name": "draft", | ||||||
|  |             "in": "query" | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "type": "boolean", | ||||||
|  |             "description": "filter (exclude / include) pre-releases", | ||||||
|  |             "name": "pre-release", | ||||||
|  |             "in": "query" | ||||||
|  |           }, | ||||||
|           { |           { | ||||||
|             "type": "integer", |             "type": "integer", | ||||||
|             "description": "page size of results, deprecated - use limit", |             "description": "page size of results, deprecated - use limit", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue