Skip to content

Commit 97292da

Browse files
authored
Fix schedule tasks bugs (go-gitea#28691)
Fix go-gitea#28157 This PR fix the possible bugs about actions schedule. ## The Changes - Move `UpdateRepositoryUnit` and `SetRepoDefaultBranch` from models to service layer - Remove schedules plan from database and cancel waiting & running schedules tasks in this repository when actions unit has been disabled or global disabled. - Remove schedules plan from database and cancel waiting & running schedules tasks in this repository when default branch changed.
1 parent 6c68239 commit 97292da

File tree

19 files changed

+204
-88
lines changed

19 files changed

+204
-88
lines changed

models/actions/run.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,14 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err
168168
}
169169

170170
// CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow.
171-
func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error {
171+
func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
172172
// Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'.
173173
runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{
174-
RepoID: repoID,
175-
Ref: ref,
176-
WorkflowID: workflowID,
177-
Status: []Status{StatusRunning, StatusWaiting},
174+
RepoID: repoID,
175+
Ref: ref,
176+
WorkflowID: workflowID,
177+
TriggerEvent: event,
178+
Status: []Status{StatusRunning, StatusWaiting},
178179
})
179180
if err != nil {
180181
return err

models/actions/run_list.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
repo_model "code.gitea.io/gitea/models/repo"
1111
user_model "code.gitea.io/gitea/models/user"
1212
"code.gitea.io/gitea/modules/container"
13+
webhook_module "code.gitea.io/gitea/modules/webhook"
1314

1415
"xorm.io/builder"
1516
)
@@ -71,6 +72,7 @@ type FindRunOptions struct {
7172
WorkflowID string
7273
Ref string // the commit/tag/… that caused this workflow
7374
TriggerUserID int64
75+
TriggerEvent webhook_module.HookEventType
7476
Approved bool // not util.OptionalBool, it works only when it's true
7577
Status []Status
7678
}
@@ -98,6 +100,9 @@ func (opts FindRunOptions) ToConds() builder.Cond {
98100
if opts.Ref != "" {
99101
cond = cond.And(builder.Eq{"ref": opts.Ref})
100102
}
103+
if opts.TriggerEvent != "" {
104+
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent})
105+
}
101106
return cond
102107
}
103108

models/actions/schedule.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package actions
55

66
import (
77
"context"
8+
"fmt"
89
"time"
910

1011
"code.gitea.io/gitea/models/db"
@@ -118,3 +119,22 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
118119

119120
return committer.Commit()
120121
}
122+
123+
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
124+
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
125+
// There is no other place we can do this because the app.ini will be changed manually
126+
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
127+
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
128+
}
129+
// cancel running cron jobs of this repository and delete old schedules
130+
if err := CancelRunningJobs(
131+
ctx,
132+
repo.ID,
133+
repo.DefaultBranch,
134+
"",
135+
webhook_module.HookEventSchedule,
136+
); err != nil {
137+
return fmt.Errorf("CancelRunningJobs: %v", err)
138+
}
139+
return nil
140+
}

models/git/branch.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ func FindRenamedBranch(ctx context.Context, repoID int64, from string) (branch *
283283
}
284284

285285
// RenameBranch rename a branch
286-
func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to string, gitAction func(isDefault bool) error) (err error) {
286+
func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to string, gitAction func(ctx context.Context, isDefault bool) error) (err error) {
287287
ctx, committer, err := db.TxContext(ctx)
288288
if err != nil {
289289
return err
@@ -358,7 +358,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
358358
}
359359

360360
// 5. do git action
361-
if err = gitAction(isDefault); err != nil {
361+
if err = gitAction(ctx, isDefault); err != nil {
362362
return err
363363
}
364364

models/git/branch_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package git_test
55

66
import (
7+
"context"
78
"testing"
89

910
"code.gitea.io/gitea/models/db"
@@ -132,7 +133,7 @@ func TestRenameBranch(t *testing.T) {
132133
}, git_model.WhitelistOptions{}))
133134
assert.NoError(t, committer.Commit())
134135

135-
assert.NoError(t, git_model.RenameBranch(db.DefaultContext, repo1, "master", "main", func(isDefault bool) error {
136+
assert.NoError(t, git_model.RenameBranch(db.DefaultContext, repo1, "master", "main", func(ctx context.Context, isDefault bool) error {
136137
_isDefault = isDefault
137138
return nil
138139
}))

models/repo/repo_unit.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -283,29 +283,3 @@ func UpdateRepoUnit(ctx context.Context, unit *RepoUnit) error {
283283
_, err := db.GetEngine(ctx).ID(unit.ID).Update(unit)
284284
return err
285285
}
286-
287-
// UpdateRepositoryUnits updates a repository's units
288-
func UpdateRepositoryUnits(ctx context.Context, repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) {
289-
ctx, committer, err := db.TxContext(ctx)
290-
if err != nil {
291-
return err
292-
}
293-
defer committer.Close()
294-
295-
// Delete existing settings of units before adding again
296-
for _, u := range units {
297-
deleteUnitTypes = append(deleteUnitTypes, u.Type)
298-
}
299-
300-
if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil {
301-
return err
302-
}
303-
304-
if len(units) > 0 {
305-
if err = db.Insert(ctx, units); err != nil {
306-
return err
307-
}
308-
}
309-
310-
return committer.Commit()
311-
}

modules/actions/github.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const (
2222
GithubEventRelease = "release"
2323
GithubEventPullRequestComment = "pull_request_comment"
2424
GithubEventGollum = "gollum"
25+
GithubEventSchedule = "schedule"
2526
)
2627

2728
// canGithubEventMatch check if the input Github event can match any Gitea event.
@@ -69,6 +70,9 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
6970
return false
7071
}
7172

73+
case GithubEventSchedule:
74+
return triggedEvent == webhook_module.HookEventSchedule
75+
7276
default:
7377
return eventName == string(triggedEvent)
7478
}

modules/actions/workflows.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
type DetectedWorkflow struct {
2424
EntryName string
25-
TriggerEvent string
25+
TriggerEvent *jobparser.Event
2626
Content []byte
2727
}
2828

@@ -100,6 +100,7 @@ func DetectWorkflows(
100100
commit *git.Commit,
101101
triggedEvent webhook_module.HookEventType,
102102
payload api.Payloader,
103+
detectSchedule bool,
103104
) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
104105
entries, err := ListWorkflows(commit)
105106
if err != nil {
@@ -114,6 +115,7 @@ func DetectWorkflows(
114115
return nil, nil, err
115116
}
116117

118+
// one workflow may have multiple events
117119
events, err := GetEventsFromContent(content)
118120
if err != nil {
119121
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
@@ -122,17 +124,18 @@ func DetectWorkflows(
122124
for _, evt := range events {
123125
log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent)
124126
if evt.IsSchedule() {
125-
dwf := &DetectedWorkflow{
126-
EntryName: entry.Name(),
127-
TriggerEvent: evt.Name,
128-
Content: content,
127+
if detectSchedule {
128+
dwf := &DetectedWorkflow{
129+
EntryName: entry.Name(),
130+
TriggerEvent: evt,
131+
Content: content,
132+
}
133+
schedules = append(schedules, dwf)
129134
}
130-
schedules = append(schedules, dwf)
131-
}
132-
if detectMatched(gitRepo, commit, triggedEvent, payload, evt) {
135+
} else if detectMatched(gitRepo, commit, triggedEvent, payload, evt) {
133136
dwf := &DetectedWorkflow{
134137
EntryName: entry.Name(),
135-
TriggerEvent: evt.Name,
138+
TriggerEvent: evt,
136139
Content: content,
137140
}
138141
workflows = append(workflows, dwf)
@@ -153,7 +156,8 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
153156
webhook_module.HookEventCreate,
154157
webhook_module.HookEventDelete,
155158
webhook_module.HookEventFork,
156-
webhook_module.HookEventWiki:
159+
webhook_module.HookEventWiki,
160+
webhook_module.HookEventSchedule:
157161
if len(evt.Acts()) != 0 {
158162
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
159163
}

modules/actions/workflows_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ func TestDetectMatched(t *testing.T) {
118118
yamlOn: "on: gollum",
119119
expected: true,
120120
},
121+
{
122+
desc: "HookEventSchedue(schedule) matches GithubEventSchedule(schedule)",
123+
triggedEvent: webhook_module.HookEventSchedule,
124+
payload: nil,
125+
yamlOn: "on: schedule",
126+
expected: true,
127+
},
121128
}
122129

123130
for _, tc := range testCases {

modules/webhook/type.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
HookEventRepository HookEventType = "repository"
3232
HookEventRelease HookEventType = "release"
3333
HookEventPackage HookEventType = "package"
34+
HookEventSchedule HookEventType = "schedule"
3435
)
3536

3637
// Event returns the HookEventType as an event string

routers/api/v1/repo/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
983983
}
984984

985985
if len(units)+len(deleteUnitTypes) > 0 {
986-
if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil {
986+
if err := repo_service.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil {
987987
ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err)
988988
return err
989989
}

routers/web/repo/setting/default_branch.go

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ package setting
66
import (
77
"net/http"
88

9-
repo_model "code.gitea.io/gitea/models/repo"
9+
git_model "code.gitea.io/gitea/models/git"
1010
"code.gitea.io/gitea/modules/context"
11-
"code.gitea.io/gitea/modules/git"
1211
"code.gitea.io/gitea/modules/log"
1312
"code.gitea.io/gitea/modules/setting"
1413
"code.gitea.io/gitea/routers/web/repo"
15-
notify_service "code.gitea.io/gitea/services/notify"
14+
repo_service "code.gitea.io/gitea/services/repository"
1615
)
1716

1817
// SetDefaultBranchPost set default branch
@@ -35,23 +34,14 @@ func SetDefaultBranchPost(ctx *context.Context) {
3534
}
3635

3736
branch := ctx.FormString("branch")
38-
if !ctx.Repo.GitRepo.IsBranchExist(branch) {
39-
ctx.Status(http.StatusNotFound)
40-
return
41-
} else if repo.DefaultBranch != branch {
42-
repo.DefaultBranch = branch
43-
if err := ctx.Repo.GitRepo.SetDefaultBranch(branch); err != nil {
44-
if !git.IsErrUnsupportedVersion(err) {
45-
ctx.ServerError("SetDefaultBranch", err)
46-
return
47-
}
48-
}
49-
if err := repo_model.UpdateDefaultBranch(ctx, repo); err != nil {
37+
if err := repo_service.SetRepoDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, branch); err != nil {
38+
switch {
39+
case git_model.IsErrBranchNotExist(err):
40+
ctx.Status(http.StatusNotFound)
41+
default:
5042
ctx.ServerError("SetDefaultBranch", err)
51-
return
5243
}
53-
54-
notify_service.ChangeDefaultBranch(ctx, repo)
44+
return
5545
}
5646

5747
log.Trace("Repository basic settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)

routers/web/repo/setting/setting.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ func SettingsPost(ctx *context.Context) {
594594
return
595595
}
596596

597-
if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil {
597+
if err := repo_service.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil {
598598
ctx.ServerError("UpdateRepositoryUnits", err)
599599
return
600600
}

0 commit comments

Comments
 (0)