aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--routers/web/repo/actions/view.go41
-rw-r--r--routers/web/web.go3
-rw-r--r--web_src/js/components/RepoActionView.vue33
-rw-r--r--web_src/js/svg.js2
4 files changed, 54 insertions, 25 deletions
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index c553aef9ae..f96cd2acf8 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -55,6 +55,7 @@ type ViewResponse struct {
Status string `json:"status"`
CanCancel bool `json:"canCancel"`
CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
+ CanRerun bool `json:"canRerun"`
Done bool `json:"done"`
Jobs []*ViewJob `json:"jobs"`
Commit ViewCommit `json:"commit"`
@@ -136,6 +137,7 @@ func ViewPost(ctx *context_module.Context) {
resp.State.Run.Link = run.Link()
resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
+ resp.State.Run.CanRerun = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.Done = run.Status.IsDone()
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
resp.State.Run.Status = run.Status.String()
@@ -238,7 +240,7 @@ func ViewPost(ctx *context_module.Context) {
ctx.JSON(http.StatusOK, resp)
}
-func Rerun(ctx *context_module.Context) {
+func RerunOne(ctx *context_module.Context) {
runIndex := ctx.ParamsInt64("run")
jobIndex := ctx.ParamsInt64("job")
@@ -246,10 +248,37 @@ func Rerun(ctx *context_module.Context) {
if ctx.Written() {
return
}
+
+ if err := rerunJob(ctx, job); err != nil {
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+
+ ctx.JSON(http.StatusOK, struct{}{})
+}
+
+func RerunAll(ctx *context_module.Context) {
+ runIndex := ctx.ParamsInt64("run")
+
+ _, jobs := getRunJobs(ctx, runIndex, 0)
+ if ctx.Written() {
+ return
+ }
+
+ for _, j := range jobs {
+ if err := rerunJob(ctx, j); err != nil {
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+ }
+
+ ctx.JSON(http.StatusOK, struct{}{})
+}
+
+func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob) error {
status := job.Status
if !status.IsDone() {
- ctx.JSON(http.StatusOK, struct{}{})
- return
+ return nil
}
job.TaskID = 0
@@ -261,13 +290,11 @@ func Rerun(ctx *context_module.Context) {
_, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped")
return err
}); err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
- return
+ return err
}
actions_service.CreateCommitStatus(ctx, job)
-
- ctx.JSON(http.StatusOK, struct{}{})
+ return nil
}
func Cancel(ctx *context_module.Context) {
diff --git a/routers/web/web.go b/routers/web/web.go
index e63add51f3..5357c55500 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -1186,10 +1186,11 @@ func registerRoutes(m *web.Route) {
m.Combo("").
Get(actions.View).
Post(web.Bind(actions.ViewRequest{}), actions.ViewPost)
- m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
+ m.Post("/rerun", reqRepoActionsWriter, actions.RerunOne)
})
m.Post("/cancel", reqRepoActionsWriter, actions.Cancel)
m.Post("/approve", reqRepoActionsWriter, actions.Approve)
+ m.Post("/rerun", reqRepoActionsWriter, actions.RerunAll)
})
}, reqRepoActionsReader, actions.MustEnableActions)
diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index 6fcd6ce880..00411654a3 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -6,11 +6,14 @@
<div class="action-title">
{{ run.title }}
</div>
- <button class="run_approve" @click="approveRun()" v-if="run.canApprove">
- <i class="play circle outline icon"/>
+ <button class="action-control-button text green" @click="approveRun()" v-if="run.canApprove">
+ <SvgIcon name="octicon-play" :size="20"/>
</button>
- <button class="run_cancel" @click="cancelRun()" v-else-if="run.canCancel">
- <i class="stop circle outline icon"/>
+ <button class="action-control-button text red" @click="cancelRun()" v-else-if="run.canCancel">
+ <SvgIcon name="octicon-x-circle-fill" :size="20"/>
+ </button>
+ <button class="action-control-button text green" @click="rerun()" v-else-if="run.canRerun">
+ <SvgIcon name="octicon-sync" :size="20"/>
</button>
</div>
<div class="action-commit-summary">
@@ -106,6 +109,7 @@ const sfc = {
status: '',
canCancel: false,
canApprove: false,
+ canRerun: false,
done: false,
jobs: [
// {
@@ -193,6 +197,11 @@ const sfc = {
await this.fetchPost(`${jobLink}/rerun`);
window.location.href = jobLink;
},
+ // rerun workflow
+ async rerun() {
+ await this.fetchPost(`${this.run.link}/rerun`);
+ window.location.href = this.run.link;
+ },
// cancel a run
cancelRun() {
this.fetchPost(`${this.run.link}/cancel`);
@@ -366,26 +375,16 @@ export function ansiLogToHTML(line) {
margin: 0 20px 20px 20px;
}
-.action-view-header .run_cancel {
- border: none;
- color: var(--color-red);
- background-color: transparent;
- outline: none;
- cursor: pointer;
- transition: transform 0.2s;
-}
-
-.action-view-header .run_approve {
+.action-view-header .action-control-button {
border: none;
- color: var(--color-green);
background-color: transparent;
outline: none;
cursor: pointer;
transition: transform 0.2s;
+ display: flex;
}
-.action-view-header .run_cancel:hover,
-.action-view-header .run_approve:hover {
+.action-view-header .action-control-button:hover {
transform: scale(130%);
}
diff --git a/web_src/js/svg.js b/web_src/js/svg.js
index 821ed9fd43..024b1fbc16 100644
--- a/web_src/js/svg.js
+++ b/web_src/js/svg.js
@@ -18,6 +18,7 @@ import octiconLink from '../../public/img/svg/octicon-link.svg';
import octiconLock from '../../public/img/svg/octicon-lock.svg';
import octiconMilestone from '../../public/img/svg/octicon-milestone.svg';
import octiconMirror from '../../public/img/svg/octicon-mirror.svg';
+import octiconPlay from '../../public/img/svg/octicon-play.svg';
import octiconProject from '../../public/img/svg/octicon-project.svg';
import octiconRepo from '../../public/img/svg/octicon-repo.svg';
import octiconRepoForked from '../../public/img/svg/octicon-repo-forked.svg';
@@ -79,6 +80,7 @@ const svgs = {
'octicon-milestone': octiconMilestone,
'octicon-mirror': octiconMirror,
'octicon-organization': octiconOrganization,
+ 'octicon-play': octiconPlay,
'octicon-plus': octiconPlus,
'octicon-project': octiconProject,
'octicon-repo': octiconRepo,