Skip to content

Commit 40b9f39

Browse files
author
Earl Warren
committed
Merge pull request '[FEAT]: New route to view latest run of specific workflows' (go-gitea#2304) from algernon/forgejo:f/web/actions/workflow-latest-run-routes into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2304 Reviewed-by: Earl Warren <[email protected]>
2 parents 91f2f02 + 5f2d8be commit 40b9f39

File tree

3 files changed

+112
-3
lines changed

3 files changed

+112
-3
lines changed

routers/web/repo/actions/view.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"code.gitea.io/gitea/modules/actions"
2323
"code.gitea.io/gitea/modules/base"
2424
context_module "code.gitea.io/gitea/modules/context"
25+
"code.gitea.io/gitea/modules/log"
2526
"code.gitea.io/gitea/modules/storage"
2627
"code.gitea.io/gitea/modules/timeutil"
2728
"code.gitea.io/gitea/modules/util"
@@ -60,6 +61,34 @@ func ViewLatest(ctx *context_module.Context) {
6061
ctx.Redirect(run.HTMLURL(), http.StatusTemporaryRedirect)
6162
}
6263

64+
func ViewLatestWorkflowRun(ctx *context_module.Context) {
65+
branch := ctx.FormString("branch")
66+
if branch == "" {
67+
branch = ctx.Repo.Repository.DefaultBranch
68+
}
69+
branch = fmt.Sprintf("refs/heads/%s", branch)
70+
event := ctx.FormString("event")
71+
72+
workflowFile := ctx.Params("workflow_name")
73+
run, err := actions_model.GetLatestRunForBranchAndWorkflow(ctx, ctx.Repo.Repository.ID, branch, workflowFile, event)
74+
if err != nil {
75+
if errors.Is(err, util.ErrNotExist) {
76+
ctx.NotFound("GetLatestRunForBranchAndWorkflow", err)
77+
} else {
78+
log.Error("GetLatestRunForBranchAndWorkflow: %v", err)
79+
ctx.Error(http.StatusInternalServerError, "Unable to get latest run for workflow on branch")
80+
}
81+
return
82+
}
83+
84+
err = run.LoadAttributes(ctx)
85+
if err != nil {
86+
ctx.ServerError("LoadAttributes", err)
87+
return
88+
}
89+
ctx.Redirect(run.HTMLURL(), http.StatusTemporaryRedirect)
90+
}
91+
6392
type ViewRequest struct {
6493
LogCursors []struct {
6594
Step int `json:"step"`

routers/web/web.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,10 @@ func registerRoutes(m *web.Route) {
14031403
})
14041404
})
14051405

1406-
m.Get("/workflows/{workflow_name}/badge.svg", badges.GetWorkflowBadge)
1406+
m.Group("/workflows/{workflow_name}", func() {
1407+
m.Get("/badge.svg", badges.GetWorkflowBadge)
1408+
m.Get("/runs/latest", actions.ViewLatestWorkflowRun)
1409+
})
14071410
}, reqRepoActionsReader, actions.MustEnableActions)
14081411

14091412
m.Group("/wiki", func() {

tests/integration/actions_route_test.go

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
23
// SPDX-License-Identifier: MIT
34

45
package integration
56

67
import (
8+
"context"
79
"fmt"
810
"net/http"
911
"net/url"
@@ -15,10 +17,82 @@ import (
1517
"code.gitea.io/gitea/models/unittest"
1618
user_model "code.gitea.io/gitea/models/user"
1719
files_service "code.gitea.io/gitea/services/repository/files"
20+
"code.gitea.io/gitea/tests"
1821

1922
"github.com/stretchr/testify/assert"
2023
)
2124

25+
func TestActionsWebRouteLatestWorkflowRun(t *testing.T) {
26+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
27+
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
28+
29+
// create the repo
30+
repo, _, f := CreateDeclarativeRepo(t, user2, "",
31+
[]unit_model.Type{unit_model.TypeActions}, nil,
32+
[]*files_service.ChangeRepoFile{
33+
{
34+
Operation: "create",
35+
TreePath: ".gitea/workflows/workflow-1.yml",
36+
ContentReader: strings.NewReader("name: workflow-1\non:\n push:\njobs:\n job-1:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
37+
},
38+
{
39+
Operation: "create",
40+
TreePath: ".gitea/workflows/workflow-2.yml",
41+
ContentReader: strings.NewReader("name: workflow-2\non:\n push:\njobs:\n job-2:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
42+
},
43+
},
44+
)
45+
defer f()
46+
47+
t.Run("valid workflows", func(t *testing.T) {
48+
defer tests.PrintCurrentTest(t)()
49+
50+
// helpers
51+
getWorkflowRunRedirectURI := func(workflow string) string {
52+
req := NewRequest(t, "GET", fmt.Sprintf("%s/actions/workflows/%s/runs/latest", repo.HTMLURL(), workflow))
53+
resp := MakeRequest(t, req, http.StatusTemporaryRedirect)
54+
55+
return resp.Header().Get("Location")
56+
}
57+
58+
// two runs have been created
59+
assert.Equal(t, 2, unittest.GetCount(t, &actions_model.ActionRun{RepoID: repo.ID}))
60+
61+
// Get the redirect URIs for both workflows
62+
workflowOneURI := getWorkflowRunRedirectURI("workflow-1.yml")
63+
workflowTwoURI := getWorkflowRunRedirectURI("workflow-2.yml")
64+
65+
// Verify that the two are different.
66+
assert.NotEqual(t, workflowOneURI, workflowTwoURI)
67+
68+
// Verify that each points to the correct workflow.
69+
workflowOne := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, Index: 1})
70+
err := workflowOne.LoadAttributes(context.Background())
71+
assert.NoError(t, err)
72+
assert.Equal(t, workflowOneURI, workflowOne.HTMLURL())
73+
74+
workflowTwo := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, Index: 2})
75+
err = workflowTwo.LoadAttributes(context.Background())
76+
assert.NoError(t, err)
77+
assert.Equal(t, workflowTwoURI, workflowTwo.HTMLURL())
78+
})
79+
80+
t.Run("existing workflow, non-existent branch", func(t *testing.T) {
81+
defer tests.PrintCurrentTest(t)()
82+
83+
req := NewRequest(t, "GET", fmt.Sprintf("%s/actions/workflows/workflow-1.yml/runs/latest?branch=foobar", repo.HTMLURL()))
84+
MakeRequest(t, req, http.StatusNotFound)
85+
})
86+
87+
t.Run("non-existing workflow", func(t *testing.T) {
88+
defer tests.PrintCurrentTest(t)()
89+
90+
req := NewRequest(t, "GET", fmt.Sprintf("%s/actions/workflows/workflow-3.yml/runs/latest", repo.HTMLURL()))
91+
MakeRequest(t, req, http.StatusNotFound)
92+
})
93+
})
94+
}
95+
2296
func TestActionsWebRouteLatestRun(t *testing.T) {
2397
onGiteaRun(t, func(t *testing.T, u *url.URL) {
2498
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@@ -44,7 +118,10 @@ func TestActionsWebRouteLatestRun(t *testing.T) {
44118
resp := MakeRequest(t, req, http.StatusTemporaryRedirect)
45119

46120
// Verify that it redirects to the run we just created
47-
expectedURI := fmt.Sprintf("%s/actions/runs/1", repo.HTMLURL())
48-
assert.Equal(t, expectedURI, resp.Header().Get("Location"))
121+
workflow := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID})
122+
err := workflow.LoadAttributes(context.Background())
123+
assert.NoError(t, err)
124+
125+
assert.Equal(t, workflow.HTMLURL(), resp.Header().Get("Location"))
49126
})
50127
}

0 commit comments

Comments
 (0)