Skip to content

Commit 18766a2

Browse files
Zettat123silverwind
authored andcommitted
Fix an actions schedule bug (go-gitea#28942)
In go-gitea#28691, schedule plans will be deleted when a repo's actions unit is disabled. But when the unit is enabled, the schedule plans won't be created again. This PR fixes the bug. The schedule plans will be created again when the actions unit is re-enabled
1 parent 1810f70 commit 18766a2

File tree

7 files changed

+104
-19
lines changed

7 files changed

+104
-19
lines changed

modules/actions/workflows.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,41 @@ func DetectWorkflows(
146146
return workflows, schedules, nil
147147
}
148148

149+
func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
150+
entries, err := ListWorkflows(commit)
151+
if err != nil {
152+
return nil, err
153+
}
154+
155+
wfs := make([]*DetectedWorkflow, 0, len(entries))
156+
for _, entry := range entries {
157+
content, err := GetContentFromEntry(entry)
158+
if err != nil {
159+
return nil, err
160+
}
161+
162+
// one workflow may have multiple events
163+
events, err := GetEventsFromContent(content)
164+
if err != nil {
165+
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
166+
continue
167+
}
168+
for _, evt := range events {
169+
if evt.IsSchedule() {
170+
log.Trace("detect scheduled workflow: %q", entry.Name())
171+
dwf := &DetectedWorkflow{
172+
EntryName: entry.Name(),
173+
TriggerEvent: evt,
174+
Content: content,
175+
}
176+
wfs = append(wfs, dwf)
177+
}
178+
}
179+
}
180+
181+
return wfs, nil
182+
}
183+
149184
func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
150185
if !canGithubEventMatch(evt.Name, triggedEvent) {
151186
return false

routers/api/v1/repo/wiki.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func getUncycloPage(ctx *context.APIContext, wikiName wiki_service.WebPath) *api.Wi
203203
}
204204

205205
return &api.UncycloPage{
206-
UncycloPageMetaData: convert.ToUncycloPageMetaData(wikiName, lastCommit, ctx.Repo.Repository),
206+
UncycloPageMetaData: wiki_service.ToUncycloPageMetaData(wikiName, lastCommit, ctx.Repo.Repository),
207207
ContentBase64: content,
208208
CommitCount: commitsCount,
209209
Sidebar: sidebarContent,
@@ -333,7 +333,7 @@ func ListUncycloPages(ctx *context.APIContext) {
333333
ctx.Error(http.StatusInternalServerError, "UncycloFilenameToName", err)
334334
return
335335
}
336-
pages = append(pages, convert.ToUncycloPageMetaData(wikiName, c, ctx.Repo.Repository))
336+
pages = append(pages, wiki_service.ToUncycloPageMetaData(wikiName, c, ctx.Repo.Repository))
337337
}
338338

339339
ctx.SetTotalCountHeader(int64(len(entries)))

services/actions/notifier_helper.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,35 @@ func handleSchedules(
474474

475475
return actions_model.CreateScheduleTask(ctx, crons)
476476
}
477+
478+
// DetectAndHandleSchedules detects the schedule workflows on the default branch and create schedule tasks
479+
func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository) error {
480+
gitRepo, err := gitrepo.OpenRepository(context.Background(), repo)
481+
if err != nil {
482+
return fmt.Errorf("git.OpenRepository: %w", err)
483+
}
484+
defer gitRepo.Close()
485+
486+
// Only detect schedule workflows on the default branch
487+
commit, err := gitRepo.GetCommit(repo.DefaultBranch)
488+
if err != nil {
489+
return fmt.Errorf("gitRepo.GetCommit: %w", err)
490+
}
491+
scheduleWorkflows, err := actions_module.DetectScheduledWorkflows(gitRepo, commit)
492+
if err != nil {
493+
return fmt.Errorf("detect schedule workflows: %w", err)
494+
}
495+
if len(scheduleWorkflows) == 0 {
496+
return nil
497+
}
498+
499+
// We need a notifyInput to call handleSchedules
500+
// Here we use the commit author as the Doer of the notifyInput
501+
commitUser, err := user_model.GetUserByEmail(ctx, commit.Author.Email)
502+
if err != nil {
503+
return fmt.Errorf("get user by email: %w", err)
504+
}
505+
notifyInput := newNotifyInput(repo, commitUser, webhook_module.HookEventSchedule)
506+
507+
return handleSchedules(ctx, scheduleWorkflows, commit, notifyInput, repo.DefaultBranch)
508+
}

services/actions/schedule_tasks.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
actions_model "code.gitea.io/gitea/models/actions"
1212
"code.gitea.io/gitea/models/db"
13+
repo_model "code.gitea.io/gitea/models/repo"
1314
"code.gitea.io/gitea/models/unit"
1415
"code.gitea.io/gitea/modules/log"
1516
"code.gitea.io/gitea/modules/timeutil"
@@ -65,8 +66,15 @@ func startTasks(ctx context.Context) error {
6566
}
6667
}
6768

68-
cfg := row.Repo.MustGetUnit(ctx, unit.TypeActions).ActionsConfig()
69-
if cfg.IsWorkflowDisabled(row.Schedule.WorkflowID) {
69+
cfg, err := row.Repo.GetUnit(ctx, unit.TypeActions)
70+
if err != nil {
71+
if repo_model.IsErrUnitTypeNotExist(err) {
72+
// Skip the actions unit of this repo is disabled.
73+
continue
74+
}
75+
return fmt.Errorf("GetUnit: %w", err)
76+
}
77+
if cfg.ActionsConfig().IsWorkflowDisabled(row.Schedule.WorkflowID) {
7078
continue
7179
}
7280

services/convert/wiki.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@ package convert
66
import (
77
"time"
88

9-
repo_model "code.gitea.io/gitea/models/repo"
109
"code.gitea.io/gitea/modules/git"
1110
api "code.gitea.io/gitea/modules/structs"
12-
"code.gitea.io/gitea/modules/util"
13-
wiki_service "code.gitea.io/gitea/services/wiki"
1411
)
1512

1613
// ToUncycloCommit convert a git commit into a UncycloCommit
@@ -46,15 +43,3 @@ func ToUncycloCommitList(commits []*git.Commit, total int64) *api.UncycloCommitList {
4643
Count: total,
4744
}
4845
}
49-
50-
// ToUncycloPageMetaData converts meta information to a UncycloPageMetaData
51-
func ToUncycloPageMetaData(wikiName wiki_service.WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.UncycloPageMetaData {
52-
subURL := string(wikiName)
53-
_, title := wiki_service.WebPathToUserTitle(wikiName)
54-
return &api.UncycloPageMetaData{
55-
Title: title,
56-
HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL),
57-
SubURL: subURL,
58-
LastCommit: ToUncycloCommit(lastCommit),
59-
}
60-
}

services/repository/setting.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
repo_model "code.gitea.io/gitea/models/repo"
1313
"code.gitea.io/gitea/models/unit"
1414
"code.gitea.io/gitea/modules/log"
15+
actions_service "code.gitea.io/gitea/services/actions"
1516
)
1617

1718
// UpdateRepositoryUnits updates a repository's units
@@ -33,6 +34,15 @@ func UpdateRepositoryUnits(ctx context.Context, repo *repo_model.Repository, uni
3334
}
3435
}
3536

37+
for _, u := range units {
38+
if u.Type == unit.TypeActions {
39+
if err := actions_service.DetectAndHandleSchedules(ctx, repo); err != nil {
40+
log.Error("DetectAndHandleSchedules: %v", err)
41+
}
42+
break
43+
}
44+
}
45+
3646
if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(repo_model.RepoUnit)); err != nil {
3747
return err
3848
}

services/wiki/wiki_path.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import (
99
"strings"
1010

1111
repo_model "code.gitea.io/gitea/models/repo"
12+
"code.gitea.io/gitea/modules/git"
13+
api "code.gitea.io/gitea/modules/structs"
1214
"code.gitea.io/gitea/modules/util"
15+
"code.gitea.io/gitea/services/convert"
1316
)
1417

1518
// To define the wiki related concepts:
@@ -155,3 +158,15 @@ func UserTitleToWebPath(base, title string) WebPath {
155158
}
156159
return WebPath(title)
157160
}
161+
162+
// ToUncycloPageMetaData converts meta information to a UncycloPageMetaData
163+
func ToUncycloPageMetaData(wikiName WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.UncycloPageMetaData {
164+
subURL := string(wikiName)
165+
_, title := WebPathToUserTitle(wikiName)
166+
return &api.UncycloPageMetaData{
167+
Title: title,
168+
HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL),
169+
SubURL: subURL,
170+
LastCommit: convert.ToUncycloCommit(lastCommit),
171+
}
172+
}

0 commit comments

Comments
 (0)