Skip to content

Commit bc2a2c4

Browse files
authored
Merge pull request #50 from vitessio/close-milestones
Add close milestone
2 parents 4d6cea7 + 3585a26 commit bc2a2c4

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

go/interactive/release/close_milestone.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
tea "github.com/charmbracelet/bubbletea"
2323
"vitess.io/vitess-releaser/go/interactive/ui"
2424
"vitess.io/vitess-releaser/go/releaser"
25+
"vitess.io/vitess-releaser/go/releaser/release"
2526
"vitess.io/vitess-releaser/go/releaser/steps"
2627
)
2728

@@ -44,9 +45,19 @@ func CloseMilestoneItem(ctx context.Context) *ui.MenuItem {
4445
type closeMilestoneUrl string
4546

4647
func closeMilestoneUpdate(mi *ui.MenuItem, msg tea.Msg) (*ui.MenuItem, tea.Cmd) {
48+
_, ok := msg.(closeMilestoneUrl)
49+
if !ok {
50+
return mi, nil
51+
}
52+
53+
mi.Info = mi.State.Issue.CloseMilestone.URL
54+
mi.IsDone = mi.State.Issue.CloseMilestone.Done
4755
return mi, nil
4856
}
4957

5058
func closeMilestoneAct(mi *ui.MenuItem) (*ui.MenuItem, tea.Cmd) {
51-
return mi, nil
59+
pl, back := release.CloseMilestone(mi.State)
60+
return mi, tea.Batch(func() tea.Msg {
61+
return closeMilestoneUrl(back())
62+
}, ui.PushDialog(ui.NewProgressDialog("Close Milestone", pl)))
5263
}

go/releaser/github/milestone.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,23 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"log"
23+
"strconv"
2324
"strings"
2425

2526
"github.com/cli/go-gh"
2627
)
2728

2829
type Milestone struct {
29-
URL string `json:"url"`
30+
URL string `json:"url"`
31+
Number int `json:"number"`
3032
}
3133

3234
func GetMilestonesByName(repo, name string) []Milestone {
3335
stdOut, _, err := gh.Exec(
3436
"milestone", "list",
3537
"--query", name,
3638
"--repo", repo,
37-
"--json", "url",
39+
"--json", "url,number",
3840
"--state", "all",
3941
)
4042
if err != nil {
@@ -62,4 +64,24 @@ func CreateNewMilestone(repo, name string) string {
6264
out := strings.ReplaceAll(stdOut.String(), "\n", "")
6365
idx := strings.LastIndex(out, fmt.Sprintf("https://github.com/%s/milestone/", repo))
6466
return out[idx:]
65-
}
67+
}
68+
69+
func CloseMilestone(repo, name string) string {
70+
ms := GetMilestonesByName(repo, name)
71+
if len(ms) != 1 {
72+
log.Fatalf("expected to find one milestone found %d", len(ms))
73+
}
74+
75+
stdOut, _, err := gh.Exec(
76+
"milestone", "edit",
77+
strconv.Itoa(ms[0].Number),
78+
"--repo", repo,
79+
"--state", "closed",
80+
)
81+
if err != nil {
82+
log.Fatal(err.Error())
83+
}
84+
out := strings.ReplaceAll(stdOut.String(), "\n", "")
85+
idx := strings.LastIndex(out, fmt.Sprintf("https://github.com/%s/milestone/", repo))
86+
return out[idx:]
87+
}

go/releaser/github/pr.go

+35
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,38 @@ func GetMergedPRsAndAuthorsByMilestone(repo, milestone string) (prs []PR, author
179179
sort.Strings(authors)
180180
return prs, authors
181181
}
182+
183+
func GetOpenedPRsByMilestone(repo, milestone string) []PR {
184+
byteRes, _, err := gh.Exec(
185+
"pr", "list",
186+
"-s", "open",
187+
"-S", fmt.Sprintf("milestone:%s", milestone),
188+
"--json", "number,title,labels,author",
189+
"--limit", "5000",
190+
"--repo", repo,
191+
)
192+
if err != nil {
193+
log.Fatal(err)
194+
}
195+
196+
var prs []PR
197+
err = json.Unmarshal(byteRes.Bytes(), &prs)
198+
if err != nil {
199+
log.Fatal(err)
200+
}
201+
return prs
202+
}
203+
204+
func AssignMilestoneToPRs(repo, milestone string, prs []PR) {
205+
for _, pr := range prs {
206+
_, _, err := gh.Exec(
207+
"pr", "edit",
208+
strconv.Itoa(pr.Number),
209+
"--milestone", milestone,
210+
"--repo", repo,
211+
)
212+
if err != nil {
213+
log.Fatal(err)
214+
}
215+
}
216+
}

go/releaser/release/milestone.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright 2023 The Vitess Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package release
18+
19+
import (
20+
"fmt"
21+
22+
"vitess.io/vitess-releaser/go/releaser"
23+
"vitess.io/vitess-releaser/go/releaser/github"
24+
"vitess.io/vitess-releaser/go/releaser/logging"
25+
)
26+
27+
func CloseMilestone(state *releaser.State) (*logging.ProgressLogging, func() string) {
28+
pl := &logging.ProgressLogging{
29+
TotalSteps: 5,
30+
}
31+
32+
return pl, func() string {
33+
milestone := fmt.Sprintf("v%s", state.Release)
34+
nextRelease := releaser.FindVersionAfterNextRelease(state)
35+
nextMilestone := fmt.Sprintf("v%s", nextRelease)
36+
37+
pl.NewStepf("Get opened Pull Requests for Milestone %s", milestone)
38+
prs := github.GetOpenedPRsByMilestone(state.VitessRepo, milestone)
39+
40+
if len(prs) > 0 {
41+
pl.NewStepf("Move %d Pull Requests to the %s Milestone", len(prs), nextMilestone)
42+
github.AssignMilestoneToPRs(state.VitessRepo, nextMilestone, prs)
43+
} else {
44+
pl.TotalSteps--
45+
}
46+
47+
pl.NewStepf("Close Milestone %s", milestone)
48+
url := github.CloseMilestone(state.VitessRepo, milestone)
49+
50+
pl.NewStepf("Update Issue %s on GitHub", state.IssueLink)
51+
state.Issue.CloseMilestone.Done = true
52+
state.Issue.CloseMilestone.URL = url
53+
_, fn := state.UploadIssue()
54+
issueLink := fn()
55+
56+
pl.NewStepf("Issue updated, see: %s", issueLink)
57+
return url
58+
}
59+
}

0 commit comments

Comments
 (0)