Skip to content

Commit

Permalink
internal/task: fetch the release issue in gopls release process
Browse files Browse the repository at this point in the history
The release issue will be referenced by all CLs generated by the gopls
release process.

For golang/go#57643

Change-Id: Icc44aeab84a7a1fc3c624267cb398729371db068
Reviewed-on: https://go-review.googlesource.com/c/build/+/610236
Auto-Submit: Hongxiang Jiang <hxjiang@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
  • Loading branch information
h9jiang authored and gopherbot committed Sep 3, 2024
1 parent 0988d2a commit 36db46e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
25 changes: 16 additions & 9 deletions internal/task/releasegopls.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (r *ReleaseGoplsTasks) NewPrereleaseDefinition() *wf.Definition {
prerelease := wf.Task1(wd, "find the pre-release version", r.nextPrereleaseVersion, semv)
approved := wf.Action2(wd, "wait for release coordinator approval", r.approveVersion, semv, prerelease)

issue := wf.Task1(wd, "create release git issue", r.createReleaseIssue, semv, wf.After(approved))
issue := wf.Task2(wd, "create release git issue", r.findOrCreateGitHubIssue, semv, wf.Const(true), wf.After(approved))
branchCreated := wf.Action1(wd, "create new branch if minor release", r.createBranchIfMinor, semv, wf.After(issue))

configChangeID := wf.Task3(wd, "update branch's codereview.cfg", r.updateCodeReviewConfig, semv, reviewers, issue, wf.After(branchCreated))
Expand Down Expand Up @@ -126,12 +126,13 @@ func (r *ReleaseGoplsTasks) approveVersion(ctx *wf.TaskContext, semv semversion,
return r.ApproveAction(ctx)
}

// createReleaseIssue attempts to locate the release issue associated with the
// given milestone. If no such issue exists, a new one is created.
// findOrCreateGitHubIssue locates or creates the release issue for the given
// release milestone.
//
// Returns the ID of the release issue (either newly created or pre-existing).
// Returns error if the release milestone does not exist or is closed.
func (r *ReleaseGoplsTasks) createReleaseIssue(ctx *wf.TaskContext, semv semversion) (int64, error) {
// If the release issue exists, return the issue ID.
// If 'create' is true and no issue exists, a new one is created.
// If 'create' is false and no issue exists, an error is returned.
func (r *ReleaseGoplsTasks) findOrCreateGitHubIssue(ctx *wf.TaskContext, semv semversion, create bool) (int64, error) {
versionString := fmt.Sprintf("v%v.%v.%v", semv.Major, semv.Minor, semv.Patch)
milestoneName := fmt.Sprintf("gopls/%s", versionString)
// All milestones and issues resides under go repo.
Expand All @@ -157,6 +158,11 @@ func (r *ReleaseGoplsTasks) createReleaseIssue(ctx *wf.TaskContext, semv semvers
}
}

if !create {
return 0, fmt.Errorf("could not find any release issue for %s", versionString)
}

ctx.DisableRetries()
content := fmt.Sprintf(`This issue tracks progress toward releasing gopls@%s
- [ ] create or update %s
Expand Down Expand Up @@ -635,7 +641,8 @@ func (r *ReleaseGoplsTasks) NewReleaseDefinition() *wf.Definition {
semv := wf.Task1(wd, "validating input version", r.isValidPrereleaseVersion, version)
tagged := wf.Action1(wd, "tag the release", r.tagRelease, semv)

changeID := wf.Task2(wd, "updating x/tools dependency in master branch in gopls sub dir", r.updateDependencyIfMinor, reviewers, semv, wf.After(tagged))
issue := wf.Task2(wd, "find release git issue", r.findOrCreateGitHubIssue, semv, wf.Const(false))
changeID := wf.Task3(wd, "updating x/tools dependency in master branch in gopls sub dir", r.updateDependencyIfMinor, reviewers, semv, issue, wf.After(tagged))
_ = wf.Task1(wd, "await x/tools gopls dependency CL submission in gopls sub dir", clAwaiter{r.Gerrit}.awaitSubmission, changeID)

return wd
Expand Down Expand Up @@ -739,7 +746,7 @@ func (r *ReleaseGoplsTasks) tagRelease(ctx *wf.TaskContext, semv semversion) err
// branch.
//
// Returns the change ID.
func (r *ReleaseGoplsTasks) updateDependencyIfMinor(ctx *wf.TaskContext, reviewers []string, semv semversion) (string, error) {
func (r *ReleaseGoplsTasks) updateDependencyIfMinor(ctx *wf.TaskContext, reviewers []string, semv semversion, issue int64) (string, error) {
if semv.Patch != 0 {
return "", nil
}
Expand Down Expand Up @@ -774,7 +781,7 @@ go mod tidy -compat=1.19
changeInput := gerrit.ChangeInput{
Project: "tools",
Branch: "master",
Subject: fmt.Sprintf("%s\n\nThis is an automated CL which updates the go.mod and go.sum.", clTitle),
Subject: fmt.Sprintf("%s\n\nThis is an automated CL which updates the go.mod and go.sum.\n\nFor golang/go#%v", clTitle, issue),
}

ctx.Printf("creating auto-submit change under master branch in x/tools repo.")
Expand Down
34 changes: 30 additions & 4 deletions internal/task/releasegopls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,42 +434,68 @@ func TestNextPrerelease(t *testing.T) {
}
}

func TestCreateReleaseIssue(t *testing.T) {
func TestFindOrCreateReleaseIssue(t *testing.T) {
ctx := context.Background()
testcases := []struct {
name string
version string
create bool
fakeGithub FakeGitHub
wantErr bool
wantIssue int64
}{
{
name: "milestone does not exist",
version: "v0.16.2",
create: true,
wantErr: true,
wantIssue: 0,
},
{
name: "irrelevant milestone exist",
version: "v0.16.2",
create: true,
fakeGithub: FakeGitHub{
Milestones: map[int]string{1: "gopls/v0.16.1"},
},
wantErr: true,
wantIssue: 0,
},
{
name: "milestone exist, issue is missing, workflow should create this issue",
name: "milestone exist, issue is missing, create true, workflow should create this issue",
version: "v0.16.2",
create: true,
fakeGithub: FakeGitHub{
Milestones: map[int]string{1: "gopls/v0.16.2"},
},
wantErr: false,
wantIssue: 1,
},
{
name: "milestone exist, issue exist, workflow should reuse the issue",
name: "milestone exist, issue is missing, create false, workflow error out",
version: "v0.16.2",
create: false,
fakeGithub: FakeGitHub{
Milestones: map[int]string{1: "gopls/v0.16.2"},
},
wantErr: true,
wantIssue: 0,
},
{
name: "milestone exist, issue exist, create true, workflow should reuse the issue",
version: "v0.16.2",
create: true,
fakeGithub: FakeGitHub{
Milestones: map[int]string{1: "gopls/v0.16.2"},
Issues: map[int]*github.Issue{2: {Number: github.Int(2), Title: github.String("x/tools/gopls: release version v0.16.2"), Milestone: &github.Milestone{ID: github.Int64(1)}}},
},
wantErr: false,
wantIssue: 2,
},
{
name: "milestone exist, issue exist, create false, workflow should reuse the issue",
version: "v0.16.2",
create: false,
fakeGithub: FakeGitHub{
Milestones: map[int]string{1: "gopls/v0.16.2"},
Issues: map[int]*github.Issue{2: {Number: github.Int(2), Title: github.String("x/tools/gopls: release version v0.16.2"), Milestone: &github.Milestone{ID: github.Int64(1)}}},
Expand All @@ -489,7 +515,7 @@ func TestCreateReleaseIssue(t *testing.T) {
if !ok {
t.Fatalf("parseSemver(%q) should success", tc.version)
}
gotIssue, err := tasks.createReleaseIssue(&workflow.TaskContext{Context: ctx, Logger: &testLogger{t, ""}}, semv)
gotIssue, err := tasks.findOrCreateGitHubIssue(&workflow.TaskContext{Context: ctx, Logger: &testLogger{t, ""}}, semv, tc.create)

if tc.wantErr && err == nil {
t.Errorf("createReleaseIssue(%s) should return error but return nil", tc.version)
Expand Down

0 comments on commit 36db46e

Please sign in to comment.