mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	Delete tag API (#13358)
* Delete tag API Signed-off-by: jolheiser <john.olheiser@gmail.com> * Wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add conflict response and fix API tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix other test Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		| @@ -154,3 +154,26 @@ func TestAPIGetReleaseByTag(t *testing.T) { | ||||
| 	DecodeJSON(t, resp, &err) | ||||
| 	assert.True(t, strings.HasPrefix(err.Message, "release tag does not exist")) | ||||
| } | ||||
|  | ||||
| func TestAPIDeleteTagByName(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) | ||||
| 	token := getTokenForLoggedInUser(t, session) | ||||
|  | ||||
| 	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/delete-tag/?token=%s", | ||||
| 		owner.Name, repo.Name, token) | ||||
|  | ||||
| 	req := NewRequestf(t, http.MethodDelete, urlStr) | ||||
| 	_ = session.MakeRequest(t, req, http.StatusNoContent) | ||||
|  | ||||
| 	// Make sure that actual releases can't be deleted outright | ||||
| 	createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test") | ||||
| 	urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag/?token=%s", | ||||
| 		owner.Name, repo.Name, token) | ||||
|  | ||||
| 	req = NewRequestf(t, http.MethodDelete, urlStr) | ||||
| 	_ = session.MakeRequest(t, req, http.StatusConflict) | ||||
| } | ||||
|   | ||||
| @@ -223,7 +223,7 @@ func TestAPIViewRepo(t *testing.T) { | ||||
| 	DecodeJSON(t, resp, &repo) | ||||
| 	assert.EqualValues(t, 1, repo.ID) | ||||
| 	assert.EqualValues(t, "repo1", repo.Name) | ||||
| 	assert.EqualValues(t, 1, repo.Releases) | ||||
| 	assert.EqualValues(t, 2, repo.Releases) | ||||
| 	assert.EqualValues(t, 1, repo.OpenIssues) | ||||
| 	assert.EqualValues(t, 3, repo.OpenPulls) | ||||
|  | ||||
|   | ||||
| @@ -83,7 +83,7 @@ func TestCreateRelease(t *testing.T) { | ||||
| 	session := loginUser(t, "user2") | ||||
| 	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"), 2) | ||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.stable"), 3) | ||||
| } | ||||
|  | ||||
| func TestCreateReleasePreRelease(t *testing.T) { | ||||
| @@ -92,7 +92,7 @@ func TestCreateReleasePreRelease(t *testing.T) { | ||||
| 	session := loginUser(t, "user2") | ||||
| 	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"), 2) | ||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.prerelease"), 3) | ||||
| } | ||||
|  | ||||
| func TestCreateReleaseDraft(t *testing.T) { | ||||
| @@ -101,7 +101,7 @@ func TestCreateReleaseDraft(t *testing.T) { | ||||
| 	session := loginUser(t, "user2") | ||||
| 	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"), 2) | ||||
| 	checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.draft"), 3) | ||||
| } | ||||
|  | ||||
| func TestCreateReleasePaging(t *testing.T) { | ||||
|   | ||||
| @@ -27,3 +27,19 @@ | ||||
|   is_prerelease: false | ||||
|   is_tag: false | ||||
|   created_unix: 946684800 | ||||
|  | ||||
| - | ||||
|   id: 3 | ||||
|   repo_id: 1 | ||||
|   publisher_id: 2 | ||||
|   tag_name: "delete-tag" | ||||
|   lower_tag_name: "delete-tag" | ||||
|   target: "master" | ||||
|   title: "delete-tag" | ||||
|   sha1: "65f1bf27bc3bf70f64657658635e66094edbcb4d" | ||||
|   num_commits: 10 | ||||
|   is_draft: false | ||||
|   is_prerelease: false | ||||
|   is_tag: true | ||||
|   created_unix: 946684800 | ||||
|  | ||||
|   | ||||
| @@ -61,6 +61,10 @@ type APIForbiddenError struct { | ||||
| // swagger:response notFound | ||||
| type APINotFound struct{} | ||||
|  | ||||
| //APIConflict is a conflict empty response | ||||
| // swagger:response conflict | ||||
| type APIConflict struct{} | ||||
|  | ||||
| //APIRedirect is a redirect response | ||||
| // swagger:response redirect | ||||
| type APIRedirect struct{} | ||||
|   | ||||
| @@ -798,7 +798,9 @@ func RegisterRoutes(m *macaron.Macaron) { | ||||
| 						}) | ||||
| 					}) | ||||
| 					m.Group("/tags", func() { | ||||
| 						m.Get("/:tag", repo.GetReleaseTag) | ||||
| 						m.Combo("/:tag"). | ||||
| 							Get(repo.GetReleaseTag). | ||||
| 							Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseTag) | ||||
| 					}) | ||||
| 				}, reqRepoReader(models.UnitTypeReleases)) | ||||
| 				m.Post("/mirror-sync", reqToken(), reqRepoWriter(models.UnitTypeCode), repo.MirrorSync) | ||||
|   | ||||
| @@ -5,11 +5,13 @@ | ||||
| package repo | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/convert" | ||||
| 	releaseservice "code.gitea.io/gitea/services/release" | ||||
| ) | ||||
|  | ||||
| // GetReleaseTag get a single release of a repository by its tagname | ||||
| @@ -59,3 +61,56 @@ func GetReleaseTag(ctx *context.APIContext) { | ||||
| 	} | ||||
| 	ctx.JSON(http.StatusOK, convert.ToRelease(release)) | ||||
| } | ||||
|  | ||||
| // DeleteReleaseTag delete a tag from a repository | ||||
| func DeleteReleaseTag(ctx *context.APIContext) { | ||||
| 	// swagger:operation DELETE /repos/{owner}/{repo}/releases/tags/{tag} repository repoDeleteReleaseTag | ||||
| 	// --- | ||||
| 	// summary: Delete a release tag | ||||
| 	// 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: name of the tag to delete | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// responses: | ||||
| 	//   "204": | ||||
| 	//     "$ref": "#/responses/empty" | ||||
| 	//   "404": | ||||
| 	//     "$ref": "#/responses/notFound" | ||||
| 	//   "409": | ||||
| 	//     "$ref": "#/responses/conflict" | ||||
|  | ||||
| 	tag := ctx.Params(":tag") | ||||
|  | ||||
| 	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.StatusInternalServerError, "GetRelease", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if !release.IsTag { | ||||
| 		ctx.Error(http.StatusConflict, "IsTag", errors.New("a tag attached to a release cannot be deleted directly")) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := releaseservice.DeleteReleaseByID(release.ID, ctx.User, true); err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) | ||||
| 	} | ||||
|  | ||||
| 	ctx.Status(http.StatusNoContent) | ||||
| } | ||||
|   | ||||
| @@ -7834,6 +7834,47 @@ | ||||
|             "$ref": "#/responses/notFound" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "delete": { | ||||
|         "tags": [ | ||||
|           "repository" | ||||
|         ], | ||||
|         "summary": "Delete a release tag", | ||||
|         "operationId": "repoDeleteReleaseTag", | ||||
|         "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": "name of the tag to delete", | ||||
|             "name": "tag", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "204": { | ||||
|             "$ref": "#/responses/empty" | ||||
|           }, | ||||
|           "404": { | ||||
|             "$ref": "#/responses/notFound" | ||||
|           }, | ||||
|           "409": { | ||||
|             "$ref": "#/responses/conflict" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/repos/{owner}/{repo}/releases/{id}": { | ||||
| @@ -16249,6 +16290,9 @@ | ||||
|         "$ref": "#/definitions/WatchInfo" | ||||
|       } | ||||
|     }, | ||||
|     "conflict": { | ||||
|       "description": "APIConflict is a conflict empty response" | ||||
|     }, | ||||
|     "empty": { | ||||
|       "description": "APIEmpty is an empty response" | ||||
|     }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user