loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request '[ACTIONS] port scheduled actions from Gitea' (#2826) from earl-warren/forgejo:wip-gitea-schedule into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2826
Reviewed-by: Gusted <gusted@noreply.codeberg.org>

+292 -133
-1
.deadcode-out
··· 329 329 330 330 package "code.gitea.io/gitea/services/repository" 331 331 func IsErrForkAlreadyExist 332 - func UpdateRepositoryUnits 333 332 334 333 package "code.gitea.io/gitea/services/repository/archiver" 335 334 func ArchiveRepository
+9 -7
models/actions/run.go
··· 170 170 return err 171 171 } 172 172 173 - // CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. 174 - func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error { 175 - // Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. 173 + // CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event. 174 + // It's useful when a new run is triggered, and all previous runs needn't be continued anymore. 175 + func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { 176 + // Find all runs in the specified repository, reference, and workflow with non-final status 176 177 runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{ 177 - RepoID: repoID, 178 - Ref: ref, 179 - WorkflowID: workflowID, 180 - Status: []Status{StatusRunning, StatusWaiting}, 178 + RepoID: repoID, 179 + Ref: ref, 180 + WorkflowID: workflowID, 181 + TriggerEvent: event, 182 + Status: []Status{StatusRunning, StatusWaiting, StatusBlocked}, 181 183 }) 182 184 if err != nil { 183 185 return err
+5
models/actions/run_list.go
··· 10 10 repo_model "code.gitea.io/gitea/models/repo" 11 11 user_model "code.gitea.io/gitea/models/user" 12 12 "code.gitea.io/gitea/modules/container" 13 + webhook_module "code.gitea.io/gitea/modules/webhook" 13 14 14 15 "xorm.io/builder" 15 16 ) ··· 71 72 WorkflowID string 72 73 Ref string // the commit/tag/… that caused this workflow 73 74 TriggerUserID int64 75 + TriggerEvent webhook_module.HookEventType 74 76 Approved bool // not util.OptionalBool, it works only when it's true 75 77 Status []Status 76 78 } ··· 97 99 } 98 100 if opts.Ref != "" { 99 101 cond = cond.And(builder.Eq{"ref": opts.Ref}) 102 + } 103 + if opts.TriggerEvent != "" { 104 + cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent}) 100 105 } 101 106 return cond 102 107 }
+20
models/actions/schedule.go
··· 5 5 6 6 import ( 7 7 "context" 8 + "fmt" 8 9 "time" 9 10 10 11 "code.gitea.io/gitea/models/db" ··· 118 119 119 120 return committer.Commit() 120 121 } 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 := CancelPreviousJobs( 131 + ctx, 132 + repo.ID, 133 + repo.DefaultBranch, 134 + "", 135 + webhook_module.HookEventSchedule, 136 + ); err != nil { 137 + return fmt.Errorf("CancelPreviousJobs: %v", err) 138 + } 139 + return nil 140 + }
+2 -2
models/git/branch.go
··· 292 292 } 293 293 294 294 // RenameBranch rename a branch 295 - func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to string, gitAction func(isDefault bool) error) (err error) { 295 + func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to string, gitAction func(ctx context.Context, isDefault bool) error) (err error) { 296 296 ctx, committer, err := db.TxContext(ctx) 297 297 if err != nil { 298 298 return err ··· 367 367 } 368 368 369 369 // 5. do git action 370 - if err = gitAction(isDefault); err != nil { 370 + if err = gitAction(ctx, isDefault); err != nil { 371 371 return err 372 372 } 373 373
+2 -1
models/git/branch_test.go
··· 4 4 package git_test 5 5 6 6 import ( 7 + "context" 7 8 "testing" 8 9 9 10 "code.gitea.io/gitea/models/db" ··· 132 133 }, git_model.WhitelistOptions{})) 133 134 assert.NoError(t, committer.Commit()) 134 135 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 { 136 137 _isDefault = isDefault 137 138 return nil 138 139 }))
-26
models/repo/repo_unit.go
··· 316 316 _, err := db.GetEngine(ctx).ID(unit.ID).Update(unit) 317 317 return err 318 318 } 319 - 320 - // UpdateRepositoryUnits updates a repository's units 321 - func UpdateRepositoryUnits(ctx context.Context, repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) { 322 - ctx, committer, err := db.TxContext(ctx) 323 - if err != nil { 324 - return err 325 - } 326 - defer committer.Close() 327 - 328 - // Delete existing settings of units before adding again 329 - for _, u := range units { 330 - deleteUnitTypes = append(deleteUnitTypes, u.Type) 331 - } 332 - 333 - if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil { 334 - return err 335 - } 336 - 337 - if len(units) > 0 { 338 - if err = db.Insert(ctx, units); err != nil { 339 - return err 340 - } 341 - } 342 - 343 - return committer.Commit() 344 - }
+3 -3
modules/actions/github.go
··· 74 74 case GithubEventGollum: 75 75 return triggedEvent == webhook_module.HookEventWiki 76 76 77 - case GithubEventSchedule: 78 - return triggedEvent == webhook_module.HookEventSchedule 79 - 80 77 case GithubEventIssues: 81 78 switch triggedEvent { 82 79 case webhook_module.HookEventIssues, ··· 118 115 // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment 119 116 return triggedEvent == webhook_module.HookEventIssueComment || 120 117 triggedEvent == webhook_module.HookEventPullRequestComment 118 + 119 + case GithubEventSchedule: 120 + return triggedEvent == webhook_module.HookEventSchedule 121 121 122 122 default: 123 123 return eventName == string(triggedEvent)
+47 -9
modules/actions/workflows.go
··· 22 22 23 23 type DetectedWorkflow struct { 24 24 EntryName string 25 - TriggerEvent string 25 + TriggerEvent *jobparser.Event 26 26 Content []byte 27 27 } 28 28 ··· 103 103 commit *git.Commit, 104 104 triggedEvent webhook_module.HookEventType, 105 105 payload api.Payloader, 106 + detectSchedule bool, 106 107 ) ([]*DetectedWorkflow, []*DetectedWorkflow, error) { 107 108 entries, err := ListWorkflows(commit) 108 109 if err != nil { ··· 117 118 return nil, nil, err 118 119 } 119 120 121 + // one workflow may have multiple events 120 122 events, err := GetEventsFromContent(content) 121 123 if err != nil { 122 124 log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) ··· 125 127 for _, evt := range events { 126 128 log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent) 127 129 if evt.IsSchedule() { 130 + if detectSchedule { 131 + dwf := &DetectedWorkflow{ 132 + EntryName: entry.Name(), 133 + TriggerEvent: evt, 134 + Content: content, 135 + } 136 + schedules = append(schedules, dwf) 137 + } 138 + } else if detectMatched(gitRepo, commit, triggedEvent, payload, evt) { 128 139 dwf := &DetectedWorkflow{ 129 140 EntryName: entry.Name(), 130 - TriggerEvent: evt.Name, 141 + TriggerEvent: evt, 131 142 Content: content, 132 143 } 133 - schedules = append(schedules, dwf) 144 + workflows = append(workflows, dwf) 134 145 } 135 - if detectMatched(gitRepo, commit, triggedEvent, payload, evt) { 146 + } 147 + } 148 + 149 + return workflows, schedules, nil 150 + } 151 + 152 + func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) { 153 + entries, err := ListWorkflows(commit) 154 + if err != nil { 155 + return nil, err 156 + } 157 + 158 + wfs := make([]*DetectedWorkflow, 0, len(entries)) 159 + for _, entry := range entries { 160 + content, err := GetContentFromEntry(entry) 161 + if err != nil { 162 + return nil, err 163 + } 164 + 165 + // one workflow may have multiple events 166 + events, err := GetEventsFromContent(content) 167 + if err != nil { 168 + log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) 169 + continue 170 + } 171 + for _, evt := range events { 172 + if evt.IsSchedule() { 173 + log.Trace("detect scheduled workflow: %q", entry.Name()) 136 174 dwf := &DetectedWorkflow{ 137 175 EntryName: entry.Name(), 138 - TriggerEvent: evt.Name, 176 + TriggerEvent: evt, 139 177 Content: content, 140 178 } 141 - workflows = append(workflows, dwf) 179 + wfs = append(wfs, dwf) 142 180 } 143 181 } 144 182 } 145 183 146 - return workflows, schedules, nil 184 + return wfs, nil 147 185 } 148 186 149 187 func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool { ··· 153 191 154 192 switch triggedEvent { 155 193 case // events with no activity types 156 - webhook_module.HookEventSchedule, 157 194 webhook_module.HookEventCreate, 158 195 webhook_module.HookEventDelete, 159 196 webhook_module.HookEventFork, 160 - webhook_module.HookEventWiki: 197 + webhook_module.HookEventWiki, 198 + webhook_module.HookEventSchedule: 161 199 if len(evt.Acts()) != 0 { 162 200 log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts()) 163 201 }
+1 -1
routers/api/v1/repo/repo.go
··· 1001 1001 } 1002 1002 1003 1003 if len(units)+len(deleteUnitTypes) > 0 { 1004 - if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { 1004 + if err := repo_service.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { 1005 1005 ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err) 1006 1006 return err 1007 1007 }
+2 -2
routers/api/v1/repo/wiki.go
··· 203 203 } 204 204 205 205 return &api.WikiPage{ 206 - WikiPageMetaData: convert.ToWikiPageMetaData(wikiName, lastCommit, ctx.Repo.Repository), 206 + WikiPageMetaData: wiki_service.ToWikiPageMetaData(wikiName, lastCommit, ctx.Repo.Repository), 207 207 ContentBase64: content, 208 208 CommitCount: commitsCount, 209 209 Sidebar: sidebarContent, ··· 333 333 ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) 334 334 return 335 335 } 336 - pages = append(pages, convert.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository)) 336 + pages = append(pages, wiki_service.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository)) 337 337 } 338 338 339 339 ctx.SetTotalCountHeader(int64(len(entries)))
+8 -19
routers/web/repo/setting/default_branch.go
··· 6 6 import ( 7 7 "net/http" 8 8 9 - repo_model "code.gitea.io/gitea/models/repo" 10 - "code.gitea.io/gitea/modules/git" 11 - "code.gitea.io/gitea/modules/gitrepo" 9 + git_model "code.gitea.io/gitea/models/git" 12 10 "code.gitea.io/gitea/modules/log" 13 11 "code.gitea.io/gitea/modules/setting" 14 12 "code.gitea.io/gitea/routers/web/repo" 15 13 "code.gitea.io/gitea/services/context" 16 - notify_service "code.gitea.io/gitea/services/notify" 14 + repo_service "code.gitea.io/gitea/services/repository" 17 15 ) 18 16 19 17 // SetDefaultBranchPost set default branch ··· 36 34 } 37 35 38 36 branch := ctx.FormString("branch") 39 - if !ctx.Repo.GitRepo.IsBranchExist(branch) { 40 - ctx.Status(http.StatusNotFound) 41 - return 42 - } else if repo.DefaultBranch != branch { 43 - repo.DefaultBranch = branch 44 - if err := gitrepo.SetDefaultBranch(ctx, repo, branch); err != nil { 45 - if !git.IsErrUnsupportedVersion(err) { 46 - ctx.ServerError("SetDefaultBranch", err) 47 - return 48 - } 49 - } 50 - 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: 51 42 ctx.ServerError("SetDefaultBranch", err) 52 - return 53 43 } 54 - 55 - notify_service.ChangeDefaultBranch(ctx, repo) 44 + return 56 45 } 57 46 58 47 log.Trace("Repository basic settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
+1 -1
routers/web/repo/setting/setting.go
··· 269 269 return 270 270 } 271 271 272 - if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { 272 + if err := repo_service.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { 273 273 ctx.ServerError("UpdateRepositoryUnits", err) 274 274 return 275 275 }
+76 -38
services/actions/notifier_helper.go
··· 123 123 return nil 124 124 } 125 125 if unit_model.TypeActions.UnitGlobalDisabled() { 126 + if err := actions_model.CleanRepoScheduleTasks(ctx, input.Repo); err != nil { 127 + log.Error("CleanRepoScheduleTasks: %v", err) 128 + } 126 129 return nil 127 130 } 128 131 if err := input.Repo.LoadUnits(ctx); err != nil { ··· 167 170 168 171 var detectedWorkflows []*actions_module.DetectedWorkflow 169 172 actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig() 170 - workflows, schedules, err := actions_module.DetectWorkflows(gitRepo, commit, input.Event, input.Payload) 173 + shouldDetectSchedules := input.Event == webhook_module.HookEventPush && git.RefName(input.Ref).BranchName() == input.Repo.DefaultBranch 174 + workflows, schedules, err := actions_module.DetectWorkflows(gitRepo, commit, 175 + input.Event, 176 + input.Payload, 177 + shouldDetectSchedules, 178 + ) 171 179 if err != nil { 172 180 return fmt.Errorf("DetectWorkflows: %w", err) 173 181 } 174 182 175 - if len(workflows) == 0 { 176 - log.Trace("repo %s with commit %s couldn't find workflows", input.Repo.RepoPath(), commit.ID) 177 - } else { 178 - for _, wf := range workflows { 179 - if actionsConfig.IsWorkflowDisabled(wf.EntryName) { 180 - log.Trace("repo %s has disable workflows %s", input.Repo.RepoPath(), wf.EntryName) 181 - continue 182 - } 183 + log.Trace("repo %s with commit %s event %s find %d workflows and %d schedules", 184 + input.Repo.RepoPath(), 185 + commit.ID, 186 + input.Event, 187 + len(workflows), 188 + len(schedules), 189 + ) 190 + 191 + for _, wf := range workflows { 192 + if actionsConfig.IsWorkflowDisabled(wf.EntryName) { 193 + log.Trace("repo %s has disable workflows %s", input.Repo.RepoPath(), wf.EntryName) 194 + continue 195 + } 183 196 184 - if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget { 185 - detectedWorkflows = append(detectedWorkflows, wf) 186 - } 197 + if wf.TriggerEvent.Name != actions_module.GithubEventPullRequestTarget { 198 + detectedWorkflows = append(detectedWorkflows, wf) 187 199 } 188 200 } 189 201 ··· 200 212 } 201 213 return fmt.Errorf("gitRepo.GetCommit: %w", err) 202 214 } 203 - baseWorkflows, _, err := actions_module.DetectWorkflows(gitRepo, baseCommit, input.Event, input.Payload) 215 + baseWorkflows, _, err := actions_module.DetectWorkflows(gitRepo, baseCommit, input.Event, input.Payload, false) 204 216 if err != nil { 205 217 return fmt.Errorf("DetectWorkflows: %w", err) 206 218 } ··· 208 220 log.Trace("repo %s with commit %s couldn't find pull_request_target workflows", input.Repo.RepoPath(), baseCommit.ID) 209 221 } else { 210 222 for _, wf := range baseWorkflows { 211 - if wf.TriggerEvent == actions_module.GithubEventPullRequestTarget { 223 + if wf.TriggerEvent.Name == actions_module.GithubEventPullRequestTarget { 212 224 detectedWorkflows = append(detectedWorkflows, wf) 213 225 } 214 226 } 215 227 } 216 228 } 217 229 218 - if err := handleSchedules(ctx, schedules, commit, input, ref); err != nil { 219 - return err 230 + if shouldDetectSchedules { 231 + if err := handleSchedules(ctx, schedules, commit, input, ref); err != nil { 232 + return err 233 + } 220 234 } 221 235 222 236 return handleWorkflows(ctx, detectedWorkflows, commit, input, ref) ··· 307 321 IsForkPullRequest: isForkPullRequest, 308 322 Event: input.Event, 309 323 EventPayload: string(p), 310 - TriggerEvent: dwf.TriggerEvent, 324 + TriggerEvent: dwf.TriggerEvent.Name, 311 325 Status: actions_model.StatusWaiting, 312 326 } 313 327 if need, err := ifNeedApproval(ctx, run, input.Repo, input.Doer); err != nil { ··· 334 348 continue 335 349 } 336 350 337 - // cancel running jobs if the event is push 338 - if run.Event == webhook_module.HookEventPush { 339 - // cancel running jobs of the same workflow 340 - if err := actions_model.CancelRunningJobs( 351 + // cancel running jobs if the event is push or pull_request_sync 352 + if run.Event == webhook_module.HookEventPush || 353 + run.Event == webhook_module.HookEventPullRequestSync { 354 + if err := actions_model.CancelPreviousJobs( 341 355 ctx, 342 356 run.RepoID, 343 357 run.Ref, 344 358 run.WorkflowID, 359 + run.Event, 345 360 ); err != nil { 346 - log.Error("CancelRunningJobs: %v", err) 361 + log.Error("CancelPreviousJobs: %v", err) 347 362 } 348 363 } 349 364 ··· 467 482 log.Error("CountSchedules: %v", err) 468 483 return err 469 484 } else if count > 0 { 470 - if err := actions_model.DeleteScheduleTaskByRepo(ctx, input.Repo.ID); err != nil { 471 - log.Error("DeleteCronTaskByRepo: %v", err) 485 + if err := actions_model.CleanRepoScheduleTasks(ctx, input.Repo); err != nil { 486 + log.Error("CleanRepoScheduleTasks: %v", err) 472 487 } 473 488 } 474 489 ··· 508 523 TriggerUserID: input.Doer.ID, 509 524 Ref: input.Repo.DefaultBranch, 510 525 CommitSHA: commit.ID.String(), 511 - Event: webhook_module.HookEventType(api.HookScheduleCreated), 526 + Event: input.Event, 512 527 EventPayload: string(p), 513 528 Specs: schedules, 514 529 Content: dwf.Content, 515 530 } 516 - 517 - // cancel running jobs if the event is push 518 - if run.Event == webhook_module.HookEventPush { 519 - // cancel running jobs of the same workflow 520 - if err := actions_model.CancelRunningJobs( 521 - ctx, 522 - run.RepoID, 523 - run.Ref, 524 - run.WorkflowID, 525 - ); err != nil { 526 - log.Error("CancelRunningJobs: %v", err) 527 - } 528 - } 529 531 crons = append(crons, run) 530 532 } 531 533 532 534 return actions_model.CreateScheduleTask(ctx, crons) 533 535 } 536 + 537 + // DetectAndHandleSchedules detects the schedule workflows on the default branch and create schedule tasks 538 + func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository) error { 539 + if repo.IsEmpty { 540 + return nil 541 + } 542 + 543 + gitRepo, err := gitrepo.OpenRepository(context.Background(), repo) 544 + if err != nil { 545 + return fmt.Errorf("git.OpenRepository: %w", err) 546 + } 547 + defer gitRepo.Close() 548 + 549 + // Only detect schedule workflows on the default branch 550 + commit, err := gitRepo.GetCommit(repo.DefaultBranch) 551 + if err != nil { 552 + return fmt.Errorf("gitRepo.GetCommit: %w", err) 553 + } 554 + scheduleWorkflows, err := actions_module.DetectScheduledWorkflows(gitRepo, commit) 555 + if err != nil { 556 + return fmt.Errorf("detect schedule workflows: %w", err) 557 + } 558 + if len(scheduleWorkflows) == 0 { 559 + return nil 560 + } 561 + 562 + // We need a notifyInput to call handleSchedules 563 + // Here we use the commit author as the Doer of the notifyInput 564 + commitUser, err := user_model.GetUserByEmail(ctx, commit.Author.Email) 565 + if err != nil { 566 + return fmt.Errorf("get user by email: %w", err) 567 + } 568 + notifyInput := newNotifyInput(repo, commitUser, webhook_module.HookEventSchedule) 569 + 570 + return handleSchedules(ctx, scheduleWorkflows, commit, notifyInput, repo.DefaultBranch) 571 + }
+14 -5
services/actions/schedule_tasks.go
··· 10 10 11 11 actions_model "code.gitea.io/gitea/models/actions" 12 12 "code.gitea.io/gitea/models/db" 13 + repo_model "code.gitea.io/gitea/models/repo" 13 14 "code.gitea.io/gitea/models/unit" 14 15 "code.gitea.io/gitea/modules/log" 15 16 "code.gitea.io/gitea/modules/timeutil" ··· 54 55 // cancel running jobs if the event is push 55 56 if row.Schedule.Event == webhook_module.HookEventPush { 56 57 // cancel running jobs of the same workflow 57 - if err := actions_model.CancelRunningJobs( 58 + if err := actions_model.CancelPreviousJobs( 58 59 ctx, 59 60 row.RepoID, 60 61 row.Schedule.Ref, 61 62 row.Schedule.WorkflowID, 63 + webhook_module.HookEventSchedule, 62 64 ); err != nil { 63 - log.Error("CancelRunningJobs: %v", err) 65 + log.Error("CancelPreviousJobs: %v", err) 64 66 } 65 67 } 66 68 67 - cfg := row.Repo.MustGetUnit(ctx, unit.TypeActions).ActionsConfig() 68 - 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) { 69 78 continue 70 79 } 71 80 ··· 112 121 Ref: cron.Ref, 113 122 CommitSHA: cron.CommitSHA, 114 123 Event: cron.Event, 115 - TriggerEvent: string(webhook_module.HookEventSchedule), 116 124 EventPayload: cron.EventPayload, 125 + TriggerEvent: string(webhook_module.HookEventSchedule), 117 126 ScheduleID: cron.ID, 118 127 Status: actions_model.StatusWaiting, 119 128 }
-15
services/convert/wiki.go
··· 6 6 import ( 7 7 "time" 8 8 9 - repo_model "code.gitea.io/gitea/models/repo" 10 9 "code.gitea.io/gitea/modules/git" 11 10 api "code.gitea.io/gitea/modules/structs" 12 - "code.gitea.io/gitea/modules/util" 13 - wiki_service "code.gitea.io/gitea/services/wiki" 14 11 ) 15 12 16 13 // ToWikiCommit convert a git commit into a WikiCommit ··· 46 43 Count: total, 47 44 } 48 45 } 49 - 50 - // ToWikiPageMetaData converts meta information to a WikiPageMetaData 51 - func ToWikiPageMetaData(wikiName wiki_service.WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.WikiPageMetaData { 52 - subURL := string(wikiName) 53 - _, title := wiki_service.WebPathToUserTitle(wikiName) 54 - return &api.WikiPageMetaData{ 55 - Title: title, 56 - HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL), 57 - SubURL: subURL, 58 - LastCommit: ToWikiCommit(lastCommit), 59 - } 60 - }
+65 -1
services/repository/branch.go
··· 10 10 "strings" 11 11 12 12 "code.gitea.io/gitea/models" 13 + actions_model "code.gitea.io/gitea/models/actions" 13 14 "code.gitea.io/gitea/models/db" 14 15 git_model "code.gitea.io/gitea/models/git" 15 16 issues_model "code.gitea.io/gitea/models/issues" ··· 23 24 "code.gitea.io/gitea/modules/queue" 24 25 repo_module "code.gitea.io/gitea/modules/repository" 25 26 "code.gitea.io/gitea/modules/timeutil" 27 + webhook_module "code.gitea.io/gitea/modules/webhook" 26 28 notify_service "code.gitea.io/gitea/services/notify" 27 29 files_service "code.gitea.io/gitea/services/repository/files" 28 30 ··· 359 361 return "from_not_exist", nil 360 362 } 361 363 362 - if err := git_model.RenameBranch(ctx, repo, from, to, func(isDefault bool) error { 364 + if err := git_model.RenameBranch(ctx, repo, from, to, func(ctx context.Context, isDefault bool) error { 363 365 err2 := gitRepo.RenameBranch(from, to) 364 366 if err2 != nil { 365 367 return err2 366 368 } 367 369 368 370 if isDefault { 371 + // if default branch changed, we need to delete all schedules and cron jobs 372 + if err := actions_model.DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil { 373 + log.Error("DeleteCronTaskByRepo: %v", err) 374 + } 375 + // cancel running cron jobs of this repository and delete old schedules 376 + if err := actions_model.CancelPreviousJobs( 377 + ctx, 378 + repo.ID, 379 + from, 380 + "", 381 + webhook_module.HookEventSchedule, 382 + ); err != nil { 383 + log.Error("CancelPreviousJobs: %v", err) 384 + } 385 + 369 386 err2 = gitrepo.SetDefaultBranch(ctx, repo, to) 370 387 if err2 != nil { 371 388 return err2 ··· 498 515 } 499 516 return nil 500 517 } 518 + 519 + func SetRepoDefaultBranch(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, newBranchName string) error { 520 + if repo.DefaultBranch == newBranchName { 521 + return nil 522 + } 523 + 524 + if !gitRepo.IsBranchExist(newBranchName) { 525 + return git_model.ErrBranchNotExist{ 526 + BranchName: newBranchName, 527 + } 528 + } 529 + 530 + oldDefaultBranchName := repo.DefaultBranch 531 + repo.DefaultBranch = newBranchName 532 + if err := db.WithTx(ctx, func(ctx context.Context) error { 533 + if err := repo_model.UpdateDefaultBranch(ctx, repo); err != nil { 534 + return err 535 + } 536 + 537 + if err := actions_model.DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil { 538 + log.Error("DeleteCronTaskByRepo: %v", err) 539 + } 540 + // cancel running cron jobs of this repository and delete old schedules 541 + if err := actions_model.CancelPreviousJobs( 542 + ctx, 543 + repo.ID, 544 + oldDefaultBranchName, 545 + "", 546 + webhook_module.HookEventSchedule, 547 + ); err != nil { 548 + log.Error("CancelPreviousJobs: %v", err) 549 + } 550 + 551 + if err := gitrepo.SetDefaultBranch(ctx, repo, newBranchName); err != nil { 552 + if !git.IsErrUnsupportedVersion(err) { 553 + return err 554 + } 555 + } 556 + return nil 557 + }); err != nil { 558 + return err 559 + } 560 + 561 + notify_service.ChangeDefaultBranch(ctx, repo) 562 + 563 + return nil 564 + }
+19
services/repository/setting.go
··· 5 5 6 6 import ( 7 7 "context" 8 + "slices" 8 9 10 + actions_model "code.gitea.io/gitea/models/actions" 9 11 "code.gitea.io/gitea/models/db" 10 12 repo_model "code.gitea.io/gitea/models/repo" 11 13 "code.gitea.io/gitea/models/unit" 14 + "code.gitea.io/gitea/modules/log" 15 + actions_service "code.gitea.io/gitea/services/actions" 12 16 ) 13 17 14 18 // UpdateRepositoryUnits updates a repository's units ··· 22 26 // Delete existing settings of units before adding again 23 27 for _, u := range units { 24 28 deleteUnitTypes = append(deleteUnitTypes, u.Type) 29 + } 30 + 31 + if slices.Contains(deleteUnitTypes, unit.TypeActions) { 32 + if err := actions_model.CleanRepoScheduleTasks(ctx, repo); err != nil { 33 + log.Error("CleanRepoScheduleTasks: %v", err) 34 + } 35 + } 36 + 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 + } 25 44 } 26 45 27 46 if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(repo_model.RepoUnit)); err != nil {
+2 -1
services/wiki/wiki.go
··· 21 21 repo_module "code.gitea.io/gitea/modules/repository" 22 22 "code.gitea.io/gitea/modules/sync" 23 23 asymkey_service "code.gitea.io/gitea/services/asymkey" 24 + repo_service "code.gitea.io/gitea/services/repository" 24 25 ) 25 26 26 27 // TODO: use clustered lock (unique queue? or *abuse* cache) ··· 399 400 400 401 // DeleteWiki removes the actual and local copy of repository wiki. 401 402 func DeleteWiki(ctx context.Context, repo *repo_model.Repository) error { 402 - if err := repo_model.UpdateRepositoryUnits(ctx, repo, nil, []unit.Type{unit.TypeWiki}); err != nil { 403 + if err := repo_service.UpdateRepositoryUnits(ctx, repo, nil, []unit.Type{unit.TypeWiki}); err != nil { 403 404 return err 404 405 } 405 406
+15
services/wiki/wiki_path.go
··· 9 9 "strings" 10 10 11 11 repo_model "code.gitea.io/gitea/models/repo" 12 + "code.gitea.io/gitea/modules/git" 13 + api "code.gitea.io/gitea/modules/structs" 12 14 "code.gitea.io/gitea/modules/util" 15 + "code.gitea.io/gitea/services/convert" 13 16 ) 14 17 15 18 // To define the wiki related concepts: ··· 155 158 } 156 159 return WebPath(title) 157 160 } 161 + 162 + // ToWikiPageMetaData converts meta information to a WikiPageMetaData 163 + func ToWikiPageMetaData(wikiName WebPath, lastCommit *git.Commit, repo *repo_model.Repository) *api.WikiPageMetaData { 164 + subURL := string(wikiName) 165 + _, title := WebPathToUserTitle(wikiName) 166 + return &api.WikiPageMetaData{ 167 + Title: title, 168 + HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", subURL), 169 + SubURL: subURL, 170 + LastCommit: convert.ToWikiCommit(lastCommit), 171 + } 172 + }
+1 -1
tests/integration/integration_test.go
··· 635 635 } 636 636 } 637 637 638 - err := repo_model.UpdateRepositoryUnits(db.DefaultContext, repo, units, disabledUnits) 638 + err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, units, disabledUnits) 639 639 assert.NoError(t, err) 640 640 } 641 641