func (tool *codeReviewTool) FinaliseRelease(v *version.Version) (action.Action, error) { // Get a GitHub client. config, err := LoadConfig() if err != nil { return nil, err } client := ghutil.NewClient(config.Token()) owner, repo, err := git.ParseUpstreamURL() if err != nil { return nil, err } // Get the relevant review milestone. releaseString := v.BaseString() task := fmt.Sprintf("Get GitHub review milestone for release %v", releaseString) log.Run(task) milestone, err := milestoneForVersion(config, owner, repo, v) if err != nil { return nil, errs.NewError(task, err) } if milestone == nil { log.Warn(fmt.Sprintf( "Weird, GitHub review milestone for release %v not found", releaseString)) return nil, nil } // Close the milestone unless there are some issues open. task = fmt.Sprintf( "Make sure the review milestone for release %v can be closed", releaseString) if num := *milestone.OpenIssues; num != 0 { return nil, errs.NewError( task, fmt.Errorf( "review milestone for release %v cannot be closed: %v issue(s) open", releaseString, num)) } milestoneTask := fmt.Sprintf("Close GitHub review milestone for release %v", releaseString) log.Run(milestoneTask) milestone, _, err = client.Issues.EditMilestone(owner, repo, *milestone.Number, &github.Milestone{ State: github.String("closed"), }) if err != nil { return nil, errs.NewError(milestoneTask, err) } // Return a rollback function. return action.ActionFunc(func() error { log.Rollback(milestoneTask) task := fmt.Sprintf("Reopen GitHub review milestone for release %v", releaseString) _, _, err := client.Issues.EditMilestone(owner, repo, *milestone.Number, &github.Milestone{ State: github.String("open"), }) if err != nil { return errs.NewError(task, err) } return nil }), nil }
func (tool *codeReviewTool) InitialiseRelease(v *version.Version) (action.Action, error) { // Get necessary config. config, err := LoadConfig() if err != nil { return nil, err } owner, repo, err := git.ParseUpstreamURL() if err != nil { return nil, err } // Check whether the review milestone exists or not. // People can create milestones manually, so this makes the thing more robust. task := fmt.Sprintf("Check whether GitHub review milestone exists for release %v", v.BaseString()) log.Run(task) milestone, err := milestoneForVersion(config, owner, repo, v) if err != nil { return nil, errs.NewError(task, err) } if milestone != nil { // Milestone already exists, we are done. log.Log(fmt.Sprintf("GitHub review milestone '%v' already exists", milestoneTitle(v))) return nil, nil } // Create the review milestone. _, act, err := createMilestone(config, owner, repo, v) return act, err }
func (tool *codeReviewTool) PostReviewRequests( ctxs []*common.ReviewContext, opts map[string]interface{}, ) (err error) { // Load the GitHub config. config, err := LoadConfig() if err != nil { return err } // Get the GitHub owner and repository from the upstream URL. owner, repo, err := git.ParseUpstreamURL() if err != nil { return err } // Group commits by story ID. // // In case the commit is associated with a story, we add it to the relevant story group. // Otherwise the commit is marked as unassigned and added to the relevant list. var ( ctxsByStoryId = make(map[string][]*common.ReviewContext, 1) unassignedCommits = make([]*git.Commit, 0, 1) ) for _, ctx := range ctxs { story := ctx.Story if story != nil { sid := story.ReadableId() rcs, ok := ctxsByStoryId[sid] if ok { rcs = append(rcs, ctx) } else { rcs = []*common.ReviewContext{ctx} } ctxsByStoryId[sid] = rcs } else { unassignedCommits = append(unassignedCommits, ctx.Commit) } } // Post the assigned commits. for _, ctxs := range ctxsByStoryId { var ( story = ctxs[0].Story commits = make([]*git.Commit, 0, len(ctxs)) ) for _, ctx := range ctxs { commits = append(commits, ctx.Commit) } if ex := postAssignedReviewRequest(config, owner, repo, story, commits, opts); ex != nil { errs.Log(ex) err = errPostReviewRequest } } // Post the unassigned commits. for _, commit := range unassignedCommits { if ex := postUnassignedReviewRequest(config, owner, repo, commit, opts); ex != nil { errs.Log(ex) err = errPostReviewRequest } } return }
func (rnm *releaseNotesManager) PostReleaseNotes( releaseNotes *common.ReleaseNotes, ) (action.Action, error) { // Get the GitHub owner and repository from the upstream URL. owner, repo, err := git.ParseUpstreamURL() if err != nil { return nil, err } // Instantiate the API client. config, err := github.LoadConfig() if err != nil { return nil, err } client := github.NewClient(config.ApiToken()) // Format the release notes. task := "Format the release notes" body := bytes.NewBufferString(` ## Overview ## **PLEASE FILL IN THE RELEASE OVERVIEW** `) encoder, err := notes.NewEncoder(notes.EncodingMarkdown, body) if err != nil { return nil, errs.NewError(task, err) } if err := encoder.Encode(releaseNotes, nil); err != nil { return nil, errs.NewError(task, err) } bodyString := body.String() // Create GitHub release for the given version. tag := releaseNotes.Version.ReleaseTagString() releaseTask := fmt.Sprintf("Create GitHub release for tag '%v'", tag) log.Run(releaseTask) release, _, err := client.Repositories.CreateRelease(owner, repo, &gh.RepositoryRelease{ TagName: gh.String(tag), Name: gh.String("Release " + releaseNotes.Version.BaseString()), Body: &bodyString, Draft: gh.Bool(true), }) if err != nil { return nil, err } // Delete the GitHub release on rollback. rollback := func() error { log.Rollback(releaseTask) task := fmt.Sprintf("Delete GitHub release for tag '%v'", tag) _, err := client.Repositories.DeleteRelease(owner, repo, *release.ID) if err != nil { return errs.NewError(task, err) } return nil } // Open the release in the browser so that the user can fill in the details. task = "Open the release notes in the browser" if err := webbrowser.Open(*release.HTMLURL); err != nil { if ex := rollback(); ex != nil { errs.Log(ex) } return nil, errs.NewError(task, err) } // Return the rollback function. return action.ActionFunc(rollback), nil }