]> source.dussan.org Git - gitea.git/commitdiff
Add API endpoints for getting action jobs status (#26673)
authorChester <chesterip0510@gmail.com>
Wed, 1 May 2024 01:40:23 +0000 (09:40 +0800)
committerGitHub <noreply@github.com>
Wed, 1 May 2024 01:40:23 +0000 (09:40 +0800)
Sample of response, it is similar to Github actions

ref
https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository

``` json
{
    "workflow_runs": [
        {
            "id": 3,
            "name": "Explore-Gitea-Actions",
            "head_branch": "main",
            "head_sha": "6d8d29a9f7a01ded8f8aeb64341cb31ee1ab5f19",
            "run_number": 3,
            "event": "push",
            "display_title": "More job",
            "status": "success",
            "workflow_id": "demo2.yaml",
            "url": "/chester/test/actions/runs/3",
            "created_at": "2023-08-22T13:41:33-04:00",
            "updated_at": "2023-08-22T13:41:37-04:00",
            "run_started_at": "2023-08-22T13:41:33-04:00"
        },
        {
            "id": 2,
            "name": "Explore-Gitea-Actions",
            "head_branch": "main",
            "head_sha": "6d8d29a9f7a01ded8f8aeb64341cb31ee1ab5f19",
            "run_number": 2,
            "event": "push",
            "display_title": "More job",
            "status": "success",
            "workflow_id": "demo.yaml",
            "url": "/chester/test/actions/runs/2",
            "created_at": "2023-08-22T13:41:30-04:00",
            "updated_at": "2023-08-22T13:41:33-04:00",
            "run_started_at": "2023-08-22T13:41:30-04:00"
        },
        {
            "id": 1,
            "name": "Explore-Gitea-Actions",
            "head_branch": "main",
            "head_sha": "e5369ab054cae79899ba36e45ee82811a6e0acd5",
            "run_number": 1,
            "event": "push",
            "display_title": "Add job",
            "status": "failure",
            "workflow_id": "demo.yaml",
            "url": "/chester/test/actions/runs/1",
            "created_at": "2023-08-22T13:15:21-04:00",
            "updated_at": "2023-08-22T13:18:10-04:00",
            "run_started_at": "2023-08-22T13:15:21-04:00"
        }
    ],
    "total_count": 3
}
```

---------

Co-authored-by: yp05327 <576951401@qq.com>
Co-authored-by: puni9869 <80308335+puni9869@users.noreply.github.com>
modules/structs/repo_actions.go [new file with mode: 0644]
routers/api/v1/api.go
routers/api/v1/repo/actions.go [new file with mode: 0644]
routers/api/v1/swagger/repo.go
services/convert/convert.go
templates/swagger/v1_json.tmpl

diff --git a/modules/structs/repo_actions.go b/modules/structs/repo_actions.go
new file mode 100644 (file)
index 0000000..b13f344
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package structs
+
+import (
+       "time"
+)
+
+// ActionTask represents a ActionTask
+type ActionTask struct {
+       ID           int64  `json:"id"`
+       Name         string `json:"name"`
+       HeadBranch   string `json:"head_branch"`
+       HeadSHA      string `json:"head_sha"`
+       RunNumber    int64  `json:"run_number"`
+       Event        string `json:"event"`
+       DisplayTitle string `json:"display_title"`
+       Status       string `json:"status"`
+       WorkflowID   string `json:"workflow_id"`
+       URL          string `json:"url"`
+       // swagger:strfmt date-time
+       CreatedAt time.Time `json:"created_at"`
+       // swagger:strfmt date-time
+       UpdatedAt time.Time `json:"updated_at"`
+       // swagger:strfmt date-time
+       RunStartedAt time.Time `json:"run_started_at"`
+}
+
+// ActionTaskResponse returns a ActionTask
+type ActionTaskResponse struct {
+       Entries    []*ActionTask `json:"workflow_runs"`
+       TotalCount int64         `json:"total_count"`
+}
index 73071aa8df7ee489f39462691ae14563b32df521..74062c44aca326b6d98403dbc672ff619d92e51b 100644 (file)
@@ -1168,6 +1168,9 @@ func Routes() *web.Route {
                                        m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateTagOption{}), repo.CreateTag)
                                        m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteTag)
                                }, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true))
+                               m.Group("/actions", func() {
+                                       m.Get("/tasks", repo.ListActionTasks)
+                               }, reqRepoReader(unit.TypeActions), context.ReferencesGitRepo(true))
                                m.Group("/keys", func() {
                                        m.Combo("").Get(repo.ListDeployKeys).
                                                Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
diff --git a/routers/api/v1/repo/actions.go b/routers/api/v1/repo/actions.go
new file mode 100644 (file)
index 0000000..635cb4e
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+       "net/http"
+
+       actions_model "code.gitea.io/gitea/models/actions"
+       "code.gitea.io/gitea/models/db"
+       api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/routers/api/v1/utils"
+       "code.gitea.io/gitea/services/context"
+       "code.gitea.io/gitea/services/convert"
+)
+
+// ListActionTasks list all the actions of a repository
+func ListActionTasks(ctx *context.APIContext) {
+       // swagger:operation GET /repos/{owner}/{repo}/actions/tasks repository ListActionTasks
+       // ---
+       // summary: List a repository's action tasks
+       // produces:
+       // - application/json
+       // parameters:
+       // - name: owner
+       //   in: path
+       //   description: owner of the repo
+       //   type: string
+       //   required: true
+       // - name: repo
+       //   in: path
+       //   description: name of the repo
+       //   type: string
+       //   required: true
+       // - name: page
+       //   in: query
+       //   description: page number of results to return (1-based)
+       //   type: integer
+       // - name: limit
+       //   in: query
+       //   description: page size of results, default maximum page size is 50
+       //   type: integer
+       // responses:
+       //   "200":
+       //     "$ref": "#/responses/TasksList"
+       //   "400":
+       //     "$ref": "#/responses/error"
+       //   "403":
+       //     "$ref": "#/responses/forbidden"
+       //   "404":
+       //     "$ref": "#/responses/notFound"
+       //   "409":
+       //     "$ref": "#/responses/conflict"
+       //   "422":
+       //     "$ref": "#/responses/validationError"
+
+       tasks, total, err := db.FindAndCount[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{
+               ListOptions: utils.GetListOptions(ctx),
+               RepoID:      ctx.Repo.Repository.ID,
+       })
+       if err != nil {
+               ctx.Error(http.StatusInternalServerError, "ListActionTasks", err)
+               return
+       }
+
+       res := new(api.ActionTaskResponse)
+       res.TotalCount = total
+
+       res.Entries = make([]*api.ActionTask, len(tasks))
+       for i := range tasks {
+               convertedTask, err := convert.ToActionTask(ctx, tasks[i])
+               if err != nil {
+                       ctx.Error(http.StatusInternalServerError, "ToActionTask", err)
+                       return
+               }
+               res.Entries[i] = convertedTask
+       }
+
+       ctx.JSON(http.StatusOK, &res)
+}
index c3219f28d6a866756b838824682e02fc3406527e..fcd34a63a9e9ab95bf9afcecede232dd884c396a 100644 (file)
@@ -415,6 +415,13 @@ type swaggerRepoNewIssuePinsAllowed struct {
        Body api.NewIssuePinsAllowed `json:"body"`
 }
 
+// TasksList
+// swagger:response TasksList
+type swaggerRepoTasksList struct {
+       // in:body
+       Body api.ActionTaskResponse `json:"body"`
+}
+
 // swagger:response Compare
 type swaggerCompare struct {
        // in:body
index 3b6139d2fec30dfac00b8bb3af8a09cf21649492..c44179632e673eb8b7789382b285cbbd15bd5546 100644 (file)
@@ -11,6 +11,7 @@ import (
        "strings"
        "time"
 
+       actions_model "code.gitea.io/gitea/models/actions"
        asymkey_model "code.gitea.io/gitea/models/asymkey"
        "code.gitea.io/gitea/models/auth"
        git_model "code.gitea.io/gitea/models/git"
@@ -24,6 +25,7 @@ import (
        "code.gitea.io/gitea/modules/container"
        "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/log"
+       "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
        "code.gitea.io/gitea/modules/util"
        "code.gitea.io/gitea/services/gitdiff"
@@ -193,6 +195,31 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
        }
 }
 
+// ToActionTask convert a actions_model.ActionTask to an api.ActionTask
+func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.ActionTask, error) {
+       if err := t.LoadAttributes(ctx); err != nil {
+               return nil, err
+       }
+
+       url := strings.TrimSuffix(setting.AppURL, "/") + t.GetRunLink()
+
+       return &api.ActionTask{
+               ID:           t.ID,
+               Name:         t.Job.Name,
+               HeadBranch:   t.Job.Run.PrettyRef(),
+               HeadSHA:      t.Job.CommitSHA,
+               RunNumber:    t.Job.Run.Index,
+               Event:        t.Job.Run.TriggerEvent,
+               DisplayTitle: t.Job.Run.Title,
+               Status:       t.Status.String(),
+               WorkflowID:   t.Job.Run.WorkflowID,
+               URL:          url,
+               CreatedAt:    t.Created.AsLocalTime(),
+               UpdatedAt:    t.Updated.AsLocalTime(),
+               RunStartedAt: t.Started.AsLocalTime(),
+       }, nil
+}
+
 // ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
 func ToVerification(ctx context.Context, c *git.Commit) *api.PayloadCommitVerification {
        verif := asymkey_model.ParseCommitWithSignature(ctx, c)
index 362a847332ad59741ed5cf2c65fbe80b4a0ab245..0c5e5c974d859e0135e65b372e60cb21d64b8e1c 100644 (file)
         }
       }
     },
+    "/repos/{owner}/{repo}/actions/tasks": {
+      "get": {
+        "produces": [
+          "application/json"
+        ],
+        "tags": [
+          "repository"
+        ],
+        "summary": "List a repository's action tasks",
+        "operationId": "ListActionTasks",
+        "parameters": [
+          {
+            "type": "string",
+            "description": "owner of the repo",
+            "name": "owner",
+            "in": "path",
+            "required": true
+          },
+          {
+            "type": "string",
+            "description": "name of the repo",
+            "name": "repo",
+            "in": "path",
+            "required": true
+          },
+          {
+            "type": "integer",
+            "description": "page number of results to return (1-based)",
+            "name": "page",
+            "in": "query"
+          },
+          {
+            "type": "integer",
+            "description": "page size of results, default maximum page size is 50",
+            "name": "limit",
+            "in": "query"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/responses/TasksList"
+          },
+          "400": {
+            "$ref": "#/responses/error"
+          },
+          "403": {
+            "$ref": "#/responses/forbidden"
+          },
+          "404": {
+            "$ref": "#/responses/notFound"
+          },
+          "409": {
+            "$ref": "#/responses/conflict"
+          },
+          "422": {
+            "$ref": "#/responses/validationError"
+          }
+        }
+      }
+    },
     "/repos/{owner}/{repo}/actions/variables": {
       "get": {
         "produces": [
       },
       "x-go-package": "code.gitea.io/gitea/modules/structs"
     },
+    "ActionTask": {
+      "description": "ActionTask represents a ActionTask",
+      "type": "object",
+      "properties": {
+        "created_at": {
+          "type": "string",
+          "format": "date-time",
+          "x-go-name": "CreatedAt"
+        },
+        "display_title": {
+          "type": "string",
+          "x-go-name": "DisplayTitle"
+        },
+        "event": {
+          "type": "string",
+          "x-go-name": "Event"
+        },
+        "head_branch": {
+          "type": "string",
+          "x-go-name": "HeadBranch"
+        },
+        "head_sha": {
+          "type": "string",
+          "x-go-name": "HeadSHA"
+        },
+        "id": {
+          "type": "integer",
+          "format": "int64",
+          "x-go-name": "ID"
+        },
+        "name": {
+          "type": "string",
+          "x-go-name": "Name"
+        },
+        "run_number": {
+          "type": "integer",
+          "format": "int64",
+          "x-go-name": "RunNumber"
+        },
+        "run_started_at": {
+          "type": "string",
+          "format": "date-time",
+          "x-go-name": "RunStartedAt"
+        },
+        "status": {
+          "type": "string",
+          "x-go-name": "Status"
+        },
+        "updated_at": {
+          "type": "string",
+          "format": "date-time",
+          "x-go-name": "UpdatedAt"
+        },
+        "url": {
+          "type": "string",
+          "x-go-name": "URL"
+        },
+        "workflow_id": {
+          "type": "string",
+          "x-go-name": "WorkflowID"
+        }
+      },
+      "x-go-package": "code.gitea.io/gitea/modules/structs"
+    },
+    "ActionTaskResponse": {
+      "description": "ActionTaskResponse returns a ActionTask",
+      "type": "object",
+      "properties": {
+        "total_count": {
+          "type": "integer",
+          "format": "int64",
+          "x-go-name": "TotalCount"
+        },
+        "workflow_runs": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/ActionTask"
+          },
+          "x-go-name": "Entries"
+        }
+      },
+      "x-go-package": "code.gitea.io/gitea/modules/structs"
+    },
     "ActionVariable": {
       "description": "ActionVariable return value of the query API",
       "type": "object",
         }
       }
     },
+    "TasksList": {
+      "description": "TasksList",
+      "schema": {
+        "$ref": "#/definitions/ActionTaskResponse"
+      }
+    },
     "Team": {
       "description": "Team",
       "schema": {