gitea源码

actions_log_test.go 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strconv"
  9. "strings"
  10. "testing"
  11. "time"
  12. actions_model "code.gitea.io/gitea/models/actions"
  13. auth_model "code.gitea.io/gitea/models/auth"
  14. repo_model "code.gitea.io/gitea/models/repo"
  15. "code.gitea.io/gitea/models/unittest"
  16. user_model "code.gitea.io/gitea/models/user"
  17. "code.gitea.io/gitea/modules/setting"
  18. "code.gitea.io/gitea/modules/storage"
  19. "code.gitea.io/gitea/modules/test"
  20. runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
  21. "github.com/stretchr/testify/assert"
  22. "google.golang.org/protobuf/types/known/timestamppb"
  23. )
  24. func TestDownloadTaskLogs(t *testing.T) {
  25. now := time.Now()
  26. testCases := []struct {
  27. treePath string
  28. fileContent string
  29. outcome []*mockTaskOutcome
  30. zstdEnabled bool
  31. }{
  32. {
  33. treePath: ".gitea/workflows/download-task-logs-zstd.yml",
  34. fileContent: `name: download-task-logs-zstd
  35. on:
  36. push:
  37. paths:
  38. - '.gitea/workflows/download-task-logs-zstd.yml'
  39. jobs:
  40. job1:
  41. runs-on: ubuntu-latest
  42. steps:
  43. - run: echo job1 with zstd enabled
  44. job2:
  45. runs-on: ubuntu-latest
  46. steps:
  47. - run: echo job2 with zstd enabled
  48. `,
  49. outcome: []*mockTaskOutcome{
  50. {
  51. result: runnerv1.Result_RESULT_SUCCESS,
  52. logRows: []*runnerv1.LogRow{
  53. {
  54. Time: timestamppb.New(now.Add(1 * time.Second)),
  55. Content: " \U0001F433 docker create image",
  56. },
  57. {
  58. Time: timestamppb.New(now.Add(2 * time.Second)),
  59. Content: "job1 zstd enabled",
  60. },
  61. {
  62. Time: timestamppb.New(now.Add(3 * time.Second)),
  63. Content: "\U0001F3C1 Job succeeded",
  64. },
  65. },
  66. },
  67. {
  68. result: runnerv1.Result_RESULT_SUCCESS,
  69. logRows: []*runnerv1.LogRow{
  70. {
  71. Time: timestamppb.New(now.Add(1 * time.Second)),
  72. Content: " \U0001F433 docker create image",
  73. },
  74. {
  75. Time: timestamppb.New(now.Add(2 * time.Second)),
  76. Content: "job2 zstd enabled",
  77. },
  78. {
  79. Time: timestamppb.New(now.Add(3 * time.Second)),
  80. Content: "\U0001F3C1 Job succeeded",
  81. },
  82. },
  83. },
  84. },
  85. zstdEnabled: true,
  86. },
  87. {
  88. treePath: ".gitea/workflows/download-task-logs-no-zstd.yml",
  89. fileContent: `name: download-task-logs-no-zstd
  90. on:
  91. push:
  92. paths:
  93. - '.gitea/workflows/download-task-logs-no-zstd.yml'
  94. jobs:
  95. job1:
  96. runs-on: ubuntu-latest
  97. steps:
  98. - run: echo job1 with zstd disabled
  99. job2:
  100. runs-on: ubuntu-latest
  101. steps:
  102. - run: echo job2 with zstd disabled
  103. `,
  104. outcome: []*mockTaskOutcome{
  105. {
  106. result: runnerv1.Result_RESULT_SUCCESS,
  107. logRows: []*runnerv1.LogRow{
  108. {
  109. Time: timestamppb.New(now.Add(4 * time.Second)),
  110. Content: " \U0001F433 docker create image",
  111. },
  112. {
  113. Time: timestamppb.New(now.Add(5 * time.Second)),
  114. Content: "job1 zstd disabled",
  115. },
  116. {
  117. Time: timestamppb.New(now.Add(6 * time.Second)),
  118. Content: "\U0001F3C1 Job succeeded",
  119. },
  120. },
  121. },
  122. {
  123. result: runnerv1.Result_RESULT_SUCCESS,
  124. logRows: []*runnerv1.LogRow{
  125. {
  126. Time: timestamppb.New(now.Add(4 * time.Second)),
  127. Content: " \U0001F433 docker create image",
  128. },
  129. {
  130. Time: timestamppb.New(now.Add(5 * time.Second)),
  131. Content: "job2 zstd disabled",
  132. },
  133. {
  134. Time: timestamppb.New(now.Add(6 * time.Second)),
  135. Content: "\U0001F3C1 Job succeeded",
  136. },
  137. },
  138. },
  139. },
  140. zstdEnabled: false,
  141. },
  142. }
  143. onGiteaRun(t, func(t *testing.T, u *url.URL) {
  144. user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  145. session := loginUser(t, user2.Name)
  146. token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  147. apiRepo := createActionsTestRepo(t, token, "actions-download-task-logs", false)
  148. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
  149. runner := newMockRunner()
  150. runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
  151. for _, tc := range testCases {
  152. t.Run("test "+tc.treePath, func(t *testing.T) {
  153. var resetFunc func()
  154. if tc.zstdEnabled {
  155. resetFunc = test.MockVariableValue(&setting.Actions.LogCompression, "zstd")
  156. assert.True(t, setting.Actions.LogCompression.IsZstd())
  157. } else {
  158. resetFunc = test.MockVariableValue(&setting.Actions.LogCompression, "none")
  159. assert.False(t, setting.Actions.LogCompression.IsZstd())
  160. }
  161. // create the workflow file
  162. opts := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+tc.treePath, tc.fileContent)
  163. createWorkflowFile(t, token, user2.Name, repo.Name, tc.treePath, opts)
  164. // fetch and execute tasks
  165. for jobIndex, outcome := range tc.outcome {
  166. task := runner.fetchTask(t)
  167. runner.execTask(t, task, outcome)
  168. // check whether the log file exists
  169. logFileName := fmt.Sprintf("%s/%02x/%d.log", repo.FullName(), task.Id%256, task.Id)
  170. if setting.Actions.LogCompression.IsZstd() {
  171. logFileName += ".zst"
  172. }
  173. _, err := storage.Actions.Stat(logFileName)
  174. assert.NoError(t, err)
  175. // download task logs and check content
  176. runIndex := task.Context.GetFields()["run_number"].GetStringValue()
  177. req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/actions/runs/%s/jobs/%d/logs", user2.Name, repo.Name, runIndex, jobIndex)).
  178. AddTokenAuth(token)
  179. resp := MakeRequest(t, req, http.StatusOK)
  180. logTextLines := strings.Split(strings.TrimSpace(resp.Body.String()), "\n")
  181. assert.Len(t, logTextLines, len(outcome.logRows))
  182. for idx, lr := range outcome.logRows {
  183. assert.Equal(
  184. t,
  185. fmt.Sprintf("%s %s", lr.Time.AsTime().Format("2006-01-02T15:04:05.0000000Z07:00"), lr.Content),
  186. logTextLines[idx],
  187. )
  188. }
  189. runID, _ := strconv.ParseInt(task.Context.GetFields()["run_id"].GetStringValue(), 10, 64)
  190. jobs, err := actions_model.GetRunJobsByRunID(t.Context(), runID)
  191. assert.NoError(t, err)
  192. assert.Len(t, jobs, len(tc.outcome))
  193. jobID := jobs[jobIndex].ID
  194. // download task logs from API and check content
  195. req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/jobs/%d/logs", user2.Name, repo.Name, jobID)).
  196. AddTokenAuth(token)
  197. resp = MakeRequest(t, req, http.StatusOK)
  198. logTextLines = strings.Split(strings.TrimSpace(resp.Body.String()), "\n")
  199. assert.Len(t, logTextLines, len(outcome.logRows))
  200. for idx, lr := range outcome.logRows {
  201. assert.Equal(
  202. t,
  203. fmt.Sprintf("%s %s", lr.Time.AsTime().Format("2006-01-02T15:04:05.0000000Z07:00"), lr.Content),
  204. logTextLines[idx],
  205. )
  206. }
  207. }
  208. resetFunc()
  209. })
  210. }
  211. })
  212. }