Files
jmiller bab29a83fa refactor: rename Go module path MokoConsulting/MokoGitea -> MokoConsulting/MokoGIT
Sweep all .go imports + go.mod, plus module-path refs in .golangci.yml,
Dockerfile, swagger templates, locale example, and repo/wiki URLs
(MokoGitea-Fork -> MokoGIT). Part of the MokoGIT rebrand.

Claude-Session: https://claude.ai/code/session_01Bqe7fAuHQeiLueYfeHFrHw
2026-07-14 15:31:19 -05:00

104 lines
3.3 KiB
Go

// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later
package cascade
import (
"context"
"fmt"
issues_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/issues"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/log"
notify_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/notify"
pull_service "code.mokoconsulting.tech/MokoConsulting/MokoGIT/services/pull"
)
func Init() {
notify_service.RegisterNotifier(&cascadeNotifier{})
}
type cascadeNotifier struct {
notify_service.NullNotifier
}
func (n *cascadeNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
handleCascade(ctx, doer, pr)
}
func (n *cascadeNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
handleCascade(ctx, doer, pr)
}
func handleCascade(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
if err := pr.LoadBaseRepo(ctx); err != nil {
log.Error("cascade: LoadBaseRepo for PR #%d: %v", pr.Index, err)
return
}
rules, err := repo_model.GetCascadeRulesForBranch(ctx, pr.BaseRepo.ID, pr.BaseBranch)
if err != nil {
log.Error("cascade: GetCascadeRulesForBranch repo=%d branch=%s: %v", pr.BaseRepo.ID, pr.BaseBranch, err)
return
}
for _, rule := range rules {
if err := createCascadePR(ctx, doer, pr, rule); err != nil {
log.Error("cascade: failed to create PR %s→%s in repo %d: %v", rule.SourceBranch, rule.TargetBranch, rule.RepoID, err)
}
}
}
func createCascadePR(ctx context.Context, doer *user_model.User, mergedPR *issues_model.PullRequest, rule *repo_model.CascadeMergeRule) error {
repo := mergedPR.BaseRepo
existingPRs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repo.ID, rule.TargetBranch)
if err != nil {
return fmt.Errorf("check existing PRs: %w", err)
}
for _, existing := range existingPRs {
if existing.HeadBranch == rule.SourceBranch && existing.HeadRepoID == repo.ID {
log.Info("cascade: PR already exists %s→%s in %s/%s (#%d), skipping",
rule.SourceBranch, rule.TargetBranch, repo.OwnerName, repo.Name, existing.Index)
return nil
}
}
title := fmt.Sprintf("cascade: merge %s into %s", rule.SourceBranch, rule.TargetBranch)
body := fmt.Sprintf("Auto-created by cascade merge rule after PR #%d was merged.\n\nSource: `%s` → Target: `%s`",
mergedPR.Index, rule.SourceBranch, rule.TargetBranch)
issue := &issues_model.Issue{
RepoID: repo.ID,
Repo: repo,
Title: title,
Content: body,
PosterID: doer.ID,
Poster: doer,
IsPull: true,
}
pullRequest := &issues_model.PullRequest{
HeadRepoID: repo.ID,
BaseRepoID: repo.ID,
HeadBranch: rule.SourceBranch,
BaseBranch: rule.TargetBranch,
HeadRepo: repo,
BaseRepo: repo,
Type: issues_model.PullRequestGitea,
}
if err := pull_service.NewPullRequest(ctx, &pull_service.NewPullRequestOptions{
Repo: repo,
Issue: issue,
PullRequest: pullRequest,
}); err != nil {
return fmt.Errorf("NewPullRequest: %w", err)
}
log.Info("cascade: created PR #%d (%s→%s) in %s/%s",
issue.Index, rule.SourceBranch, rule.TargetBranch, repo.OwnerName, repo.Name)
return nil
}