From 5fdb61540f26cea67353e423a74cba74e7bfe405 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 28 Apr 2026 01:31:54 +0200 Subject: [PATCH] actions: reuse preview path helpers in devtest mock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mock had its own normalizeMockArtifactPath / chooseMockArtifactPath that drifted from the production helpers (silent fallback to first file on invalid input, instead of "" — the new no-fallback semantics). Export GetRequestedPreviewPath and ChoosePreviewPath and call them from the mock so behavior stays in sync. Co-Authored-By: Claude (Opus 4.7) --- routers/web/devtest/mock_actions.go | 34 ++++++----------------------- routers/web/repo/actions/view.go | 13 ++++++----- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/routers/web/devtest/mock_actions.go b/routers/web/devtest/mock_actions.go index 4107f4a068..3437d94631 100644 --- a/routers/web/devtest/mock_actions.go +++ b/routers/web/devtest/mock_actions.go @@ -157,24 +157,12 @@ end_of_record }, } -func normalizeMockArtifactPath(path string) string { - path = util.PathJoinRelX(path) - if path == "." { - return "" +func mockArtifactFilePaths(files []mockArtifactFile) []string { + paths := make([]string, len(files)) + for i, file := range files { + paths[i] = file.Path } - return path -} - -func chooseMockArtifactPath(files []mockArtifactFile, requestedPath string) string { - if len(files) == 0 { - return "" - } - for _, file := range files { - if file.Path == requestedPath { - return requestedPath - } - } - return files[0].Path + return paths } type generateMockStepsLogOptions struct { @@ -534,11 +522,7 @@ func MockActionsArtifactPreview(ctx *context.Context) { return } - selectedPath := normalizeMockArtifactPath(strings.TrimPrefix(ctx.PathParam("*"), "/")) - if selectedPath == "" { - selectedPath = normalizeMockArtifactPath(ctx.Req.URL.Query().Get("path")) - } - selectedPath = chooseMockArtifactPath(files, selectedPath) + selectedPath := actions.ChoosePreviewPath(mockArtifactFilePaths(files), actions.GetRequestedPreviewPath(ctx)) previewFiles := make([]actions.ArtifactPreviewFile, 0, len(files)) for _, file := range files { previewFiles = append(previewFiles, actions.ArtifactPreviewFile{ @@ -568,11 +552,7 @@ func MockActionsArtifactPreviewRaw(ctx *context.Context) { return } - selectedPath := normalizeMockArtifactPath(strings.TrimPrefix(ctx.PathParam("*"), "/")) - if selectedPath == "" { - selectedPath = normalizeMockArtifactPath(ctx.Req.URL.Query().Get("path")) - } - selectedPath = chooseMockArtifactPath(files, selectedPath) + selectedPath := actions.ChoosePreviewPath(mockArtifactFilePaths(files), actions.GetRequestedPreviewPath(ctx)) if selectedPath == "" { ctx.NotFound(nil) return diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 69f02c5f4f..a09cb70965 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -1017,7 +1017,10 @@ func normalizeArtifactPreviewPath(path string) string { return path } -func getRequestedPreviewPath(ctx *context_module.Context) string { +// GetRequestedPreviewPath reads the requested artifact preview path from a +// request, accepting either the trailing `/preview/raw/*` path segment or a +// `?path=` query parameter, and normalizes it to a safe relative path. +func GetRequestedPreviewPath(ctx *context_module.Context) string { path := strings.TrimPrefix(ctx.PathParam("*"), "/") if path == "" { path = ctx.Req.URL.Query().Get("path") @@ -1033,10 +1036,10 @@ func artifactPreviewFallbackPath(artifact *actions_model.ActionArtifact) string return artifact.ArtifactName } -// choosePreviewPath resolves the preview path to render. +// ChoosePreviewPath resolves the preview path to render. // An empty `requested` means no path was specified, so the first file is selected as a default. // A non-empty `requested` that is not present in `paths` returns "" so callers can 404 instead of silently swapping to a different file. -func choosePreviewPath(paths []string, requested string) string { +func ChoosePreviewPath(paths []string, requested string) string { if len(paths) == 0 { return "" } @@ -1249,7 +1252,7 @@ func ArtifactsPreviewView(ctx *context_module.Context) { ctx.ServerError("listPreviewPaths", err) return } - selectedPath := choosePreviewPath(paths, getRequestedPreviewPath(ctx)) + selectedPath := ChoosePreviewPath(paths, GetRequestedPreviewPath(ctx)) previewFiles := make([]ArtifactPreviewFile, 0, len(paths)) for _, path := range paths { @@ -1289,7 +1292,7 @@ func ArtifactsPreviewRawView(ctx *context_module.Context) { ctx.ServerError("listPreviewPaths", err) return } - selectedPath := choosePreviewPath(paths, getRequestedPreviewPath(ctx)) + selectedPath := ChoosePreviewPath(paths, GetRequestedPreviewPath(ctx)) if selectedPath == "" { ctx.HTTPError(http.StatusNotFound, "artifact file not found") return