Skip to content

Commit

Permalink
add DeleteArtifact api
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristopherHX committed Feb 6, 2025
1 parent 5e3c79d commit b1b0ef3
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 2 deletions.
5 changes: 4 additions & 1 deletion routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,10 @@ func Routes() *web.Router {
m.Get("/tasks", repo.ListActionTasks)
m.Get("/runs/{run}/artifacts", repo.GetArtifactsOfRun)
m.Get("/artifacts", repo.GetArtifacts)
m.Get("/artifacts/{artifact_id}", repo.GetArtifact)
m.Group("/artifacts/{artifact_id}", func() {
m.Get("", repo.GetArtifact)
m.Delete("", reqRepoWriter(unit.TypeActions), repo.DeleteArtifact)
})
m.Get("/artifacts/{artifact_id}/zip", repo.DownloadArtifact)
m.Get("/artifacts/{artifact_id}/zip/raw", repo.DownloadArtifactRaw)
}, reqRepoReader(unit.TypeActions), context.ReferencesGitRepo(true))
Expand Down
48 changes: 48 additions & 0 deletions routers/api/v1/repo/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,54 @@ func GetArtifact(ctx *context.APIContext) {
ctx.Error(http.StatusNotFound, "artifact not found", fmt.Errorf("artifact not found"))
}

// DeleteArtifact Deletes a specific artifact for a workflow run.
func DeleteArtifact(ctx *context.APIContext) {
// swagger:operation DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id} repository deleteArtifact
// ---
// summary: Deletes a specific artifact for a workflow run
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: artifact_id
// in: path
// description: id of the artifact
// type: string
// required: true
// responses:
// "204":
// description: "No Content"
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"

art, ok := getArtifactByID(ctx)
if !ok {
return
}

if actions.IsArtifactV4(art) {
if err := actions_model.SetArtifactNeedDelete(ctx, art.RunID, art.ArtifactName); err != nil {
ctx.Error(http.StatusInternalServerError, err.Error(), err)
return
}
ctx.Status(http.StatusNoContent)
return
}
// v3 not supported due to not having one unique id
ctx.Error(http.StatusNotFound, "artifact not found", fmt.Errorf("artifact not found"))
}

// DownloadArtifact Downloads a specific artifact for a workflow run redirects to blob url.
func DownloadArtifact(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/zip repository downloadArtifact
Expand Down
44 changes: 44 additions & 0 deletions templates/swagger/v1_json.tmpl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 49 additions & 1 deletion tests/integration/api_actions_artifact_v4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ func TestActionsArtifactV4DownloadArtifactCorrectRepoOwnerFound(t *testing.T) {
session := loginUser(t, user.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)

// confirm artifacts of wrong owner or repo is not visible
// confirm artifacts of correct owner and repo is visible
req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d/zip", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusFound)
Expand Down Expand Up @@ -514,3 +514,51 @@ func TestActionsArtifactV4Delete(t *testing.T) {
protojson.Unmarshal(resp.Body.Bytes(), &deleteResp)
assert.True(t, deleteResp.Ok)
}

func TestActionsArtifactV4DeletePublicApi(t *testing.T) {
defer prepareTestEnvActionsArtifacts(t)()

repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
session := loginUser(t, user.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)

// confirm artifacts exists
req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)

// delete artifact by id
req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)

// confirm artifacts has been deleted
req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
}

func TestActionsArtifactV4DeletePublicApiNotAllowedReadScope(t *testing.T) {
defer prepareTestEnvActionsArtifacts(t)()

repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
session := loginUser(t, user.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)

// confirm artifacts exists
req := NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)

// try delete artifact by id
req = NewRequestWithBody(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusForbidden)

// confirm artifacts has not been deleted
req = NewRequestWithBody(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/artifacts/%d", repo.FullName(), 22), nil).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)
}

0 comments on commit b1b0ef3

Please sign in to comment.