github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/scripts/internal/workflow-controllers/pr.go (about) 1 package wc 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "strings" 8 9 "github.com/ActiveState/cli/internal/errs" 10 wh "github.com/ActiveState/cli/scripts/internal/workflow-helpers" 11 "github.com/andygrunwald/go-jira" 12 "github.com/blang/semver" 13 "github.com/google/go-github/v45/github" 14 "golang.org/x/net/context" 15 ) 16 17 type Meta interface { 18 GetVersion() semver.Version 19 GetJiraVersion() string 20 GetVersionBranchName() string 21 GetVersionPRName() string 22 } 23 24 func DetectBaseRef(ghClient *github.Client, jiraClient *jira.Client, meta Meta) (string, error) { 25 if meta.GetVersion().EQ(wh.VersionMaster) { 26 return wh.MasterBranch, nil 27 } 28 29 // Check if master is safe to fork from 30 finish := PrintStart("Checking if master is safe to fork from for version %s", meta.GetVersion()) 31 var ref *string 32 versionsGT, err := wh.BranchHasVersionsGT(ghClient, jiraClient, wh.MasterBranch, meta.GetVersion()) 33 if err != nil { 34 return "", errs.Wrap(err, "failed to check if can fork master") 35 } 36 37 // Calculate SHA for master 38 if !versionsGT { 39 Print("Master is safe") 40 finish2 := PrintStart("Getting master HEAD SHA") 41 branch, _, err := ghClient.Repositories.GetBranch(context.Background(), "ActiveState", "cli", wh.MasterBranch, false) 42 if err != nil { 43 return "", errs.Wrap(err, "failed to get branch info") 44 } 45 ref = branch.GetCommit().SHA 46 Print("Master SHA: " + *ref) 47 finish2() 48 } else { 49 Print("Master is unsafe as it has versions greater than %s", meta.GetVersion()) 50 } 51 finish() 52 53 // Master is unsafe, detect closest matching PR instead 54 if ref == nil { 55 finish = PrintStart("Finding nearest matching version PR to fork from") 56 prevVersionPR, err := wh.FetchVersionPR(ghClient, wh.AssertLT, meta.GetVersion()) 57 if err != nil { 58 return "", errs.Wrap(err, 59 "Failed to find fork branch, please manually create the Version PR "+ 60 "for '%s' by running the create-version-pr script.", 61 meta.GetVersion()) 62 } 63 64 ref = prevVersionPR.Head.SHA 65 Print("Nearest matching PR: %s (%d), branch: %s, SHA: %s", 66 prevVersionPR.GetTitle(), prevVersionPR.GetNumber(), prevVersionPR.Head.GetRef(), *ref) 67 finish() 68 } 69 70 return *ref, nil 71 } 72 73 func CreateVersionPR(ghClient *github.Client, jiraClient *jira.Client, meta Meta) error { 74 finish := PrintStart("Detecting base ref to fork from") 75 prevVersionRef, err := DetectBaseRef(ghClient, jiraClient, meta) 76 if err != nil { 77 return errs.Wrap(err, "failed to detect base ref") 78 } 79 finish() 80 81 // Create branch 82 finish = PrintStart("Creating version branch, name: %s, forked from: %s", meta.GetVersionBranchName(), prevVersionRef) 83 dryRun := os.Getenv("DRYRUN") == "true" 84 if !dryRun { 85 if err := wh.CreateBranch(ghClient, meta.GetVersionBranchName(), prevVersionRef); err != nil { 86 if !strings.Contains(err.Error(), "Reference already exists") { 87 return errs.Wrap(err, "failed to create branch") 88 } 89 Print("Branch already exists, continuing") 90 } 91 } else { 92 Print("DRYRUN: skip") 93 } 94 finish() 95 96 // Create commit with version.txt change 97 finish = PrintStart("Creating commit with version.txt change") 98 parentSha, err := wh.CreateFileUpdateCommit(ghClient, meta.GetVersionBranchName(), "version.txt", meta.GetVersion().String(), wh.UpdateVersionCommitMessage) 99 if err != nil { 100 return errs.Wrap(err, "failed to create commit") 101 } 102 Print("Created commit SHA: %s", parentSha) 103 finish() 104 105 // Prepare PR Body 106 body := fmt.Sprintf(`[View %s tickets on Jira](%s)`, 107 meta.GetVersion(), 108 "https://activestatef.atlassian.net/jira/software/c/projects/DX/issues/?jql="+ 109 url.QueryEscape(fmt.Sprintf(`project = "DX" AND fixVersion=%s ORDER BY created DESC`, meta.GetJiraVersion())), 110 ) 111 112 // Create PR 113 finish = PrintStart("Creating version PR, name: %s", meta.GetVersionPRName()) 114 if !dryRun { 115 versionPR, err := wh.CreatePR(ghClient, meta.GetVersionPRName(), meta.GetVersionBranchName(), wh.StagingBranch, body) 116 if err != nil { 117 return errs.Wrap(err, "failed to create target PR") 118 } 119 120 if err := wh.LabelPR(ghClient, versionPR.GetNumber(), []string{"Test: all"}); err != nil { 121 return errs.Wrap(err, "failed to label PR") 122 } 123 } else { 124 fmt.Printf("DRYRUN: would create PR with body:\n%s\n", body) 125 } 126 finish() 127 128 return nil 129 }