Fix an actions schedule bug (#28942)
In #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
This commit is contained in:
parent
0b1a42ce0f
commit
adc3598a75
|
@ -146,6 +146,41 @@ func DetectWorkflows(
|
||||||
return workflows, schedules, nil
|
return workflows, schedules, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
|
||||||
|
entries, err := ListWorkflows(commit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wfs := make([]*DetectedWorkflow, 0, len(entries))
|
||||||
|
for _, entry := range entries {
|
||||||
|
content, err := GetContentFromEntry(entry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// one workflow may have multiple events
|
||||||
|
events, err := GetEventsFromContent(content)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, evt := range events {
|
||||||
|
if evt.IsSchedule() {
|
||||||
|
log.Trace("detect scheduled workflow: %q", entry.Name())
|
||||||
|
dwf := &DetectedWorkflow{
|
||||||
|
EntryName: entry.Name(),
|
||||||
|
TriggerEvent: evt,
|
||||||
|
Content: content,
|
||||||
|
}
|
||||||
|
wfs = append(wfs, dwf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wfs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
|
func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {
|
||||||
if !canGithubEventMatch(evt.Name, triggedEvent) {
|
if !canGithubEventMatch(evt.Name, triggedEvent) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -203,7 +203,7 @@ func getWikiPage(ctx *context.APIContext, wikiName wiki_service.WebPath) *api.Wi
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.WikiPage{
|
return &api.WikiPage{
|
||||||
WikiPageMetaData: convert.ToWikiPageMetaData(wikiName, lastCommit, ctx.Repo.Repository),
|
WikiPageMetaData: wiki_service.ToWikiPageMetaData(wikiName, lastCommit, ctx.Repo.Repository),
|
||||||
ContentBase64: content,
|
ContentBase64: content,
|
||||||
CommitCount: commitsCount,
|
CommitCount: commitsCount,
|
||||||
Sidebar: sidebarContent,
|
Sidebar: sidebarContent,
|
||||||
|
@ -333,7 +333,7 @@ func ListWikiPages(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err)
|
ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pages = append(pages, convert.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository))
|
pages = append(pages, wiki_service.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetTotalCountHeader(int64(len(entries)))
|
ctx.SetTotalCountHeader(int64(len(entries)))
|
||||||
|
|
|
@ -474,3 +474,35 @@ func handleSchedules(
|
||||||
|
|
||||||
return actions_model.CreateScheduleTask(ctx, crons)
|
return actions_model.CreateScheduleTask(ctx, crons)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DetectAndHandleSchedules detects the schedule workflows on the default branch and create schedule tasks
|
||||||
|
func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository) error {
|
||||||
|
gitRepo, err := gitrepo.OpenRepository(context.Background(), repo)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("git.OpenRepository: %w", err)
|
||||||
|
}
|
||||||
|
defer gitRepo.Close()
|
||||||
|
|
||||||
|
// Only detect schedule workflows on the default branch
|
||||||
|
commit, err := gitRepo.GetCommit(repo.DefaultBranch)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
||||||
|
}
|
||||||
|
scheduleWorkflows, err := actions_module.DetectScheduledWorkflows(gitRepo, commit)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("detect schedule workflows: %w", err)
|
||||||
|
}
|
||||||
|
if len(scheduleWorkflows) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need a notifyInput to call handleSchedules
|
||||||
|
// Here we use the commit author as the Doer of the notifyInput
|
||||||
|
commitUser, err := user_model.GetUserByEmail(ctx, commit.Author.Email)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("get user by email: %w", err)
|
||||||
|
}
|
||||||
|
notifyInput := newNotifyInput(repo, commitUser, webhook_module.HookEventSchedule)
|
||||||
|
|
||||||
|
return handleSchedules(ctx, scheduleWorkflows, commit, notifyInput, repo.DefaultBranch)
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -65,8 +66,15 @@ func startTasks(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := row.Repo.MustGetUnit(ctx, unit.TypeActions).ActionsConfig()
|
cfg, err := row.Repo.GetUnit(ctx, unit.TypeActions)
|
||||||
if cfg.IsWorkflowDisabled(row.Schedule.WorkflowID) {
|
if err != nil {
|
||||||
|
if repo_model.IsErrUnitTypeNotExist(err) {
|
||||||
|
// Skip the actions unit of this repo is disabled.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("GetUnit: %w", err)
|
||||||
|
}
|
||||||
|
if cfg.ActionsConfig().IsWorkflowDisabled(row.Schedule.WorkflowID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,8 @@ package convert
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
wiki_service "code.gitea.io/gitea/services/wiki"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToWikiCommit convert a git commit into a WikiCommit
|
// ToWikiCommit convert a git commit into a WikiCommit
|
||||||
|
@ -46,15 +43,3 @@ func ToWikiCommitList(commits []*git.Commit, total int64) *api.WikiCommitList {
|
||||||
Count: total,
|
Count: total,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToWikiPageMetaData converts meta information to a WikiPageMetaData
|
|
||||||
func ToWikiPageMetaData(wikiName wiki_service.WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.WikiPageMetaData {
|
|
||||||
subURL := string(wikiName)
|
|
||||||
_, title := wiki_service.WebPathToUserTitle(wikiName)
|
|
||||||
return &api.WikiPageMetaData{
|
|
||||||
Title: title,
|
|
||||||
HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL),
|
|
||||||
SubURL: subURL,
|
|
||||||
LastCommit: ToWikiCommit(lastCommit),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
actions_service "code.gitea.io/gitea/services/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpdateRepositoryUnits updates a repository's units
|
// UpdateRepositoryUnits updates a repository's units
|
||||||
|
@ -33,6 +34,15 @@ func UpdateRepositoryUnits(ctx context.Context, repo *repo_model.Repository, uni
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, u := range units {
|
||||||
|
if u.Type == unit.TypeActions {
|
||||||
|
if err := actions_service.DetectAndHandleSchedules(ctx, repo); err != nil {
|
||||||
|
log.Error("DetectAndHandleSchedules: %v", err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(repo_model.RepoUnit)); err != nil {
|
if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(repo_model.RepoUnit)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
"code.gitea.io/gitea/services/convert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// To define the wiki related concepts:
|
// To define the wiki related concepts:
|
||||||
|
@ -155,3 +158,15 @@ func UserTitleToWebPath(base, title string) WebPath {
|
||||||
}
|
}
|
||||||
return WebPath(title)
|
return WebPath(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToWikiPageMetaData converts meta information to a WikiPageMetaData
|
||||||
|
func ToWikiPageMetaData(wikiName WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.WikiPageMetaData {
|
||||||
|
subURL := string(wikiName)
|
||||||
|
_, title := WebPathToUserTitle(wikiName)
|
||||||
|
return &api.WikiPageMetaData{
|
||||||
|
Title: title,
|
||||||
|
HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL),
|
||||||
|
SubURL: subURL,
|
||||||
|
LastCommit: convert.ToWikiCommit(lastCommit),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue