aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChester <chesterip0510@gmail.com>2024-05-01 09:40:23 +0800
committerGitHub <noreply@github.com>2024-05-01 09:40:23 +0800
commit6709e28da78a0ea7e63f9fe4e32f620abdc88d14 (patch)
tree67f544f4a438612f06b20cc3ded875bc92770dc0
parentd8d46d1c483390da746d7a60edd2ace18a66c933 (diff)
downloadgitea-6709e28da78a0ea7e63f9fe4e32f620abdc88d14.tar.gz
gitea-6709e28da78a0ea7e63f9fe4e32f620abdc88d14.zip
Add API endpoints for getting action jobs status (#26673)
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>
-rw-r--r--modules/structs/repo_actions.go34
-rw-r--r--routers/api/v1/api.go3
-rw-r--r--routers/api/v1/repo/actions.go80
-rw-r--r--routers/api/v1/swagger/repo.go7
-rw-r--r--services/convert/convert.go27
-rw-r--r--templates/swagger/v1_json.tmpl149
6 files changed, 300 insertions, 0 deletions
diff --git a/modules/structs/repo_actions.go b/modules/structs/repo_actions.go
new file mode 100644
index 0000000000..b13f344738
--- /dev/null
+++ b/modules/structs/repo_actions.go
@@ -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"`
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 73071aa8df..74062c44ac 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -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
index 0000000000..635cb4e138
--- /dev/null
+++ b/routers/api/v1/repo/actions.go
@@ -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)
+}
diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go
index c3219f28d6..fcd34a63a9 100644
--- a/routers/api/v1/swagger/repo.go
+++ b/routers/api/v1/swagger/repo.go
@@ -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
diff --git a/services/convert/convert.go b/services/convert/convert.go
index 3b6139d2fe..c44179632e 100644
--- a/services/convert/convert.go
+++ b/services/convert/convert.go
@@ -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)
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 362a847332..0c5e5c974d 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -3997,6 +3997,66 @@
}
}
},
+ "/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": [
@@ -17953,6 +18013,89 @@
},
"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",
@@ -25409,6 +25552,12 @@
}
}
},
+ "TasksList": {
+ "description": "TasksList",
+ "schema": {
+ "$ref": "#/definitions/ActionTaskResponse"
+ }
+ },
"Team": {
"description": "Team",
"schema": {