implement evaluate concurrency expression again, vars may change after the run is done

This commit is contained in:
Christopher Homberger 2025-07-25 16:38:35 +02:00
parent 5e43aa2251
commit d5f6c44a49
3 changed files with 50 additions and 28 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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
}