Skip to content

Commit 8580dca

Browse files
committed
fix
1 parent 838653d commit 8580dca

File tree

5 files changed

+278
-148
lines changed

5 files changed

+278
-148
lines changed

routers/web/devtest/mock_actions.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package devtest
5+
6+
import (
7+
"fmt"
8+
mathRand "math/rand/v2"
9+
"net/http"
10+
"strings"
11+
"time"
12+
13+
actions_model "code.gitea.io/gitea/models/actions"
14+
"code.gitea.io/gitea/modules/util"
15+
"code.gitea.io/gitea/modules/web"
16+
"code.gitea.io/gitea/routers/web/repo/actions"
17+
"code.gitea.io/gitea/services/context"
18+
)
19+
20+
func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewStepLog) {
21+
mockedLogs := []string{
22+
"::group::test group for: step={step}, cursor={cursor}",
23+
"in group msg for: step={step}, cursor={cursor}",
24+
"in group msg for: step={step}, cursor={cursor}",
25+
"in group msg for: step={step}, cursor={cursor}",
26+
"::endgroup::",
27+
"message for: step={step}, cursor={cursor}",
28+
"message for: step={step}, cursor={cursor}",
29+
"message for: step={step}, cursor={cursor}",
30+
"message for: step={step}, cursor={cursor}",
31+
"message for: step={step}, cursor={cursor}",
32+
}
33+
cur := logCur.Cursor // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally
34+
for i := 0; i < util.Iif(logCur.Step == 0, 3, 1); i++ {
35+
logStr := mockedLogs[int(cur)%len(mockedLogs)]
36+
cur++
37+
logStr = strings.ReplaceAll(logStr, "{step}", fmt.Sprintf("%d", logCur.Step))
38+
logStr = strings.ReplaceAll(logStr, "{cursor}", fmt.Sprintf("%d", cur))
39+
stepsLog = append(stepsLog, &actions.ViewStepLog{
40+
Step: logCur.Step,
41+
Cursor: cur,
42+
Started: time.Now().Unix() - 1,
43+
Lines: []*actions.ViewStepLogLine{
44+
{Index: cur, Message: logStr, Timestamp: float64(time.Now().UnixNano()) / float64(time.Second)},
45+
},
46+
})
47+
}
48+
return stepsLog
49+
}
50+
51+
func MockActionsRunsJobs(ctx *context.Context) {
52+
req := web.GetForm(ctx).(*actions.ViewRequest)
53+
54+
resp := &actions.ViewResponse{}
55+
resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
56+
Name: "artifact-a",
57+
Size: 100 * 1024,
58+
Status: "expired",
59+
})
60+
resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
61+
Name: "artifact-b",
62+
Size: 1024 * 1024,
63+
Status: "completed",
64+
})
65+
resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
66+
Summary: "step 0 (mock slow)",
67+
Duration: time.Hour.String(),
68+
Status: actions_model.StatusRunning.String(),
69+
})
70+
resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
71+
Summary: "step 1 (mock fast)",
72+
Duration: time.Hour.String(),
73+
Status: actions_model.StatusRunning.String(),
74+
})
75+
resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
76+
Summary: "step 2 (mock error)",
77+
Duration: time.Hour.String(),
78+
Status: actions_model.StatusRunning.String(),
79+
})
80+
if len(req.LogCursors) == 0 {
81+
ctx.JSON(http.StatusOK, resp)
82+
return
83+
}
84+
85+
resp.Logs.StepsLog = []*actions.ViewStepLog{}
86+
doSlowResponse := false
87+
doErrorResponse := false
88+
for _, logCur := range req.LogCursors {
89+
if !logCur.Expanded {
90+
continue
91+
}
92+
doSlowResponse = doSlowResponse || logCur.Step == 0
93+
doErrorResponse = doErrorResponse || logCur.Step == 2
94+
resp.Logs.StepsLog = append(resp.Logs.StepsLog, generateMockStepsLog(logCur)...)
95+
}
96+
if doErrorResponse {
97+
if mathRand.Float64() > 0.5 {
98+
ctx.Error(http.StatusInternalServerError, "devtest mock error response")
99+
return
100+
}
101+
}
102+
if doSlowResponse {
103+
time.Sleep(time.Duration(3000) * time.Millisecond)
104+
} else {
105+
time.Sleep(time.Duration(100) * time.Millisecond) // actually, frontend reload every 1 second, any smaller delay is fine
106+
}
107+
ctx.JSON(http.StatusOK, resp)
108+
}

routers/web/repo/actions/view.go

Lines changed: 46 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,25 @@ func View(ctx *context_module.Context) {
6666
ctx.HTML(http.StatusOK, tplViewActions)
6767
}
6868

69+
type LogCursor struct {
70+
Step int `json:"step"`
71+
Cursor int64 `json:"cursor"`
72+
Expanded bool `json:"expanded"`
73+
}
74+
6975
type ViewRequest struct {
70-
LogCursors []struct {
71-
Step int `json:"step"`
72-
Cursor int64 `json:"cursor"`
73-
Expanded bool `json:"expanded"`
74-
} `json:"logCursors"`
76+
LogCursors []LogCursor `json:"logCursors"`
77+
}
78+
79+
type ArtifactsViewItem struct {
80+
Name string `json:"name"`
81+
Size int64 `json:"size"`
82+
Status string `json:"status"`
7583
}
7684

7785
type ViewResponse struct {
86+
Artifacts []*ArtifactsViewItem `json:"artifacts"`
87+
7888
State struct {
7989
Run struct {
8090
Link string `json:"link"`
@@ -146,6 +156,25 @@ type ViewStepLogLine struct {
146156
Timestamp float64 `json:"timestamp"`
147157
}
148158

159+
func getActionsViewArtifacts(ctx context.Context, repoID, runIndex int64) (artifactsViewItems []*ArtifactsViewItem, err error) {
160+
run, err := actions_model.GetRunByIndex(ctx, repoID, runIndex)
161+
if err != nil {
162+
return nil, err
163+
}
164+
artifacts, err := actions_model.ListUploadedArtifactsMeta(ctx, run.ID)
165+
if err != nil {
166+
return nil, err
167+
}
168+
for _, art := range artifacts {
169+
artifactsViewItems = append(artifactsViewItems, &ArtifactsViewItem{
170+
Name: art.ArtifactName,
171+
Size: art.FileSize,
172+
Status: util.Iif(art.Status == actions_model.ArtifactStatusExpired, "expired", "completed"),
173+
})
174+
}
175+
return artifactsViewItems, nil
176+
}
177+
149178
func ViewPost(ctx *context_module.Context) {
150179
req := web.GetForm(ctx).(*ViewRequest)
151180
runIndex := getRunIndex(ctx)
@@ -157,11 +186,19 @@ func ViewPost(ctx *context_module.Context) {
157186
}
158187
run := current.Run
159188
if err := run.LoadAttributes(ctx); err != nil {
160-
ctx.Error(http.StatusInternalServerError, err.Error())
189+
ctx.ServerError("run.LoadAttributes", err)
161190
return
162191
}
163192

193+
var err error
164194
resp := &ViewResponse{}
195+
resp.Artifacts, err = getActionsViewArtifacts(ctx, ctx.Repo.Repository.ID, runIndex)
196+
if err != nil {
197+
if !errors.Is(err, util.ErrNotExist) {
198+
ctx.ServerError("getActionsViewArtifacts", err)
199+
return
200+
}
201+
}
165202

166203
resp.State.Run.Title = run.Title
167204
resp.State.Run.Link = run.Link()
@@ -205,12 +242,12 @@ func ViewPost(ctx *context_module.Context) {
205242
var err error
206243
task, err = actions_model.GetTaskByID(ctx, current.TaskID)
207244
if err != nil {
208-
ctx.Error(http.StatusInternalServerError, err.Error())
245+
ctx.ServerError("actions_model.GetTaskByID", err)
209246
return
210247
}
211248
task.Job = current
212249
if err := task.LoadAttributes(ctx); err != nil {
213-
ctx.Error(http.StatusInternalServerError, err.Error())
250+
ctx.ServerError("task.LoadAttributes", err)
214251
return
215252
}
216253
}
@@ -278,7 +315,7 @@ func ViewPost(ctx *context_module.Context) {
278315
offset := task.LogIndexes[index]
279316
logRows, err := actions.ReadLogs(ctx, task.LogInStorage, task.LogFilename, offset, length)
280317
if err != nil {
281-
ctx.Error(http.StatusInternalServerError, err.Error())
318+
ctx.ServerError("actions.ReadLogs", err)
282319
return
283320
}
284321

@@ -555,49 +592,6 @@ func getRunJobs(ctx *context_module.Context, runIndex, jobIndex int64) (*actions
555592
return jobs[0], jobs
556593
}
557594

558-
type ArtifactsViewResponse struct {
559-
Artifacts []*ArtifactsViewItem `json:"artifacts"`
560-
}
561-
562-
type ArtifactsViewItem struct {
563-
Name string `json:"name"`
564-
Size int64 `json:"size"`
565-
Status string `json:"status"`
566-
}
567-
568-
func ArtifactsView(ctx *context_module.Context) {
569-
runIndex := getRunIndex(ctx)
570-
run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
571-
if err != nil {
572-
if errors.Is(err, util.ErrNotExist) {
573-
ctx.Error(http.StatusNotFound, err.Error())
574-
return
575-
}
576-
ctx.Error(http.StatusInternalServerError, err.Error())
577-
return
578-
}
579-
artifacts, err := actions_model.ListUploadedArtifactsMeta(ctx, run.ID)
580-
if err != nil {
581-
ctx.Error(http.StatusInternalServerError, err.Error())
582-
return
583-
}
584-
artifactsResponse := ArtifactsViewResponse{
585-
Artifacts: make([]*ArtifactsViewItem, 0, len(artifacts)),
586-
}
587-
for _, art := range artifacts {
588-
status := "completed"
589-
if art.Status == actions_model.ArtifactStatusExpired {
590-
status = "expired"
591-
}
592-
artifactsResponse.Artifacts = append(artifactsResponse.Artifacts, &ArtifactsViewItem{
593-
Name: art.ArtifactName,
594-
Size: art.FileSize,
595-
Status: status,
596-
})
597-
}
598-
ctx.JSON(http.StatusOK, artifactsResponse)
599-
}
600-
601595
func ArtifactsDeleteView(ctx *context_module.Context) {
602596
if !ctx.Repo.CanWrite(unit.TypeActions) {
603597
ctx.Error(http.StatusForbidden, "no permission")

routers/web/web.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,6 @@ func registerRoutes(m *web.Router) {
14231423
})
14241424
m.Post("/cancel", reqRepoActionsWriter, actions.Cancel)
14251425
m.Post("/approve", reqRepoActionsWriter, actions.Approve)
1426-
m.Get("/artifacts", actions.ArtifactsView)
14271426
m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView)
14281427
m.Delete("/artifacts/{artifact_name}", actions.ArtifactsDeleteView)
14291428
m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
@@ -1625,9 +1624,12 @@ func registerRoutes(m *web.Router) {
16251624
}
16261625

16271626
if !setting.IsProd {
1628-
m.Any("/devtest", devtest.List)
1629-
m.Any("/devtest/fetch-action-test", devtest.FetchActionTest)
1630-
m.Any("/devtest/{sub}", devtest.Tmpl)
1627+
m.Group("/devtest", func() {
1628+
m.Any("", devtest.List)
1629+
m.Any("/fetch-action-test", devtest.FetchActionTest)
1630+
m.Any("/{sub}", devtest.Tmpl)
1631+
m.Post("/actions-mock/runs/{run}/jobs/{job}", web.Bind(actions.ViewRequest{}), devtest.MockActionsRunsJobs)
1632+
})
16311633
}
16321634

16331635
m.NotFound(func(w http.ResponseWriter, req *http.Request) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{{template "base/head" .}}
2+
<div class="page-content">
3+
<div id="repo-action-view"
4+
data-run-index="1"
5+
data-job-index="2"
6+
data-actions-url="{{AppSubUrl}}/devtest/actions-mock"
7+
data-locale-approve="approve"
8+
data-locale-cancel="cancel"
9+
data-locale-rerun="re-run"
10+
data-locale-rerun-all="re-run all"
11+
data-locale-runs-scheduled="scheduled"
12+
data-locale-runs-commit="commit"
13+
data-locale-runs-pushed-by="pushed by"
14+
data-locale-status-unknown="unknown"
15+
data-locale-status-waiting="waiting"
16+
data-locale-status-running="running"
17+
data-locale-status-success="success"
18+
data-locale-status-failure="failure"
19+
data-locale-status-cancelled="cancelled"
20+
data-locale-status-skipped="skipped"
21+
data-locale-status-blocked="blocked"
22+
data-locale-artifacts-title="artifacts"
23+
data-locale-confirm-delete-artifact="confirm delete artifact"
24+
data-locale-show-timestamps="show timestamps"
25+
data-locale-show-log-seconds="show log seconds"
26+
data-locale-show-full-screen="show full screen"
27+
data-locale-download-logs="download logs"
28+
></div>
29+
</div>
30+
{{template "base/footer" .}}

0 commit comments

Comments
 (0)