diff --git a/models/actions/run.go b/models/actions/run.go index f4e130dce45..30c892484f4 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -27,29 +27,31 @@ import ( // ActionRun represents a run of a workflow file type ActionRun struct { - ID int64 - Title string - RepoID int64 `xorm:"index unique(repo_index) index(repo_concurrency)"` - Repo *repo_model.Repository `xorm:"-"` - OwnerID int64 `xorm:"index"` - WorkflowID string `xorm:"index"` // the name of workflow file - Index int64 `xorm:"index unique(repo_index)"` // a unique number for each run of a repository - TriggerUserID int64 `xorm:"index"` - TriggerUser *user_model.User `xorm:"-"` - ScheduleID int64 - Ref string `xorm:"index"` // the commit/tag/… that caused the run - IsRefDeleted bool `xorm:"-"` - CommitSHA string - IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow. - NeedApproval bool // may need approval if it's a fork pull request - ApprovedBy int64 `xorm:"index"` // who approved - Event webhook_module.HookEventType // the webhook event that causes the workflow to run - EventPayload string `xorm:"LONGTEXT"` - TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow - Status Status `xorm:"index"` - Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed - ConcurrencyGroup string `xorm:"index(repo_concurrency)"` - ConcurrencyCancel bool + ID int64 + Title string + RepoID int64 `xorm:"index unique(repo_index) index(repo_concurrency)"` + Repo *repo_model.Repository `xorm:"-"` + OwnerID int64 `xorm:"index"` + WorkflowID string `xorm:"index"` // the name of workflow file + Index int64 `xorm:"index unique(repo_index)"` // a unique number for each run of a repository + TriggerUserID int64 `xorm:"index"` + TriggerUser *user_model.User `xorm:"-"` + ScheduleID int64 + Ref string `xorm:"index"` // the commit/tag/… that caused the run + IsRefDeleted bool `xorm:"-"` + CommitSHA string + IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow. + NeedApproval bool // may need approval if it's a fork pull request + ApprovedBy int64 `xorm:"index"` // who approved + Event webhook_module.HookEventType // the webhook event that causes the workflow to run + EventPayload string `xorm:"LONGTEXT"` + TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow + Status Status `xorm:"index"` + Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed + RawConcurrencyGroup string + RawConcurrencyCancel string + ConcurrencyGroup string `xorm:"index(repo_concurrency)"` + ConcurrencyCancel bool // Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0 Started timeutil.TimeStamp Stopped timeutil.TimeStamp diff --git a/models/migrations/v1_25/v322.go b/models/migrations/v1_25/v322.go index 85cf32926fa..a3241de91d8 100644 --- a/models/migrations/v1_25/v322.go +++ b/models/migrations/v1_25/v322.go @@ -9,9 +9,11 @@ import ( func AddActionsConcurrency(x *xorm.Engine) error { type ActionRun struct { - RepoID int64 `xorm:"index unique(repo_index) index(repo_concurrency)"` - ConcurrencyGroup string `xorm:"index(repo_concurrency)"` - ConcurrencyCancel bool + RepoID int64 `xorm:"index unique(repo_index) index(repo_concurrency)"` + RawConcurrencyGroup string + RawConcurrencyCancel string + ConcurrencyGroup string `xorm:"index(repo_concurrency)"` + ConcurrencyCancel bool } if err := x.Sync(new(ActionRun)); err != nil { diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 6875d964ecc..670b41ca888 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -419,7 +419,6 @@ func Rerun(ctx *context_module.Context) { return } - // TODO evaluate concurrency expression again, vars may change after the run is done // check run (workflow-level) concurrency job, jobs := getRunJobs(ctx, runIndex, jobIndex) @@ -435,6 +434,25 @@ func Rerun(ctx *context_module.Context) { run.Started = 0 run.Stopped = 0 + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + ctx.ServerError("GetVariablesOfRun", fmt.Errorf("get run %d variables: %w", run.ID, err)) + return + } + + wfConcurrencyGroup, wfConcurrencyCancel, err := actions_service.EvaluateWorkflowConcurrency(ctx, run, &model.RawConcurrency{ + Group: run.RawConcurrencyGroup, + CancelInProgress: run.RawConcurrencyCancel, + }, vars) + if err != nil { + ctx.ServerError("EvaluateWorkflowConcurrency", fmt.Errorf("evaluate workflow concurrency: %w", err)) + return + } + if wfConcurrencyGroup != "" { + run.ConcurrencyGroup = wfConcurrencyGroup + run.ConcurrencyCancel = wfConcurrencyCancel + } + blockRunByConcurrency, err = actions_model.ShouldBlockRunByConcurrency(ctx, run) if err != nil { ctx.ServerError("ShouldBlockRunByConcurrency", err) @@ -449,7 +467,7 @@ func Rerun(ctx *context_module.Context) { ctx.ServerError("cancel jobs", err) return } - if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration", "status"); err != nil { + if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration", "status", "concurrency_group", "concurrency_cancel"); err != nil { ctx.ServerError("UpdateRun", err) return }