mirror of
https://github.com/go-gitea/gitea.git
synced 2025-05-01 13:15:12 +00:00
actions artifacts api list/download check status upload confirmed (#34273)
* fixes a fixture status to upload confirmed * add another fixture as noise to break tests as soon they are exposed to api * v4 delete test added check that artifact is no longer visible in internal api with status pending delete * removal of http 404 on empty list: actions/upload-artifact@v4 now backoff on http 404 of ListArtifacts endpoint * fixes artifacts with pending delete etc. are able to be found and downloaded if the storage is not freed
This commit is contained in:
parent
533b8b2d3d
commit
4ed07244b9
@ -30,6 +30,25 @@ const (
|
||||
ArtifactStatusDeleted // 6, ArtifactStatusDeleted is the status of an artifact that is deleted
|
||||
)
|
||||
|
||||
func (status ArtifactStatus) ToString() string {
|
||||
switch status {
|
||||
case ArtifactStatusUploadPending:
|
||||
return "upload is not yet completed"
|
||||
case ArtifactStatusUploadConfirmed:
|
||||
return "upload is completed"
|
||||
case ArtifactStatusUploadError:
|
||||
return "upload failed"
|
||||
case ArtifactStatusExpired:
|
||||
return "expired"
|
||||
case ArtifactStatusPendingDeletion:
|
||||
return "pending deletion"
|
||||
case ArtifactStatusDeleted:
|
||||
return "deleted"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(ActionArtifact))
|
||||
}
|
||||
|
@ -11,6 +11,24 @@
|
||||
content_encoding: ""
|
||||
artifact_path: "abc.txt"
|
||||
artifact_name: "artifact-download"
|
||||
status: 2
|
||||
created_unix: 1712338649
|
||||
updated_unix: 1712338649
|
||||
expired_unix: 1720114649
|
||||
|
||||
-
|
||||
id: 2
|
||||
run_id: 791
|
||||
runner_id: 1
|
||||
repo_id: 4
|
||||
owner_id: 1
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
storage_path: ""
|
||||
file_size: 1024
|
||||
file_compressed_size: 1024
|
||||
content_encoding: "30/20/1712348022422036662.chunk"
|
||||
artifact_path: "abc.txt"
|
||||
artifact_name: "artifact-download-incomplete"
|
||||
status: 1
|
||||
created_unix: 1712338649
|
||||
updated_unix: 1712338649
|
||||
|
@ -337,7 +337,10 @@ func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) {
|
||||
return
|
||||
}
|
||||
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID})
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Error getting artifacts: %v", err)
|
||||
ctx.HTTPError(http.StatusInternalServerError, err.Error())
|
||||
@ -402,6 +405,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
ArtifactName: itemPath,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Error getting artifacts: %v", err)
|
||||
@ -473,6 +477,11 @@ func (ar artifactRoutes) downloadArtifact(ctx *ArtifactContext) {
|
||||
ctx.HTTPError(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if artifact.Status != actions.ArtifactStatusUploadConfirmed {
|
||||
log.Error("Error artifact not found: %s", artifact.Status.ToString())
|
||||
ctx.HTTPError(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
|
||||
fd, err := ar.fs.Open(artifact.StoragePath)
|
||||
if err != nil {
|
||||
|
@ -448,17 +448,15 @@ func (r *artifactV4Routes) listArtifacts(ctx *ArtifactContext) {
|
||||
return
|
||||
}
|
||||
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{RunID: runID})
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Error getting artifacts: %v", err)
|
||||
ctx.HTTPError(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
if len(artifacts) == 0 {
|
||||
log.Debug("[artifact] handleListArtifacts, no artifacts")
|
||||
ctx.HTTPError(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
list := []*ListArtifactsResponse_MonolithArtifact{}
|
||||
|
||||
@ -510,6 +508,11 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
|
||||
ctx.HTTPError(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
if artifact.Status != actions.ArtifactStatusUploadConfirmed {
|
||||
log.Error("Error artifact not found: %s", artifact.Status.ToString())
|
||||
ctx.HTTPError(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
|
||||
respData := GetSignedArtifactURLResponse{}
|
||||
|
||||
@ -538,6 +541,11 @@ func (r *artifactV4Routes) downloadArtifact(ctx *ArtifactContext) {
|
||||
ctx.HTTPError(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
if artifact.Status != actions.ArtifactStatusUploadConfirmed {
|
||||
log.Error("Error artifact not found: %s", artifact.Status.ToString())
|
||||
ctx.HTTPError(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
|
||||
file, _ := r.fs.Open(artifact.StoragePath)
|
||||
|
||||
|
@ -557,6 +557,26 @@ func TestActionsArtifactV4Delete(t *testing.T) {
|
||||
var deleteResp actions.DeleteArtifactResponse
|
||||
protojson.Unmarshal(resp.Body.Bytes(), &deleteResp)
|
||||
assert.True(t, deleteResp.Ok)
|
||||
|
||||
// confirm artifact is no longer accessible by GetSignedArtifactURL
|
||||
req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/GetSignedArtifactURL", toProtoJSON(&actions.GetSignedArtifactURLRequest{
|
||||
Name: "artifact-v4-download",
|
||||
WorkflowRunBackendId: "792",
|
||||
WorkflowJobRunBackendId: "193",
|
||||
})).
|
||||
AddTokenAuth(token)
|
||||
_ = MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// confirm artifact is no longer enumerateable by ListArtifacts and returns length == 0 without error
|
||||
req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/ListArtifacts", toProtoJSON(&actions.ListArtifactsRequest{
|
||||
NameFilter: wrapperspb.String("artifact-v4-download"),
|
||||
WorkflowRunBackendId: "792",
|
||||
WorkflowJobRunBackendId: "193",
|
||||
})).AddTokenAuth(token)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
var listResp actions.ListArtifactsResponse
|
||||
protojson.Unmarshal(resp.Body.Bytes(), &listResp)
|
||||
assert.Empty(t, listResp.Artifacts)
|
||||
}
|
||||
|
||||
func TestActionsArtifactV4DeletePublicApi(t *testing.T) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user