mirror of
https://github.com/go-gitea/gitea.git
synced 2025-10-24 13:53:42 +09:00
Fix #24769 Fix #32662 Fix #33260 Depends on https://gitea.com/gitea/act/pulls/124 - https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency ## ⚠️ BREAKING ⚠️ This PR removes the auto-cancellation feature added by #25716. Users need to manually add `concurrency` to workflows to control concurrent workflows or jobs. --------- Signed-off-by: Zettat123 <zettat123@gmail.com> Co-authored-by: Christopher Homberger <christopher.homberger@web.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
128 lines
3.8 KiB
Go
128 lines
3.8 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
actions_model "code.gitea.io/gitea/models/actions"
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/modules/util"
|
|
|
|
"github.com/nektos/act/pkg/jobparser"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// InsertRun inserts a run
|
|
// The title will be cut off at 255 characters if it's longer than 255 characters.
|
|
func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobparser.SingleWorkflow) error {
|
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
|
index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
run.Index = index
|
|
run.Title = util.EllipsisDisplayString(run.Title, 255)
|
|
|
|
// check run (workflow-level) concurrency
|
|
run.Status, err = PrepareToStartRunWithConcurrency(ctx, run)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := db.Insert(ctx, run); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := run.LoadRepo(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := actions_model.UpdateRepoRunsNumbers(ctx, run.Repo); err != nil {
|
|
return err
|
|
}
|
|
|
|
// query vars for evaluating job concurrency groups
|
|
vars, err := actions_model.GetVariablesOfRun(ctx, run)
|
|
if err != nil {
|
|
return fmt.Errorf("get run %d variables: %w", run.ID, err)
|
|
}
|
|
|
|
runJobs := make([]*actions_model.ActionRunJob, 0, len(jobs))
|
|
var hasWaitingJobs bool
|
|
for _, v := range jobs {
|
|
id, job := v.Job()
|
|
needs := job.Needs()
|
|
if err := v.SetJob(id, job.EraseNeeds()); err != nil {
|
|
return err
|
|
}
|
|
payload, _ := v.Marshal()
|
|
|
|
shouldBlockJob := len(needs) > 0 || run.NeedApproval || run.Status == actions_model.StatusBlocked
|
|
|
|
job.Name = util.EllipsisDisplayString(job.Name, 255)
|
|
runJob := &actions_model.ActionRunJob{
|
|
RunID: run.ID,
|
|
RepoID: run.RepoID,
|
|
OwnerID: run.OwnerID,
|
|
CommitSHA: run.CommitSHA,
|
|
IsForkPullRequest: run.IsForkPullRequest,
|
|
Name: job.Name,
|
|
WorkflowPayload: payload,
|
|
JobID: id,
|
|
Needs: needs,
|
|
RunsOn: job.RunsOn(),
|
|
Status: util.Iif(shouldBlockJob, actions_model.StatusBlocked, actions_model.StatusWaiting),
|
|
}
|
|
// check job concurrency
|
|
if job.RawConcurrency != nil {
|
|
rawConcurrency, err := yaml.Marshal(job.RawConcurrency)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal raw concurrency: %w", err)
|
|
}
|
|
runJob.RawConcurrency = string(rawConcurrency)
|
|
|
|
// do not evaluate job concurrency when it requires `needs`, the jobs with `needs` will be evaluated later by job emitter
|
|
if len(needs) == 0 {
|
|
err = EvaluateJobConcurrencyFillModel(ctx, run, runJob, vars)
|
|
if err != nil {
|
|
return fmt.Errorf("evaluate job concurrency: %w", err)
|
|
}
|
|
}
|
|
|
|
// If a job needs other jobs ("needs" is not empty), its status is set to StatusBlocked at the entry of the loop
|
|
// No need to check job concurrency for a blocked job (it will be checked by job emitter later)
|
|
if runJob.Status == actions_model.StatusWaiting {
|
|
runJob.Status, err = PrepareToStartJobWithConcurrency(ctx, runJob)
|
|
if err != nil {
|
|
return fmt.Errorf("prepare to start job with concurrency: %w", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
hasWaitingJobs = hasWaitingJobs || runJob.Status == actions_model.StatusWaiting
|
|
if err := db.Insert(ctx, runJob); err != nil {
|
|
return err
|
|
}
|
|
|
|
runJobs = append(runJobs, runJob)
|
|
}
|
|
|
|
run.Status = actions_model.AggregateJobStatus(runJobs)
|
|
if err := actions_model.UpdateRun(ctx, run, "status"); err != nil {
|
|
return err
|
|
}
|
|
|
|
// if there is a job in the waiting status, increase tasks version.
|
|
if hasWaitingJobs {
|
|
if err := actions_model.IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|