2023-08-30 04:54:49 +08:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repo
import (
2023-09-05 17:21:02 +02:00
"errors"
2025-06-02 22:05:12 +02:00
"fmt"
2023-08-30 04:54:49 +08:00
"net/http"
2025-03-27 19:40:14 +00:00
actions_model "forgejo.org/models/actions"
"forgejo.org/models/db"
secret_model "forgejo.org/models/secret"
api "forgejo.org/modules/structs"
"forgejo.org/modules/util"
"forgejo.org/modules/web"
"forgejo.org/routers/api/v1/shared"
"forgejo.org/routers/api/v1/utils"
actions_service "forgejo.org/services/actions"
"forgejo.org/services/context"
"forgejo.org/services/convert"
secret_service "forgejo.org/services/secrets"
2023-08-30 04:54:49 +08:00
)
2024-04-26 21:11:49 +08:00
// ListActionsSecrets list an repo's actions secrets
func ( Action ) ListActionsSecrets ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/actions/secrets repository repoListActionsSecrets
// ---
// summary: List an repo's actions secrets
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repository
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// 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
// type: integer
// responses:
// "200":
// "$ref": "#/responses/SecretList"
// "404":
// "$ref": "#/responses/notFound"
repo := ctx . Repo . Repository
opts := & secret_model . FindSecretsOptions {
RepoID : repo . ID ,
ListOptions : utils . GetListOptions ( ctx ) ,
}
secrets , count , err := db . FindAndCount [ secret_model . Secret ] ( ctx , opts )
if err != nil {
ctx . InternalServerError ( err )
return
}
apiSecrets := make ( [ ] * api . Secret , len ( secrets ) )
for k , v := range secrets {
apiSecrets [ k ] = & api . Secret {
Name : v . Name ,
Created : v . CreatedUnix . AsTime ( ) ,
}
}
ctx . SetTotalCountHeader ( count )
ctx . JSON ( http . StatusOK , apiSecrets )
}
2023-08-30 04:54:49 +08:00
// create or update one secret of the repository
2024-04-26 21:11:49 +08:00
func ( Action ) CreateOrUpdateSecret ( ctx * context . APIContext ) {
2023-08-30 04:54:49 +08:00
// swagger:operation PUT /repos/{owner}/{repo}/actions/secrets/{secretname} repository updateRepoSecret
// ---
// summary: Create or Update a secret value in a repository
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repository
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: secretname
// in: path
// description: name of the secret
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/CreateOrUpdateSecretOption"
// responses:
// "201":
// description: response when creating a secret
// "204":
// description: response when updating a secret
// "400":
// "$ref": "#/responses/error"
2023-09-05 17:21:02 +02:00
// "404":
// "$ref": "#/responses/notFound"
2023-08-30 04:54:49 +08:00
repo := ctx . Repo . Repository
opt := web . GetForm ( ctx ) . ( * api . CreateOrUpdateSecretOption )
2023-09-05 17:21:02 +02:00
2024-07-30 01:15:02 +08:00
_ , created , err := secret_service . CreateOrUpdateSecret ( ctx , 0 , repo . ID , ctx . Params ( "secretname" ) , opt . Data )
2023-08-30 04:54:49 +08:00
if err != nil {
2023-09-05 17:21:02 +02:00
if errors . Is ( err , util . ErrInvalidArgument ) {
ctx . Error ( http . StatusBadRequest , "CreateOrUpdateSecret" , err )
} else if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "CreateOrUpdateSecret" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "CreateOrUpdateSecret" , err )
}
2023-08-30 04:54:49 +08:00
return
}
2023-09-05 17:21:02 +02:00
if created {
2023-08-30 04:54:49 +08:00
ctx . Status ( http . StatusCreated )
2023-09-05 17:21:02 +02:00
} else {
ctx . Status ( http . StatusNoContent )
2023-08-30 04:54:49 +08:00
}
}
2023-09-01 21:02:49 +08:00
// DeleteSecret delete one secret of the repository
2024-04-26 21:11:49 +08:00
func ( Action ) DeleteSecret ( ctx * context . APIContext ) {
2023-09-01 21:02:49 +08:00
// swagger:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secretname} repository deleteRepoSecret
// ---
// summary: Delete a secret in a repository
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repository
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: secretname
// in: path
// description: name of the secret
// type: string
// required: true
// responses:
// "204":
// description: delete one secret of the organization
2023-09-05 17:21:02 +02:00
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
2023-09-01 21:02:49 +08:00
repo := ctx . Repo . Repository
2024-07-30 01:15:02 +08:00
err := secret_service . DeleteSecretByName ( ctx , 0 , repo . ID , ctx . Params ( "secretname" ) )
2023-09-01 21:02:49 +08:00
if err != nil {
2023-09-05 17:21:02 +02:00
if errors . Is ( err , util . ErrInvalidArgument ) {
ctx . Error ( http . StatusBadRequest , "DeleteSecret" , err )
} else if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "DeleteSecret" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "DeleteSecret" , err )
}
2023-09-01 21:02:49 +08:00
return
}
ctx . Status ( http . StatusNoContent )
}
2024-03-29 04:40:35 +08:00
// GetVariable get a repo-level variable
2024-04-26 21:11:49 +08:00
func ( Action ) GetVariable ( ctx * context . APIContext ) {
2024-03-29 04:40:35 +08:00
// swagger:operation GET /repos/{owner}/{repo}/actions/variables/{variablename} repository getRepoVariable
// ---
// summary: Get a repo-level variable
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: variablename
// in: path
// description: name of the variable
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/ActionVariable"
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
v , err := actions_service . GetVariable ( ctx , actions_model . FindVariablesOpts {
RepoID : ctx . Repo . Repository . ID ,
Name : ctx . Params ( "variablename" ) ,
} )
if err != nil {
if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "GetVariable" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "GetVariable" , err )
}
return
}
variable := & api . ActionVariable {
OwnerID : v . OwnerID ,
RepoID : v . RepoID ,
Name : v . Name ,
Data : v . Data ,
}
ctx . JSON ( http . StatusOK , variable )
}
// DeleteVariable delete a repo-level variable
2024-04-26 21:11:49 +08:00
func ( Action ) DeleteVariable ( ctx * context . APIContext ) {
2024-03-29 04:40:35 +08:00
// swagger:operation DELETE /repos/{owner}/{repo}/actions/variables/{variablename} repository deleteRepoVariable
// ---
// summary: Delete a repo-level variable
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: variablename
// in: path
// description: name of the variable
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/ActionVariable"
// "201":
// description: response when deleting a variable
// "204":
// description: response when deleting a variable
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
if err := actions_service . DeleteVariableByName ( ctx , 0 , ctx . Repo . Repository . ID , ctx . Params ( "variablename" ) ) ; err != nil {
if errors . Is ( err , util . ErrInvalidArgument ) {
ctx . Error ( http . StatusBadRequest , "DeleteVariableByName" , err )
} else if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "DeleteVariableByName" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "DeleteVariableByName" , err )
}
return
}
ctx . Status ( http . StatusNoContent )
}
// CreateVariable create a repo-level variable
2024-04-26 21:11:49 +08:00
func ( Action ) CreateVariable ( ctx * context . APIContext ) {
2024-03-29 04:40:35 +08:00
// swagger:operation POST /repos/{owner}/{repo}/actions/variables/{variablename} repository createRepoVariable
// ---
// summary: Create a repo-level variable
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: variablename
// in: path
// description: name of the variable
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/CreateVariableOption"
// responses:
// "201":
// description: response when creating a repo-level variable
// "204":
// description: response when creating a repo-level variable
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
opt := web . GetForm ( ctx ) . ( * api . CreateVariableOption )
repoID := ctx . Repo . Repository . ID
variableName := ctx . Params ( "variablename" )
v , err := actions_service . GetVariable ( ctx , actions_model . FindVariablesOpts {
RepoID : repoID ,
Name : variableName ,
} )
if err != nil && ! errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusInternalServerError , "GetVariable" , err )
return
}
if v != nil && v . ID > 0 {
ctx . Error ( http . StatusConflict , "VariableNameAlreadyExists" , util . NewAlreadyExistErrorf ( "variable name %s already exists" , variableName ) )
return
}
if _ , err := actions_service . CreateVariable ( ctx , 0 , repoID , variableName , opt . Value ) ; err != nil {
if errors . Is ( err , util . ErrInvalidArgument ) {
ctx . Error ( http . StatusBadRequest , "CreateVariable" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "CreateVariable" , err )
}
return
}
ctx . Status ( http . StatusNoContent )
}
// UpdateVariable update a repo-level variable
2024-04-26 21:11:49 +08:00
func ( Action ) UpdateVariable ( ctx * context . APIContext ) {
2024-03-29 04:40:35 +08:00
// swagger:operation PUT /repos/{owner}/{repo}/actions/variables/{variablename} repository updateRepoVariable
// ---
// summary: Update a repo-level variable
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// type: string
// required: true
// - name: variablename
// in: path
// description: name of the variable
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/UpdateVariableOption"
// responses:
// "201":
// description: response when updating a repo-level variable
// "204":
// description: response when updating a repo-level variable
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
opt := web . GetForm ( ctx ) . ( * api . UpdateVariableOption )
v , err := actions_service . GetVariable ( ctx , actions_model . FindVariablesOpts {
RepoID : ctx . Repo . Repository . ID ,
Name : ctx . Params ( "variablename" ) ,
} )
if err != nil {
if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "GetVariable" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "GetVariable" , err )
}
return
}
if opt . Name == "" {
opt . Name = ctx . Params ( "variablename" )
}
2025-01-25 15:10:03 +01:00
if _ , err := actions_service . UpdateVariable ( ctx , v . ID , 0 , ctx . Repo . Repository . ID , opt . Name , opt . Value ) ; err != nil {
2024-03-29 04:40:35 +08:00
if errors . Is ( err , util . ErrInvalidArgument ) {
ctx . Error ( http . StatusBadRequest , "UpdateVariable" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "UpdateVariable" , err )
}
return
}
ctx . Status ( http . StatusNoContent )
}
// ListVariables list repo-level variables
2024-04-26 21:11:49 +08:00
func ( Action ) ListVariables ( ctx * context . APIContext ) {
2024-03-29 04:40:35 +08:00
// swagger:operation GET /repos/{owner}/{repo}/actions/variables repository getRepoVariablesList
// ---
// summary: Get repo-level variables list
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: name of the owner
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repository
// 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
// type: integer
// responses:
// "200":
// "$ref": "#/responses/VariableList"
// "400":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
vars , count , err := db . FindAndCount [ actions_model . ActionVariable ] ( ctx , & actions_model . FindVariablesOpts {
RepoID : ctx . Repo . Repository . ID ,
ListOptions : utils . GetListOptions ( ctx ) ,
} )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "FindVariables" , err )
return
}
variables := make ( [ ] * api . ActionVariable , len ( vars ) )
for i , v := range vars {
variables [ i ] = & api . ActionVariable {
OwnerID : v . OwnerID ,
RepoID : v . RepoID ,
Name : v . Name ,
}
}
ctx . SetTotalCountHeader ( count )
ctx . JSON ( http . StatusOK , variables )
}
2024-04-26 21:11:49 +08:00
// GetRegistrationToken returns the token to register repo runners
func ( Action ) GetRegistrationToken ( ctx * context . APIContext ) {
2024-07-30 00:45:24 +08:00
// swagger:operation GET /repos/{owner}/{repo}/actions/runners/registration-token repository repoGetRunnerRegistrationToken
2024-04-26 21:11:49 +08:00
// ---
// summary: Get a repository's actions runner registration token
// 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
// responses:
// "200":
// "$ref": "#/responses/RegistrationToken"
2024-07-30 02:46:45 +08:00
shared . GetRegistrationToken ( ctx , 0 , ctx . Repo . Repository . ID )
2024-04-26 21:11:49 +08:00
}
2025-01-14 11:17:42 +00:00
// SearchActionRunJobs return a list of actions jobs filtered by the provided parameters
func ( Action ) SearchActionRunJobs ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/actions/runners/jobs repository repoSearchRunJobs
// ---
// summary: Search for repository's action jobs according filter conditions
// 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: labels
// in: query
// description: a comma separated list of run job labels to search for
// type: string
// responses:
// "200":
// "$ref": "#/responses/RunJobList"
// "403":
// "$ref": "#/responses/forbidden"
shared . GetActionRunJobs ( ctx , 0 , ctx . Repo . Repository . ID )
}
2024-04-26 21:11:49 +08:00
var _ actions_service . API = new ( Action )
// Action implements actions_service.API
type Action struct { }
// NewAction creates a new Action service
func NewAction ( ) actions_service . API {
return Action { }
}
2024-05-03 01:43:29 +08:00
// 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 )
}
2024-06-28 05:17:11 +00:00
// DispatchWorkflow dispatches a workflow
func DispatchWorkflow ( ctx * context . APIContext ) {
// swagger:operation POST /repos/{owner}/{repo}/actions/workflows/{workflowname}/dispatches repository DispatchWorkflow
// ---
// summary: Dispatches a workflow
// consumes:
// - 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: workflowname
// in: path
// description: name of the workflow
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/DispatchWorkflowOption"
// responses:
2025-03-25 21:22:32 +00:00
// "201":
// "$ref": "#/responses/DispatchWorkflowRun"
2024-06-28 05:17:11 +00:00
// "204":
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
opt := web . GetForm ( ctx ) . ( * api . DispatchWorkflowOption )
name := ctx . Params ( "workflowname" )
if len ( opt . Ref ) == 0 {
2024-07-31 21:09:17 +02:00
ctx . Error ( http . StatusBadRequest , "ref" , "ref is empty" )
2024-06-28 05:17:11 +00:00
return
} else if len ( name ) == 0 {
2024-07-31 21:09:17 +02:00
ctx . Error ( http . StatusBadRequest , "workflowname" , "workflow name is empty" )
2024-06-28 05:17:11 +00:00
return
}
workflow , err := actions_service . GetWorkflowFromCommit ( ctx . Repo . GitRepo , opt . Ref , name )
if err != nil {
if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "GetWorkflowFromCommit" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "GetWorkflowFromCommit" , err )
}
return
}
inputGetter := func ( key string ) string {
return opt . Inputs [ key ]
}
2025-03-14 16:01:15 +00:00
run , jobs , err := workflow . Dispatch ( ctx , inputGetter , ctx . Repo . Repository , ctx . Doer )
if err != nil {
2024-06-28 05:17:11 +00:00
if actions_service . IsInputRequiredErr ( err ) {
ctx . Error ( http . StatusBadRequest , "workflow.Dispatch" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "workflow.Dispatch" , err )
}
return
}
2025-03-14 16:01:15 +00:00
workflowRun := & api . DispatchWorkflowRun {
2025-03-25 21:22:32 +00:00
ID : run . ID ,
RunNumber : run . Index ,
Jobs : jobs ,
2025-03-14 16:01:15 +00:00
}
if opt . ReturnRunInfo {
ctx . JSON ( http . StatusCreated , workflowRun )
} else {
ctx . JSON ( http . StatusNoContent , nil )
}
2024-06-28 05:17:11 +00:00
}
2025-06-02 22:05:12 +02:00
// ListActionRuns return a filtered list of ActionRun
func ListActionRuns ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/actions/runs repository ListActionRuns
// ---
// summary: List a repository's action runs
// 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
// - name: event
// in: query
// description: Returns workflow run triggered by the specified events. For example, `push`, `pull_request` or `workflow_dispatch`.
// type: array
// items:
// type: string
// - name: status
// in: query
// description: |
// Returns workflow runs with the check run status or conclusion that is specified. For example, a conclusion can be success or a status can be in_progress. Only Forgejo Actions can set a status of waiting, pending, or requested.
// type: array
// items:
// type: string
// enum: [unknown, waiting, running, success, failure, cancelled, skipped, blocked]
// - name: run_number
// in: query
// description: |
// Returns the workflow run associated with the run number.
// type: integer
// format: int64
// - name: head_sha
// in: query
// description: Only returns workflow runs that are associated with the specified head_sha.
// type: string
// responses:
// "200":
// "$ref": "#/responses/ActionRunList"
// "400":
// "$ref": "#/responses/error"
// "403":
// "$ref": "#/responses/forbidden"
statusStrs := ctx . FormStrings ( "status" )
statuses := make ( [ ] actions_model . Status , len ( statusStrs ) )
for i , s := range statusStrs {
if status , exists := actions_model . StatusFromString ( s ) ; exists {
statuses [ i ] = status
} else {
ctx . Error ( http . StatusBadRequest , "StatusFromString" , fmt . Sprintf ( "unknown status: %s" , s ) )
return
}
}
runs , total , err := db . FindAndCount [ actions_model . ActionRun ] ( ctx , & actions_model . FindRunJobOptions {
ListOptions : utils . GetListOptions ( ctx ) ,
OwnerID : ctx . Repo . Owner . ID ,
RepoID : ctx . Repo . Repository . ID ,
Events : ctx . FormStrings ( "event" ) ,
Statuses : statuses ,
RunNumber : ctx . FormInt64 ( "run_number" ) ,
CommitSHA : ctx . FormString ( "head_sha" ) ,
} )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "ListActionRuns" , err )
return
}
res := new ( api . ListActionRunResponse )
res . TotalCount = total
res . Entries = make ( [ ] * api . ActionRun , len ( runs ) )
for i , r := range runs {
cr , err := convert . ToActionRun ( ctx , r )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "ToActionRun" , err )
return
}
res . Entries [ i ] = cr
}
ctx . JSON ( http . StatusOK , & res )
}
// GetActionRun get one action instance
func GetActionRun ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/actions/runs/{run_id} repository ActionRun
// ---
// summary: Get an action run
// 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: run_id
// in: path
// description: id of the action run
// type: integer
// format: int64
// required: true
// responses:
// "200":
// "$ref": "#/responses/ActionRun"
// "400":
// "$ref": "#/responses/error"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
run , err := actions_model . GetRunByID ( ctx , ctx . ParamsInt64 ( ":run_id" ) )
if err != nil {
if errors . Is ( err , util . ErrNotExist ) {
ctx . Error ( http . StatusNotFound , "GetRunById" , err )
} else {
ctx . Error ( http . StatusInternalServerError , "GetRunByID" , err )
}
return
}
if ctx . Repo . Repository . ID != run . RepoID {
ctx . Error ( http . StatusNotFound , "GetRunById" , util . ErrNotExist )
return
}
res , err := convert . ToActionRun ( ctx , run )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "ToActionRun" , err )
return
}
ctx . JSON ( http . StatusOK , res )
}