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 https://github.com/golang/vscode-go/issues/3500#issuecomment-2313190704

For golang/vscode-go#3500

Change-Id: I7ba69a670bd66618bdb294761901af0fb7fd0dd1
Reviewed-on: https://go-review.googlesource.com/c/build/+/608417
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Hongxiang Jiang 2024-08-27 17:03:30 +00:00
Родитель 3a2d61cfab
Коммит 8ac64ccecd
5 изменённых файлов: 155 добавлений и 2 удалений

Просмотреть файл

@ -308,6 +308,10 @@ func main() {
dh.RegisterDefinition("Update x/crypto NSS root bundle", bundleTasks.NewDefinition())
releaseVSCodeGoTasks := task.ReleaseVSCodeGoTasks{
GitHub: &task.GitHubClient{
V3: github.NewClient(githubHTTPClient),
V4: githubv4.NewClient(githubHTTPClient),
},
Gerrit: gerritClient,
ApproveAction: relui.ApproveActionDep(dbPool),
}

Просмотреть файл

@ -915,6 +915,9 @@ func (f *FakeGitHub) FetchMilestone(_ context.Context, owner, repo, name string,
if create {
newID := f.nextMilestoneID()
if f.Milestones == nil {
f.Milestones = map[int]string{}
}
f.Milestones[newID] = name
return newID, nil
}

Просмотреть файл

@ -5,8 +5,10 @@
package task
import (
_ "embed"
"fmt"
"github.com/google/go-github/v48/github"
"golang.org/x/build/internal/relui/groups"
"golang.org/x/build/internal/workflow"
wf "golang.org/x/build/internal/workflow"
@ -43,6 +45,7 @@ import (
// insider versions.
type ReleaseVSCodeGoTasks struct {
Gerrit GerritClient
GitHub GitHubClientInterface
ApproveAction func(*wf.TaskContext) error
}
@ -57,18 +60,62 @@ var nextVersionParam = wf.ParamDef[string]{
},
}
//go:embed template/vscode-go-release-issue.md
var vscodeGOReleaseIssueTmplStr string
// NewPrereleaseDefinition create a new workflow definition for vscode-go pre-release.
func (r *ReleaseVSCodeGoTasks) NewPrereleaseDefinition() *wf.Definition {
wd := wf.New(wf.ACL{Groups: []string{groups.ToolsTeam}})
versionBumpStrategy := wf.Param(wd, nextVersionParam)
version := wf.Task1(wd, "find the next pre-release version", r.nextPrereleaseVersion, versionBumpStrategy)
_ = wf.Action1(wd, "await release coordinator's approval", r.approveVersion, version)
semv := wf.Task1(wd, "find the next pre-release version", r.nextPrereleaseVersion, versionBumpStrategy)
approved := wf.Action1(wd, "await release coordinator's approval", r.approveVersion, semv)
_ = wf.Task1(wd, "create release milestone and issue", r.createReleaseMilestoneAndIssue, semv, wf.After(approved))
return wd
}
func (r *ReleaseVSCodeGoTasks) createReleaseMilestoneAndIssue(ctx *wf.TaskContext, semv semversion) (int, error) {
version := fmt.Sprintf("v%v.%v.%v", semv.Major, semv.Minor, semv.Patch)
// The vscode-go release milestone name matches the release version.
milestoneID, err := r.GitHub.FetchMilestone(ctx, "golang", "vscode-go", version, true)
if err != nil {
return 0, err
}
title := fmt.Sprintf("Release %s", version)
issues, err := r.GitHub.FetchMilestoneIssues(ctx, "golang", "vscode-go", milestoneID)
if err != nil {
return 0, err
}
for id := range issues {
issue, _, err := r.GitHub.GetIssue(ctx, "golang", "vscode-go", id)
if err != nil {
return 0, err
}
if title == issue.GetTitle() {
ctx.Printf("found existing releasing issue %v", id)
return id, nil
}
}
content := fmt.Sprintf(vscodeGOReleaseIssueTmplStr, version)
issue, _, err := r.GitHub.CreateIssue(ctx, "golang", "vscode-go", &github.IssueRequest{
Title: &title,
Body: &content,
Assignee: github.String("h9jiang"),
Milestone: &milestoneID,
})
if err != nil {
return 0, fmt.Errorf("failed to create release tracking issue for %q: %w", version, err)
}
ctx.Printf("created releasing issue %v", *issue.Number)
return *issue.Number, nil
}
// nextPrereleaseVersion determines the next pre-release version for the
// upcoming stable release of vscode-go by examining all existing tags in the
// repository.

Просмотреть файл

@ -8,9 +8,77 @@ import (
"context"
"testing"
"github.com/google/go-github/v48/github"
"golang.org/x/build/internal/workflow"
)
func TestCreateReleaseMilestoneAndIssue(t *testing.T) {
testcases := []struct {
name string
version string
fakeGithub FakeGitHub
wantIssue int
wantMilestone int
}{
{
name: "flow should create a milestone and create an issue under the milestone",
version: "v0.45.0-rc.1",
fakeGithub: FakeGitHub{}, // no issues and no milestones.
wantIssue: 1,
wantMilestone: 1,
},
{
name: "flow should create an issue under the existing milestone",
version: "v0.48.0-rc.1",
fakeGithub: FakeGitHub{
Milestones: map[int]string{999: "v0.48.0", 998: "v0.46.0"},
},
wantIssue: 1,
wantMilestone: 999,
},
{
name: "flow should reuse the existing release issue",
version: "v0.48.0-rc.1",
fakeGithub: FakeGitHub{
Milestones: map[int]string{999: "v0.48.0", 998: "Release v0.46.0"},
Issues: map[int]*github.Issue{1000: {Number: github.Int(1000), Title: github.String("Release v0.48.0"), Milestone: &github.Milestone{ID: github.Int64(999)}}},
},
wantIssue: 1000,
wantMilestone: 999,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
tasks := &ReleaseVSCodeGoTasks{
GitHub: &tc.fakeGithub,
}
semv, ok := parseSemver(tc.version)
if !ok {
t.Fatalf("parseSemver(%q) should success", tc.version)
}
issueNumber, err := tasks.createReleaseMilestoneAndIssue(&workflow.TaskContext{Context: context.Background(), Logger: &testLogger{t, ""}}, semv)
if err != nil {
t.Fatal(err)
}
issue, ok := tc.fakeGithub.Issues[issueNumber]
if !ok {
t.Errorf("release issue with number %v does not exist", issueNumber)
}
if *issue.Number != tc.wantIssue {
t.Errorf("createReleaseMilestoneAndIssue() create an issue with number %v, but should create issue with number %v", issue.Number, tc.wantIssue)
}
if int(*issue.Milestone.ID) != tc.wantMilestone {
t.Errorf("release issue is created under milestone %v should under milestone %v", *issue.Milestone.ID, tc.wantMilestone)
}
})
}
}
func TestNextPrereleaseVersion(t *testing.T) {
tests := []struct {
name string

Просмотреть файл

@ -0,0 +1,31 @@
# Release candidate (TODO: DATE)
- [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.
- [ ] Check [the milestone](https://github.com/golang/vscode-go/issues?q=milestone%%3A%[1]s) and resolve/move unresolved issues.
- [ ] Update master for the release
- [ ] Update hardcoded latest version for gopls.
- [ ] Update [CHANGELOG.md](https://github.com/golang/vscode-go/blob/master/extension/CHANGELOG.md).
- [ ] Make sure the "Thanks" section is up-to-date.
- [ ] Check the Markdown rendering to make sure everything looks good.
- [ ] Update release for the release
- [ ] Create a branch against release for a pull request.
- [ ] Merge changes from master to prepare for the release.
- [ ] Change the version in [package.json](https://github.com/golang/vscode-go/blob/master/extension/package.json) from a -dev suffix
- [ ] Run npm install to make sure [package-lock.json](https://github.com/golang/vscode-go/blob/master/extension/package.json) is up-to-date
- [ ] Update the license file ($ tools/license.sh; mv LICENSE.prod LICENSE)
- [ ] 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.
- [ ] Perform manual [smoke tests](https://github.com/golang/vscode-go/blob/master/docs/smoke-test.md)
- [ ] Create new RC version tag for %[1]s-rc.1 at gerrits vscode-go [repo management page](https://go-review.googlesource.com/admin/repos/vscode-go,tags)
- [ ] 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. Dont mutate uploaded vsix.
- [ ] Ask @golang/tools-team and contributors to this release to test the release candidate
# Final (TODO: DATE)
- [ ] Tag the new release for %[1]s
- [ ] Monitor the [cloud build status](https://pantheon.corp.google.com/cloud-build/dashboard?project=go-vscode-go)
- [ ] Update the release description with CHANGELOG contents
- [ ] Close the milestone
# Prepare for the Next Release
- [ ] Update master post-release
- [ ] Bump the version number to the next monthly release in the master branch
- [ ] Update package.json
- [ ] Update package-lock.json