Skip to content

Commit 8ac64cc

Browse files
committed
internal/task: reuse or create release milestone and issue
If there are open release milestone and release issue in golang/vscode-go, the flow will reuse them. A local relui screenshot is at golang/vscode-go#3500 (comment) For golang/vscode-go#3500 Change-Id: I7ba69a670bd66618bdb294761901af0fb7fd0dd1 Reviewed-on: https://go-review.googlesource.com/c/build/+/608417 Reviewed-by: Hyang-Ah Hana Kim <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 3a2d61c commit 8ac64cc

File tree

5 files changed

+155
-2
lines changed

5 files changed

+155
-2
lines changed

cmd/relui/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ func main() {
308308
dh.RegisterDefinition("Update x/crypto NSS root bundle", bundleTasks.NewDefinition())
309309

310310
releaseVSCodeGoTasks := task.ReleaseVSCodeGoTasks{
311+
GitHub: &task.GitHubClient{
312+
V3: github.NewClient(githubHTTPClient),
313+
V4: githubv4.NewClient(githubHTTPClient),
314+
},
311315
Gerrit: gerritClient,
312316
ApproveAction: relui.ApproveActionDep(dbPool),
313317
}

internal/task/fakes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,9 @@ func (f *FakeGitHub) FetchMilestone(_ context.Context, owner, repo, name string,
915915

916916
if create {
917917
newID := f.nextMilestoneID()
918+
if f.Milestones == nil {
919+
f.Milestones = map[int]string{}
920+
}
918921
f.Milestones[newID] = name
919922
return newID, nil
920923
}

internal/task/releasevscodego.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
package task
66

77
import (
8+
_ "embed"
89
"fmt"
910

11+
"github.com/google/go-github/v48/github"
1012
"golang.org/x/build/internal/relui/groups"
1113
"golang.org/x/build/internal/workflow"
1214
wf "golang.org/x/build/internal/workflow"
@@ -43,6 +45,7 @@ import (
4345
// insider versions.
4446
type ReleaseVSCodeGoTasks struct {
4547
Gerrit GerritClient
48+
GitHub GitHubClientInterface
4649
ApproveAction func(*wf.TaskContext) error
4750
}
4851

@@ -57,18 +60,62 @@ var nextVersionParam = wf.ParamDef[string]{
5760
},
5861
}
5962

63+
//go:embed template/vscode-go-release-issue.md
64+
var vscodeGOReleaseIssueTmplStr string
65+
6066
// NewPrereleaseDefinition create a new workflow definition for vscode-go pre-release.
6167
func (r *ReleaseVSCodeGoTasks) NewPrereleaseDefinition() *wf.Definition {
6268
wd := wf.New(wf.ACL{Groups: []string{groups.ToolsTeam}})
6369

6470
versionBumpStrategy := wf.Param(wd, nextVersionParam)
6571

66-
version := wf.Task1(wd, "find the next pre-release version", r.nextPrereleaseVersion, versionBumpStrategy)
67-
_ = wf.Action1(wd, "await release coordinator's approval", r.approveVersion, version)
72+
semv := wf.Task1(wd, "find the next pre-release version", r.nextPrereleaseVersion, versionBumpStrategy)
73+
approved := wf.Action1(wd, "await release coordinator's approval", r.approveVersion, semv)
74+
75+
_ = wf.Task1(wd, "create release milestone and issue", r.createReleaseMilestoneAndIssue, semv, wf.After(approved))
6876

6977
return wd
7078
}
7179

80+
func (r *ReleaseVSCodeGoTasks) createReleaseMilestoneAndIssue(ctx *wf.TaskContext, semv semversion) (int, error) {
81+
version := fmt.Sprintf("v%v.%v.%v", semv.Major, semv.Minor, semv.Patch)
82+
83+
// The vscode-go release milestone name matches the release version.
84+
milestoneID, err := r.GitHub.FetchMilestone(ctx, "golang", "vscode-go", version, true)
85+
if err != nil {
86+
return 0, err
87+
}
88+
89+
title := fmt.Sprintf("Release %s", version)
90+
issues, err := r.GitHub.FetchMilestoneIssues(ctx, "golang", "vscode-go", milestoneID)
91+
if err != nil {
92+
return 0, err
93+
}
94+
for id := range issues {
95+
issue, _, err := r.GitHub.GetIssue(ctx, "golang", "vscode-go", id)
96+
if err != nil {
97+
return 0, err
98+
}
99+
if title == issue.GetTitle() {
100+
ctx.Printf("found existing releasing issue %v", id)
101+
return id, nil
102+
}
103+
}
104+
105+
content := fmt.Sprintf(vscodeGOReleaseIssueTmplStr, version)
106+
issue, _, err := r.GitHub.CreateIssue(ctx, "golang", "vscode-go", &github.IssueRequest{
107+
Title: &title,
108+
Body: &content,
109+
Assignee: github.String("h9jiang"),
110+
Milestone: &milestoneID,
111+
})
112+
if err != nil {
113+
return 0, fmt.Errorf("failed to create release tracking issue for %q: %w", version, err)
114+
}
115+
ctx.Printf("created releasing issue %v", *issue.Number)
116+
return *issue.Number, nil
117+
}
118+
72119
// nextPrereleaseVersion determines the next pre-release version for the
73120
// upcoming stable release of vscode-go by examining all existing tags in the
74121
// repository.

internal/task/releasevscodego_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,77 @@ import (
88
"context"
99
"testing"
1010

11+
"github.com/google/go-github/v48/github"
1112
"golang.org/x/build/internal/workflow"
1213
)
1314

15+
func TestCreateReleaseMilestoneAndIssue(t *testing.T) {
16+
testcases := []struct {
17+
name string
18+
version string
19+
fakeGithub FakeGitHub
20+
wantIssue int
21+
wantMilestone int
22+
}{
23+
{
24+
name: "flow should create a milestone and create an issue under the milestone",
25+
version: "v0.45.0-rc.1",
26+
fakeGithub: FakeGitHub{}, // no issues and no milestones.
27+
wantIssue: 1,
28+
wantMilestone: 1,
29+
},
30+
{
31+
name: "flow should create an issue under the existing milestone",
32+
version: "v0.48.0-rc.1",
33+
fakeGithub: FakeGitHub{
34+
Milestones: map[int]string{999: "v0.48.0", 998: "v0.46.0"},
35+
},
36+
wantIssue: 1,
37+
wantMilestone: 999,
38+
},
39+
{
40+
name: "flow should reuse the existing release issue",
41+
version: "v0.48.0-rc.1",
42+
fakeGithub: FakeGitHub{
43+
Milestones: map[int]string{999: "v0.48.0", 998: "Release v0.46.0"},
44+
Issues: map[int]*github.Issue{1000: {Number: github.Int(1000), Title: github.String("Release v0.48.0"), Milestone: &github.Milestone{ID: github.Int64(999)}}},
45+
},
46+
wantIssue: 1000,
47+
wantMilestone: 999,
48+
},
49+
}
50+
51+
for _, tc := range testcases {
52+
t.Run(tc.name, func(t *testing.T) {
53+
tasks := &ReleaseVSCodeGoTasks{
54+
GitHub: &tc.fakeGithub,
55+
}
56+
57+
semv, ok := parseSemver(tc.version)
58+
if !ok {
59+
t.Fatalf("parseSemver(%q) should success", tc.version)
60+
}
61+
issueNumber, err := tasks.createReleaseMilestoneAndIssue(&workflow.TaskContext{Context: context.Background(), Logger: &testLogger{t, ""}}, semv)
62+
if err != nil {
63+
t.Fatal(err)
64+
}
65+
66+
issue, ok := tc.fakeGithub.Issues[issueNumber]
67+
if !ok {
68+
t.Errorf("release issue with number %v does not exist", issueNumber)
69+
}
70+
71+
if *issue.Number != tc.wantIssue {
72+
t.Errorf("createReleaseMilestoneAndIssue() create an issue with number %v, but should create issue with number %v", issue.Number, tc.wantIssue)
73+
}
74+
75+
if int(*issue.Milestone.ID) != tc.wantMilestone {
76+
t.Errorf("release issue is created under milestone %v should under milestone %v", *issue.Milestone.ID, tc.wantMilestone)
77+
}
78+
})
79+
}
80+
}
81+
1482
func TestNextPrereleaseVersion(t *testing.T) {
1583
tests := []struct {
1684
name string
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Release candidate (TODO: DATE)
2+
- [x] Announce the release, leave enough time for teams to surface any last minute issues that need to get in before freeze. Make sure debugger and gopls teams are looped in as well.
3+
- [ ] Check [the milestone](https://github.com/golang/vscode-go/issues?q=milestone%%3A%[1]s) and resolve/move unresolved issues.
4+
- [ ] Update master for the release
5+
- [ ] Update hardcoded latest version for gopls.
6+
- [ ] Update [CHANGELOG.md](https://github.com/golang/vscode-go/blob/master/extension/CHANGELOG.md).
7+
- [ ] Make sure the "Thanks" section is up-to-date.
8+
- [ ] Check the Markdown rendering to make sure everything looks good.
9+
- [ ] Update release for the release
10+
- [ ] Create a branch against release for a pull request.
11+
- [ ] Merge changes from master to prepare for the release.
12+
- [ ] Change the version in [package.json](https://github.com/golang/vscode-go/blob/master/extension/package.json) from a -dev suffix
13+
- [ ] Run npm install to make sure [package-lock.json](https://github.com/golang/vscode-go/blob/master/extension/package.json) is up-to-date
14+
- [ ] Update the license file ($ tools/license.sh; mv LICENSE.prod LICENSE)
15+
- [ ] Check the [Long Tests status](https://github.com/golang/vscode-go/actions?query=workflow%%3A%%22Long+Tests%%22) is green. Otherwise, fix the tests, send cls for review, submit them, and repeat.
16+
- [ ] Perform manual [smoke tests](https://github.com/golang/vscode-go/blob/master/docs/smoke-test.md)
17+
- [ ] Create new RC version tag for %[1]s-rc.1 at gerrit’s vscode-go [repo management page](https://go-review.googlesource.com/admin/repos/vscode-go,tags)
18+
- [ ] Go to the release page https://github.com/golang/vscode-go/releases and check if the new release candidate is up. If necessary, you can manually edit the comment by clicking the “Edit” button. Don’t mutate uploaded vsix.
19+
- [ ] Ask @golang/tools-team and contributors to this release to test the release candidate
20+
21+
# Final (TODO: DATE)
22+
- [ ] Tag the new release for %[1]s
23+
- [ ] Monitor the [cloud build status](https://pantheon.corp.google.com/cloud-build/dashboard?project=go-vscode-go)
24+
- [ ] Update the release description with CHANGELOG contents
25+
- [ ] Close the milestone
26+
27+
# Prepare for the Next Release
28+
- [ ] Update master post-release
29+
- [ ] Bump the version number to the next monthly release in the master branch
30+
- [ ] Update package.json
31+
- [ ] Update package-lock.json

0 commit comments

Comments
 (0)