@@ -12,6 +12,7 @@ import (
1212 "fmt"
1313 "net/http"
1414 "net/url"
15+ "slices"
1516 "strconv"
1617 "strings"
1718 "time"
@@ -1103,6 +1104,33 @@ func ActionsEnableWorkflow(ctx *context.APIContext) {
11031104 ctx .Status (http .StatusNoContent )
11041105}
11051106
1107+ func getCurrentRepoActionRunByID (ctx * context.APIContext ) * actions_model.ActionRun {
1108+ runID := ctx .PathParamInt64 ("run" )
1109+ run , err := actions_model .GetRunByRepoAndID (ctx , ctx .Repo .Repository .ID , runID )
1110+ if errors .Is (err , util .ErrNotExist ) {
1111+ ctx .APIErrorNotFound (err )
1112+ return nil
1113+ } else if err != nil {
1114+ ctx .APIErrorInternal (err )
1115+ return nil
1116+ }
1117+ return run
1118+ }
1119+
1120+ func getCurrentRepoActionRunJobsByID (ctx * context.APIContext ) (* actions_model.ActionRun , actions_model.ActionJobList ) {
1121+ run := getCurrentRepoActionRunByID (ctx )
1122+ if ctx .Written () {
1123+ return nil , nil
1124+ }
1125+
1126+ jobs , err := actions_model .GetRunJobsByRunID (ctx , run .ID )
1127+ if err != nil {
1128+ ctx .APIErrorInternal (err )
1129+ return nil , nil
1130+ }
1131+ return run , jobs
1132+ }
1133+
11061134// GetWorkflowRun Gets a specific workflow run.
11071135func GetWorkflowRun (ctx * context.APIContext ) {
11081136 // swagger:operation GET /repos/{owner}/{repo}/actions/runs/{run} repository GetWorkflowRun
@@ -1134,24 +1162,144 @@ func GetWorkflowRun(ctx *context.APIContext) {
11341162 // "404":
11351163 // "$ref": "#/responses/notFound"
11361164
1137- runID := ctx .PathParamInt64 ("run" )
1138- job , has , err := db .GetByID [actions_model.ActionRun ](ctx , runID )
1165+ run := getCurrentRepoActionRunByID (ctx )
1166+ if ctx .Written () {
1167+ return
1168+ }
1169+
1170+ convertedRun , err := convert .ToActionWorkflowRun (ctx , ctx .Repo .Repository , run )
11391171 if err != nil {
11401172 ctx .APIErrorInternal (err )
11411173 return
11421174 }
1175+ ctx .JSON (http .StatusOK , convertedRun )
1176+ }
11431177
1144- if ! has || job .RepoID != ctx .Repo .Repository .ID {
1145- ctx .APIErrorNotFound (util .ErrNotExist )
1178+ // RerunWorkflowRun Reruns an entire workflow run.
1179+ func RerunWorkflowRun (ctx * context.APIContext ) {
1180+ // swagger:operation POST /repos/{owner}/{repo}/actions/runs/{run}/rerun repository rerunWorkflowRun
1181+ // ---
1182+ // summary: Reruns an entire workflow run
1183+ // produces:
1184+ // - application/json
1185+ // parameters:
1186+ // - name: owner
1187+ // in: path
1188+ // description: owner of the repo
1189+ // type: string
1190+ // required: true
1191+ // - name: repo
1192+ // in: path
1193+ // description: name of the repository
1194+ // type: string
1195+ // required: true
1196+ // - name: run
1197+ // in: path
1198+ // description: id of the run
1199+ // type: integer
1200+ // required: true
1201+ // responses:
1202+ // "201":
1203+ // "$ref": "#/responses/WorkflowRun"
1204+ // "400":
1205+ // "$ref": "#/responses/error"
1206+ // "403":
1207+ // "$ref": "#/responses/forbidden"
1208+ // "404":
1209+ // "$ref": "#/responses/notFound"
1210+ // "422":
1211+ // "$ref": "#/responses/validationError"
1212+
1213+ run , jobs := getCurrentRepoActionRunJobsByID (ctx )
1214+ if ctx .Written () {
11461215 return
11471216 }
11481217
1149- convertedRun , err := convert .ToActionWorkflowRun (ctx , ctx .Repo .Repository , job )
1218+ if err := actions_service .RerunWorkflowRunJobs (ctx , ctx .Repo .Repository , run , jobs , nil ); err != nil {
1219+ handleWorkflowRerunError (ctx , err )
1220+ return
1221+ }
1222+
1223+ convertedRun , err := convert .ToActionWorkflowRun (ctx , ctx .Repo .Repository , run )
11501224 if err != nil {
11511225 ctx .APIErrorInternal (err )
11521226 return
11531227 }
1154- ctx .JSON (http .StatusOK , convertedRun )
1228+ ctx .JSON (http .StatusCreated , convertedRun )
1229+ }
1230+
1231+ // RerunWorkflowJob Reruns a specific workflow job in a run.
1232+ func RerunWorkflowJob (ctx * context.APIContext ) {
1233+ // swagger:operation POST /repos/{owner}/{repo}/actions/runs/{run}/jobs/{job_id}/rerun repository rerunWorkflowJob
1234+ // ---
1235+ // summary: Reruns a specific workflow job in a run
1236+ // produces:
1237+ // - application/json
1238+ // parameters:
1239+ // - name: owner
1240+ // in: path
1241+ // description: owner of the repo
1242+ // type: string
1243+ // required: true
1244+ // - name: repo
1245+ // in: path
1246+ // description: name of the repository
1247+ // type: string
1248+ // required: true
1249+ // - name: run
1250+ // in: path
1251+ // description: id of the run
1252+ // type: integer
1253+ // required: true
1254+ // - name: job_id
1255+ // in: path
1256+ // description: id of the job
1257+ // type: integer
1258+ // required: true
1259+ // responses:
1260+ // "201":
1261+ // "$ref": "#/responses/WorkflowJob"
1262+ // "400":
1263+ // "$ref": "#/responses/error"
1264+ // "403":
1265+ // "$ref": "#/responses/forbidden"
1266+ // "404":
1267+ // "$ref": "#/responses/notFound"
1268+ // "422":
1269+ // "$ref": "#/responses/validationError"
1270+
1271+ run , jobs := getCurrentRepoActionRunJobsByID (ctx )
1272+ if ctx .Written () {
1273+ return
1274+ }
1275+
1276+ jobID := ctx .PathParamInt64 ("job_id" )
1277+ jobIdx := slices .IndexFunc (jobs , func (job * actions_model.ActionRunJob ) bool { return job .ID == jobID })
1278+ if jobIdx == - 1 {
1279+ ctx .APIErrorNotFound (util .NewNotExistErrorf ("workflow job with id %d" , jobID ))
1280+ return
1281+ }
1282+
1283+ targetJob := jobs [jobIdx ]
1284+ if err := actions_service .RerunWorkflowRunJobs (ctx , ctx .Repo .Repository , run , jobs , targetJob ); err != nil {
1285+ handleWorkflowRerunError (ctx , err )
1286+ return
1287+ }
1288+
1289+ convertedJob , err := convert .ToActionWorkflowJob (ctx , ctx .Repo .Repository , nil , targetJob )
1290+ if err != nil {
1291+ ctx .APIErrorInternal (err )
1292+ return
1293+ }
1294+ ctx .JSON (http .StatusCreated , convertedJob )
1295+ }
1296+
1297+ func handleWorkflowRerunError (ctx * context.APIContext , err error ) {
1298+ if errors .Is (err , util .ErrInvalidArgument ) {
1299+ ctx .APIError (http .StatusBadRequest , err )
1300+ return
1301+ }
1302+ ctx .APIErrorInternal (err )
11551303}
11561304
11571305// ListWorkflowRunJobs Lists all jobs for a workflow run.
@@ -1198,9 +1346,7 @@ func ListWorkflowRunJobs(ctx *context.APIContext) {
11981346 // "404":
11991347 // "$ref": "#/responses/notFound"
12001348
1201- repoID := ctx .Repo .Repository .ID
1202-
1203- runID := ctx .PathParamInt64 ("run" )
1349+ repoID , runID := ctx .Repo .Repository .ID , ctx .PathParamInt64 ("run" )
12041350
12051351 // Avoid the list all jobs functionality for this api route to be used with a runID == 0.
12061352 if runID <= 0 {
@@ -1300,10 +1446,8 @@ func GetArtifactsOfRun(ctx *context.APIContext) {
13001446 // "404":
13011447 // "$ref": "#/responses/notFound"
13021448
1303- repoID := ctx .Repo .Repository .ID
13041449 artifactName := ctx .Req .URL .Query ().Get ("name" )
1305-
1306- runID := ctx .PathParamInt64 ("run" )
1450+ repoID , runID := ctx .Repo .Repository .ID , ctx .PathParamInt64 ("run" )
13071451
13081452 artifacts , total , err := db .FindAndCount [actions_model.ActionArtifact ](ctx , actions_model.FindArtifactsOptions {
13091453 RepoID : repoID ,
@@ -1364,15 +1508,11 @@ func DeleteActionRun(ctx *context.APIContext) {
13641508 // "404":
13651509 // "$ref": "#/responses/notFound"
13661510
1367- runID := ctx .PathParamInt64 ("run" )
1368- run , err := actions_model .GetRunByRepoAndID (ctx , ctx .Repo .Repository .ID , runID )
1369- if errors .Is (err , util .ErrNotExist ) {
1370- ctx .APIErrorNotFound (err )
1371- return
1372- } else if err != nil {
1373- ctx .APIErrorInternal (err )
1511+ run := getCurrentRepoActionRunByID (ctx )
1512+ if ctx .Written () {
13741513 return
13751514 }
1515+
13761516 if ! run .Status .IsDone () {
13771517 ctx .APIError (http .StatusBadRequest , "this workflow run is not done" )
13781518 return
0 commit comments