From f23c3286937b1dc8fc98957d113bd0a7b8f3f7bb Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 14:36:37 +0200 Subject: [PATCH 1/8] Add release by tags endpoint Get a release based on a tag name (for which a release exists). Based on: https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name --- routers/api/v1/api.go | 3 ++ routers/api/v1/repo/release_tags.go | 54 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 routers/api/v1/repo/release_tags.go diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8b3a7545c63ae..ca52bcfbcbd83 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -797,6 +797,9 @@ func RegisterRoutes(m *macaron.Macaron) { Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseAttachment) }) }) + m.Group("/tags", func() { + m.Get("/:tag", repo.GetReleaseTag) + }) }, reqRepoReader(models.UnitTypeReleases)) m.Post("/mirror-sync", reqToken(), reqRepoWriter(models.UnitTypeCode), repo.MirrorSync) m.Get("/editorconfig/:filename", context.RepoRef(), reqRepoReader(models.UnitTypeCode), repo.GetEditorconfig) diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go new file mode 100644 index 0000000000000..711a8b10264bb --- /dev/null +++ b/routers/api/v1/repo/release_tags.go @@ -0,0 +1,54 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "net/http" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" +) + +// GetReleaseTag get a single release of a repository by its tagname +func GetReleaseTag(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/releases/tags/{tag} repository repoGetReleaseTag + // --- + // summary: Get a release by tagname + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: tag + // in: path + // description: tagname of the release to get + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/Release" + + tag := ctx.Params(":tag") + + release, err := models.GetRelease(ctx.Repo.Repository.ID, tag) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetRelease", err) + return + } + + if err := release.LoadAttributes(); err != nil { + ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) + return + } + ctx.JSON(http.StatusOK, release.APIFormat()) +} From 212db639bcaa52098dbd2ab0da2fa6cc9ed08081 Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 15:23:50 +0200 Subject: [PATCH 2/8] Update swagger template --- templates/swagger/v1_json.tmpl | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 6792f7444b062..4b4f519e626a4 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -7569,6 +7569,46 @@ } } }, + "/repos/{owner}/{repo}/releases/tags/{tag}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Get a release by tagname", + "operationId": "repoGetReleaseTag", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "tagname of the release to get", + "name": "tag", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/Release" + } + } + } + }, "/repos/{owner}/{repo}/releases/{id}": { "get": { "produces": [ From 2b5aaa20ac6e7637697aff31c09af5ae3910e2d5 Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 15:28:28 +0200 Subject: [PATCH 3/8] Return 404 if not found instead of 500 --- routers/api/v1/repo/release_tags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 711a8b10264bb..e308dc85bb7c4 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -42,7 +42,7 @@ func GetReleaseTag(ctx *context.APIContext) { release, err := models.GetRelease(ctx.Repo.Repository.ID, tag) if err != nil { - ctx.Error(http.StatusInternalServerError, "GetRelease", err) + ctx.Error(http.StatusNotFound, "GetRelease", err) return } From 2803b2fe49fda3af19b258511fa963f9f3a7bde6 Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 16:22:45 +0200 Subject: [PATCH 4/8] Apply suggestions from code review a1012112796 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 赵智超 <1012112796@qq.com> --- routers/api/v1/repo/release_tags.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index e308dc85bb7c4..b2caa5b086930 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -15,7 +15,7 @@ import ( func GetReleaseTag(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/releases/tags/{tag} repository repoGetReleaseTag // --- - // summary: Get a release by tagname + // summary: Get a release by tag name // produces: // - application/json // parameters: @@ -37,6 +37,8 @@ func GetReleaseTag(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/Release" + // "404": + // "$ref": "#/responses/notFound" tag := ctx.Params(":tag") From 4ae584ad80e8ceaf0876e44971bc8c1d5dbcd3c3 Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 16:28:32 +0200 Subject: [PATCH 5/8] Improve error handling Co-authored-by: 6543 <6543@obermui.de> --- routers/api/v1/repo/release_tags.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index b2caa5b086930..95899264c7366 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -44,7 +44,11 @@ func GetReleaseTag(ctx *context.APIContext) { release, err := models.GetRelease(ctx.Repo.Repository.ID, tag) if err != nil { - ctx.Error(http.StatusNotFound, "GetRelease", err) + if models.IsErrReleaseNotExist(err) { + ctx.Error(http.StatusNotFound, "GetRelease", err) + return + } + ctx.Error(http.StatusInternalServerError, "GetRelease", err) return } From 685016e26ed12e3ce75c2665f79218c093fba46b Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 21:21:45 +0200 Subject: [PATCH 6/8] Add tests --- integrations/api_releases_test.go | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/integrations/api_releases_test.go b/integrations/api_releases_test.go index 9aef33d068979..58c2e35440f09 100644 --- a/integrations/api_releases_test.go +++ b/integrations/api_releases_test.go @@ -7,6 +7,7 @@ package integrations import ( "fmt" "net/http" + "strings" "testing" "code.gitea.io/gitea/models" @@ -120,3 +121,36 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) { createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test") } + +func TestAPIGetReleaseByTag(t *testing.T) { + defer prepareTestEnv(t)() + + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User) + session := loginUser(t, owner.LowerName) + + tag := "v1.1" + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s/", + owner.Name, repo.Name, tag) + + req := NewRequestf(t, "GET", urlStr) + resp := session.MakeRequest(t, req, http.StatusOK) + + var release *api.Release + DecodeJSON(t, resp, &release) + + assert.Equal(t, "testing-release", release.Title) + + nonexistingtag := "nonexistingtag" + + urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s/", + owner.Name, repo.Name, nonexistingtag) + + req = NewRequestf(t, "GET", urlStr) + resp = session.MakeRequest(t, req, http.StatusNotFound) + + var err *api.APIError + DecodeJSON(t, resp, &err) + assert.True(t, strings.HasPrefix(err.Message, "release tag does not exist")) +} From 14872dd3a4c5b1156fadb4e39e1f7df19963b426 Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 21:22:14 +0200 Subject: [PATCH 7/8] Update swagger template --- templates/swagger/v1_json.tmpl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4b4f519e626a4..bb05c604363a2 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -7577,7 +7577,7 @@ "tags": [ "repository" ], - "summary": "Get a release by tagname", + "summary": "Get a release by tag name", "operationId": "repoGetReleaseTag", "parameters": [ { @@ -7605,6 +7605,9 @@ "responses": { "200": { "$ref": "#/responses/Release" + }, + "404": { + "$ref": "#/responses/notFound" } } } From ea32bf7ce80d48fed46918aa171b34416b723f6a Mon Sep 17 00:00:00 2001 From: Johan Van de Wauw <johan@gisky.be> Date: Thu, 24 Sep 2020 21:48:23 +0200 Subject: [PATCH 8/8] gofmt --- routers/api/v1/repo/release_tags.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 95899264c7366..bde3251ba28ca 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -45,8 +45,8 @@ func GetReleaseTag(ctx *context.APIContext) { release, err := models.GetRelease(ctx.Repo.Repository.ID, tag) if err != nil { if models.IsErrReleaseNotExist(err) { - ctx.Error(http.StatusNotFound, "GetRelease", err) - return + ctx.Error(http.StatusNotFound, "GetRelease", err) + return } ctx.Error(http.StatusInternalServerError, "GetRelease", err) return