@@ -49,11 +49,12 @@ type ViewRequest struct {
4949type  ViewResponse  struct  {
5050	State  struct  {
5151		Run  struct  {
52- 			Link       string      `json:"link"` 
53- 			Title      string      `json:"title"` 
54- 			CanCancel  bool        `json:"canCancel"` 
55- 			Done       bool        `json:"done"` 
56- 			Jobs       []* ViewJob  `json:"jobs"` 
52+ 			Link        string      `json:"link"` 
53+ 			Title       string      `json:"title"` 
54+ 			CanCancel   bool        `json:"canCancel"` 
55+ 			CanApprove  bool        `json:"canApprove"`  // the run needs an approval and the doer has permission to approve 
56+ 			Done        bool        `json:"done"` 
57+ 			Jobs        []* ViewJob  `json:"jobs"` 
5758		} `json:"run"` 
5859		CurrentJob  struct  {
5960			Title   string          `json:"title"` 
@@ -107,6 +108,7 @@ func ViewPost(ctx *context_module.Context) {
107108	resp .State .Run .Title  =  run .Title 
108109	resp .State .Run .Link  =  run .Link ()
109110	resp .State .Run .CanCancel  =  ! run .Status .IsDone () &&  ctx .Repo .CanWrite (unit .TypeActions )
111+ 	resp .State .Run .CanApprove  =  run .NeedApproval  &&  ctx .Repo .CanWrite (unit .TypeActions )
110112	resp .State .Run .Done  =  run .Status .IsDone ()
111113	resp .State .Run .Jobs  =  make ([]* ViewJob , 0 , len (jobs )) // marshal to '[]' instead fo 'null' in json 
112114	for  _ , v  :=  range  jobs  {
@@ -135,6 +137,9 @@ func ViewPost(ctx *context_module.Context) {
135137
136138	resp .State .CurrentJob .Title  =  current .Name 
137139	resp .State .CurrentJob .Detail  =  current .Status .LocaleString (ctx .Locale )
140+ 	if  run .NeedApproval  {
141+ 		resp .State .CurrentJob .Detail  =  ctx .Locale .Tr ("actions.need_approval_desc" )
142+ 	}
138143	resp .State .CurrentJob .Steps  =  make ([]* ViewJobStep , 0 ) // marshal to '[]' instead fo 'null' in json 
139144	resp .Logs .StepsLog  =  make ([]* ViewStepLog , 0 )          // marshal to '[]' instead fo 'null' in json 
140145	if  task  !=  nil  {
@@ -261,6 +266,40 @@ func Cancel(ctx *context_module.Context) {
261266	ctx .JSON (http .StatusOK , struct {}{})
262267}
263268
269+ func  Approve (ctx  * context_module.Context ) {
270+ 	runIndex  :=  ctx .ParamsInt64 ("run" )
271+ 
272+ 	current , jobs  :=  getRunJobs (ctx , runIndex , - 1 )
273+ 	if  ctx .Written () {
274+ 		return 
275+ 	}
276+ 	run  :=  current .Run 
277+ 	doer  :=  ctx .Doer 
278+ 
279+ 	if  err  :=  db .WithTx (ctx , func (ctx  context.Context ) error  {
280+ 		run .NeedApproval  =  false 
281+ 		run .ApprovedBy  =  doer .ID 
282+ 		if  err  :=  actions_model .UpdateRun (ctx , run , "need_approval" , "approved_by" ); err  !=  nil  {
283+ 			return  err 
284+ 		}
285+ 		for  _ , job  :=  range  jobs  {
286+ 			if  len (job .Needs ) ==  0  &&  job .Status .IsBlocked () {
287+ 				job .Status  =  actions_model .StatusWaiting 
288+ 				_ , err  :=  actions_model .UpdateRunJob (ctx , job , nil , "status" )
289+ 				if  err  !=  nil  {
290+ 					return  err 
291+ 				}
292+ 			}
293+ 		}
294+ 		return  nil 
295+ 	}); err  !=  nil  {
296+ 		ctx .Error (http .StatusInternalServerError , err .Error ())
297+ 		return 
298+ 	}
299+ 
300+ 	ctx .JSON (http .StatusOK , struct {}{})
301+ }
302+ 
264303// getRunJobs gets the jobs of runIndex, and returns jobs[jobIndex], jobs. 
265304// Any error will be written to the ctx. 
266305// It never returns a nil job of an empty jobs, if the jobIndex is out of range, it will be treated as 0. 
0 commit comments