From 464e807747f1d5067811be95e13ca0ab2f67552f4a75f963128e9f0c31bac1b9 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Fri, 27 Sep 2024 17:58:09 +0200 Subject: [PATCH] pr: WIP --- workflow-pr/example.json | 19 +++++++ workflow-pr/main.go | 106 +++++++++++++++++++++++++++++++++++---- 2 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 workflow-pr/example.json diff --git a/workflow-pr/example.json b/workflow-pr/example.json new file mode 100644 index 0000000..2b53e75 --- /dev/null +++ b/workflow-pr/example.json @@ -0,0 +1,19 @@ +[ + { + "Workflows": ["direct"], + "Organization": "autogits", + "GitProjectName": "MyPrj" + }, + { + "Workflows": ["direct"], + "Organization": "autogits", + "GitProjectName": "HiddenPrj", + "Branch": "hidden" + }, + { + "Workflows": ["pr", "direct"], + "Organization": "importtest", + "Branch": "factory" + } +] + diff --git a/workflow-pr/main.go b/workflow-pr/main.go index 18e86f7..60d7f80 100644 --- a/workflow-pr/main.go +++ b/workflow-pr/main.go @@ -22,14 +22,17 @@ import ( "flag" "fmt" "log" + "math/rand" "path" "slices" + "strings" "time" "src.opensuse.org/autogits/common" ) const ( + AppName = "pr_workflow" GitAuthor = "AutoGits - pr-review" GitEmail = "adam+autogits-pr@zombino.com" PrReview = "pr-review" @@ -55,7 +58,12 @@ func fetchPrGit(h *common.RequestHandler, pr *models.PullRequest) error { }*/ func processPullRequestClosed(req *common.PullRequestWebhookEvent, git *common.GitHandler, config *common.AutogitConfig) error { - // this needs to be moved to pull merger + if req.Repository.Name != config.GitProjectName { + return nil + } + + log.Println("request was:", req.Pull_Request.State) + return nil /* req := h.Data.(*common.PullRequestAction) @@ -108,9 +116,8 @@ func processPullRequestSync(req *common.PullRequestWebhookEvent, git *common.Git log.Println("associated pr:", prjPr) - prjgit := config.GitProjectName - common.PanicOnError(git.GitExec("", "clone", "--branch", prjPr.Head.Name, "--depth", "1", prjPr.Head.Repo.SSHURL, prjgit)) - commitId, ok := git.GitSubmoduleCommitId(prjgit, req.Repository.Name, prjPr.Head.Sha) + common.PanicOnError(git.GitExec("", "clone", "--branch", prjPr.Head.Name, "--depth", "1", prjPr.Head.Repo.SSHURL, common.DefaultGitPrj)) + commitId, ok := git.GitSubmoduleCommitId(common.DefaultGitPrj, req.Repository.Name, prjPr.Head.Sha) if !ok { return fmt.Errorf("Cannot fetch submodule commit id in prjgit for '%s'", req.Repository.Name) @@ -156,11 +163,11 @@ PullRequest: %s/%s#%d`, req.Repository.Owner.Username, return err } - common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGit.SSHURL, config.GitProjectName)) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "checkout", "-B", branchName, config.GitProjectName)) + common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGit.SSHURL, common.DefaultGitPrj)) + common.PanicOnError(git.GitExec(common.DefaultGitPrj, "checkout", "-B", branchName, prjGit.DefaultBranch)) common.PanicOnError(updateOrCreatePRBranch(req, git, commitMsg, branchName)) - PR, err := gitea.CreatePullRequest(prjGit, branchName, prjGit.DefaultBranch, + PR, err := gitea.CreatePullRequestIfNotExist(prjGit, branchName, prjGit.DefaultBranch, fmt.Sprintf("Forwarded PR: %s", req.Repository.Name), fmt.Sprintf(`This is a forwarded pull request by %s referencing the following pull request: @@ -192,11 +199,16 @@ func processPullRequest(request *common.Request) error { var config *common.AutogitConfig for _, c := range configs { - if c.Branch == req.Pull_Request.Base.Ref { + if c.GitProjectName == req.Pull_Request.Base.Repo.Name || + c.Branch == req.Pull_Request.Base.Ref { + config = c break } } + if config == nil { + return fmt.Errorf("Cannot find config for branch '%s'", req.Pull_Request.Base.Ref) + } git, err := common.CreateGitHandler(GitAuthor, GitEmail, PrReview) if err != nil { @@ -222,8 +234,84 @@ var DebugMode bool var checkOnStart bool var checkInterval time.Duration +func verifyProjectState(git *common.GitHandler, orgName string, config *common.AutogitConfig, configs []*common.AutogitConfig) error { + org := common.Organization{ + Username: orgName, + } + repo, err := gitea.CreateRepositoryIfNotExist(git, org, config.GitProjectName) + if err != nil { + return fmt.Errorf("Error fetching or creating '%s/%s' -- aborting verifyProjectState(). Err: %w", orgName, config.GitProjectName, err) + } + + common.PanicOnError(git.GitExec("", "clone", "--depth", "1", repo.SSHURL, config.GitProjectName)) + log.Println("getting submodule list") + submodules, err := git.GitSubmoduleList(config.GitProjectName, "HEAD") + +nextSubmodule: + for sub, commitID := range submodules { + submoduleName := sub + if n := strings.LastIndex(sub, "/"); n != -1 { + submoduleName = sub[n+1:] + } + commits, err := gitea.GetRecentCommits(config.Organization, submoduleName, config.Branch, 10) + if err != nil { + return fmt.Errorf("Error fetching recent commits for %s/%s. Err: %w", config.Organization, submoduleName, err) + } + + for idx, commit := range commits { + if commit.SHA == commitID { + if idx != 0 { + // commit in past ... + log.Println(" W -", submoduleName, " is behind the branch by", idx, "This should not happen in PR workflow alone") + } + continue nextSubmodule + } + } + + // not found in past, check if we should advance the branch label ... pull the submodule + } + + // forward any package-gits referred by the project git, but don't go back + return nil +} + +func checkRepos() { + for org, configs := range configuredRepos { + for _, config := range configs { + if checkInterval > 0 { + sleepInterval := checkInterval - checkInterval/2 + time.Duration(rand.Int63n(int64(checkInterval))) + log.Println(" - sleep interval", sleepInterval, "until next check") + time.Sleep(sleepInterval) + } + + log.Printf(" ++ starting verification, org: `%s` config: `%s`\n", org, config.GitProjectName) + git, err := common.CreateGitHandler(GitAuthor, GitEmail, AppName) + if err != nil { + log.Println("Faield to allocate GitHandler:", err) + return + } + defer git.Close() + if err := verifyProjectState(git, org, config, configs); err != nil { + log.Printf(" *** verification failed, org: `%s`, err: %#v\n", org, err) + } + log.Printf(" ++ verification complete, org: `%s` config: `%s`\n", org, config.GitProjectName) + } + } +} + func consistencyCheckProcess() { - // TODO -- add self-healing options + if checkOnStart { + savedCheckInterval := checkInterval + checkInterval = 0 + log.Println("== Startup consistency check begin...") + checkRepos() + log.Println("== Startup consistency check done...") + checkInterval = savedCheckInterval + } + + for { + checkRepos() + } } func main() {