gitea源码

mock_actions.go 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package devtest
  4. import (
  5. mathRand "math/rand/v2"
  6. "net/http"
  7. "strconv"
  8. "strings"
  9. "time"
  10. actions_model "code.gitea.io/gitea/models/actions"
  11. "code.gitea.io/gitea/modules/util"
  12. "code.gitea.io/gitea/modules/web"
  13. "code.gitea.io/gitea/routers/web/repo/actions"
  14. "code.gitea.io/gitea/services/context"
  15. )
  16. func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewStepLog) {
  17. mockedLogs := []string{
  18. "::group::test group for: step={step}, cursor={cursor}",
  19. "in group msg for: step={step}, cursor={cursor}",
  20. "in group msg for: step={step}, cursor={cursor}",
  21. "in group msg for: step={step}, cursor={cursor}",
  22. "::endgroup::",
  23. "message for: step={step}, cursor={cursor}",
  24. "message for: step={step}, cursor={cursor}",
  25. "##[group]test group for: step={step}, cursor={cursor}",
  26. "in group msg for: step={step}, cursor={cursor}",
  27. "##[endgroup]",
  28. }
  29. cur := logCur.Cursor // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally
  30. mockCount := util.Iif(logCur.Step == 0, 3, 1)
  31. if logCur.Step == 1 && logCur.Cursor == 0 {
  32. mockCount = 30 // for the first batch, return as many as possible to test the auto-expand and auto-scroll
  33. }
  34. for i := 0; i < mockCount; i++ {
  35. logStr := mockedLogs[int(cur)%len(mockedLogs)]
  36. cur++
  37. logStr = strings.ReplaceAll(logStr, "{step}", strconv.Itoa(logCur.Step))
  38. logStr = strings.ReplaceAll(logStr, "{cursor}", strconv.FormatInt(cur, 10))
  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. func MockActionsView(ctx *context.Context) {
  51. ctx.Data["RunID"] = ctx.PathParam("run")
  52. ctx.Data["JobID"] = ctx.PathParam("job")
  53. ctx.HTML(http.StatusOK, "devtest/repo-action-view")
  54. }
  55. func MockActionsRunsJobs(ctx *context.Context) {
  56. runID := ctx.PathParamInt64("run")
  57. req := web.GetForm(ctx).(*actions.ViewRequest)
  58. resp := &actions.ViewResponse{}
  59. resp.State.Run.TitleHTML = `mock run title <a href="/">link</a>`
  60. resp.State.Run.Status = actions_model.StatusRunning.String()
  61. resp.State.Run.CanCancel = runID == 10
  62. resp.State.Run.CanApprove = runID == 20
  63. resp.State.Run.CanRerun = runID == 30
  64. resp.State.Run.CanDeleteArtifact = true
  65. resp.State.Run.WorkflowID = "workflow-id"
  66. resp.State.Run.WorkflowLink = "./workflow-link"
  67. resp.State.Run.Commit = actions.ViewCommit{
  68. ShortSha: "ccccdddd",
  69. Link: "./commit-link",
  70. Pusher: actions.ViewUser{
  71. DisplayName: "pusher user",
  72. Link: "./pusher-link",
  73. },
  74. Branch: actions.ViewBranch{
  75. Name: "commit-branch",
  76. Link: "./branch-link",
  77. IsDeleted: false,
  78. },
  79. }
  80. resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
  81. Name: "artifact-a",
  82. Size: 100 * 1024,
  83. Status: "expired",
  84. })
  85. resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
  86. Name: "artifact-b",
  87. Size: 1024 * 1024,
  88. Status: "completed",
  89. })
  90. resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
  91. Name: "artifact-very-loooooooooooooooooooooooooooooooooooooooooooooooooooooooong",
  92. Size: 100 * 1024,
  93. Status: "expired",
  94. })
  95. resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
  96. Name: "artifact-really-loooooooooooooooooooooooooooooooooooooooooooooooooooooooong",
  97. Size: 1024 * 1024,
  98. Status: "completed",
  99. })
  100. resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
  101. ID: runID * 10,
  102. Name: "job 100",
  103. Status: actions_model.StatusRunning.String(),
  104. CanRerun: true,
  105. Duration: "1h",
  106. })
  107. resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
  108. ID: runID*10 + 1,
  109. Name: "job 101",
  110. Status: actions_model.StatusWaiting.String(),
  111. CanRerun: false,
  112. Duration: "2h",
  113. })
  114. resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{
  115. ID: runID*10 + 2,
  116. Name: "job 102",
  117. Status: actions_model.StatusFailure.String(),
  118. CanRerun: false,
  119. Duration: "3h",
  120. })
  121. resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
  122. Summary: "step 0 (mock slow)",
  123. Duration: time.Hour.String(),
  124. Status: actions_model.StatusRunning.String(),
  125. })
  126. resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
  127. Summary: "step 1 (mock fast)",
  128. Duration: time.Hour.String(),
  129. Status: actions_model.StatusRunning.String(),
  130. })
  131. resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{
  132. Summary: "step 2 (mock error)",
  133. Duration: time.Hour.String(),
  134. Status: actions_model.StatusRunning.String(),
  135. })
  136. if len(req.LogCursors) == 0 {
  137. ctx.JSON(http.StatusOK, resp)
  138. return
  139. }
  140. resp.Logs.StepsLog = []*actions.ViewStepLog{}
  141. doSlowResponse := false
  142. doErrorResponse := false
  143. for _, logCur := range req.LogCursors {
  144. if !logCur.Expanded {
  145. continue
  146. }
  147. doSlowResponse = doSlowResponse || logCur.Step == 0
  148. doErrorResponse = doErrorResponse || logCur.Step == 2
  149. resp.Logs.StepsLog = append(resp.Logs.StepsLog, generateMockStepsLog(logCur)...)
  150. }
  151. if doErrorResponse {
  152. if mathRand.Float64() > 0.5 {
  153. ctx.HTTPError(http.StatusInternalServerError, "devtest mock error response")
  154. return
  155. }
  156. }
  157. if doSlowResponse {
  158. time.Sleep(time.Duration(3000) * time.Millisecond)
  159. } else {
  160. time.Sleep(time.Duration(100) * time.Millisecond) // actually, frontend reload every 1 second, any smaller delay is fine
  161. }
  162. ctx.JSON(http.StatusOK, resp)
  163. }