This commit is contained in:
@@ -66,21 +66,22 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/httplib"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
web_types "code.gitea.io/gitea/modules/web/types"
|
||||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"gitea.dev/models/actions"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/modules/httplib"
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/storage"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/web"
|
||||
web_types "gitea.dev/modules/web/types"
|
||||
actions_service "gitea.dev/services/actions"
|
||||
"gitea.dev/services/context"
|
||||
)
|
||||
|
||||
const artifactRouteBase = "/_apis/pipelines/workflows/{run_id}/artifacts"
|
||||
@@ -120,6 +121,9 @@ func ArtifactsRoutes(prefix string) *web.Router {
|
||||
m.Get("/{artifact_id}/download", r.downloadArtifact)
|
||||
})
|
||||
|
||||
// Job summary upload endpoint (GITHUB_STEP_SUMMARY).
|
||||
m.Put(jobSummaryRouteBase, uploadJobSummary)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -310,7 +314,7 @@ func (ar artifactRoutes) confirmUploadArtifact(ctx *ArtifactContext) {
|
||||
ctx.HTTPError(http.StatusBadRequest, "Error artifact name is empty")
|
||||
return
|
||||
}
|
||||
if err := mergeChunksForRun(ctx, ar.fs, runID, artifactName); err != nil {
|
||||
if err := mergeChunksForRun(ctx, ar.fs, runID, ctx.ActionTask.Job.RunAttemptID, artifactName); err != nil {
|
||||
log.Error("Error merge chunks: %v", err)
|
||||
ctx.HTTPError(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
@@ -332,14 +336,19 @@ type (
|
||||
)
|
||||
|
||||
func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) {
|
||||
_, runID, ok := validateRunID(ctx)
|
||||
task, runID, ok := validateRunID(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
attemptIDs, ok := readableArtifactAttemptIDs(ctx, task)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
artifacts, err := actions.FindReadableArtifacts(ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
RunAttemptIDs: attemptIDs,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Error getting artifacts: %v", err)
|
||||
@@ -392,7 +401,7 @@ type (
|
||||
|
||||
// getDownloadArtifactURL generates download url for each artifact
|
||||
func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
|
||||
_, runID, ok := validateRunID(ctx)
|
||||
task, runID, ok := validateRunID(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -402,10 +411,16 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
|
||||
return
|
||||
}
|
||||
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
ArtifactName: itemPath,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
attemptIDs, ok := readableArtifactAttemptIDs(ctx, task)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
artifacts, err := actions.FindReadableArtifacts(ctx, actions.FindArtifactsOptions{
|
||||
RunID: runID,
|
||||
RunAttemptIDs: attemptIDs,
|
||||
ArtifactName: itemPath,
|
||||
Status: int(actions.ArtifactStatusUploadConfirmed),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Error getting artifacts: %v", err)
|
||||
@@ -455,7 +470,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
|
||||
|
||||
// downloadArtifact downloads artifact content
|
||||
func (ar artifactRoutes) downloadArtifact(ctx *ArtifactContext) {
|
||||
_, runID, ok := validateRunID(ctx)
|
||||
task, runID, ok := validateRunID(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -477,6 +492,18 @@ func (ar artifactRoutes) downloadArtifact(ctx *ArtifactContext) {
|
||||
ctx.HTTPError(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// resolving the readable attempts costs a query, and an artifact of the task's own attempt never needs it
|
||||
if artifact.RunAttemptID != task.Job.RunAttemptID {
|
||||
attemptIDs, ok := readableArtifactAttemptIDs(ctx, task)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !slices.Contains(attemptIDs, artifact.RunAttemptID) {
|
||||
log.Error("Error artifact %d belongs to run attempt %d, which the task cannot read: %v", artifactID, artifact.RunAttemptID, attemptIDs)
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user