diff --git a/build.go b/build.go index 176965658..09e49a5ed 100644 --- a/build.go +++ b/build.go @@ -288,6 +288,7 @@ func setup() { runPrint("go", "get", "-v", "github.com/AlekSi/gocov-xml") runPrint("go", "get", "-v", "bitbucket.org/tebeka/go2xunit") runPrint("go", "get", "-v", "github.com/alecthomas/gometalinter") + runPrint("go", "get", "-v", "github.com/mitchellh/go-wordwrap") } func test(pkgs ...string) { diff --git a/script/changelog.go b/script/changelog.go index 29f566ae0..e1014e957 100644 --- a/script/changelog.go +++ b/script/changelog.go @@ -10,11 +10,19 @@ package main import ( "bytes" + "encoding/json" "flag" "fmt" + "io/ioutil" "log" + "net/http" + "os" "os/exec" "regexp" + "strconv" + "strings" + + "github.com/mitchellh/go-wordwrap" ) var ( @@ -25,6 +33,8 @@ var ( func main() { flag.Parse() + fmt.Printf("Resolved issues:\n\n") + // Display changelog since the version given on the command line, or // figure out the last release if there were no arguments. var prevRel string @@ -39,7 +49,7 @@ func main() { } // Get the git log with subject and author nickname - bs, err := runError("git", "log", "--reverse", "--pretty=format:%s|%aN", prevRel+"..") + bs, err := runError("git", "log", "--reverse", "--pretty=format:%s|%aN|%cN", prevRel+"..") if err != nil { log.Fatal(err) } @@ -50,14 +60,39 @@ func main() { fields := bytes.Split(line, []byte{'|'}) subj := fields[0] author := fields[1] + committer := fields[2] // Check if subject contains a "(fixes ...)" or "(ref ...)"" if m := subjectIssues.FindSubmatch(subj); len(m) > 0 { - // Find all issue numbers + subj := m[1] issues := issueNumbers.FindAll(m[2], -1) + for _, issue := range issues { + n, err := strconv.Atoi(string(issue[1:])) + if err != nil { + continue + } + title, err := githubIssueTitle(n) + if err != nil { + fmt.Println(err) + continue + } - // Format a changelog entry - fmt.Printf("* %s (%s, @%s)\n", m[1], bytes.Join(issues, []byte(", ")), author) + // Format a changelog entry + reviewed := "" + if !bytes.Equal(committer, author) { + reviewed = fmt.Sprintf(", reviewed by @%s", committer) + } + + message := fmt.Sprintf("%s: %s\n\n%s (by @%s%s)\n", issue, title, subj, author, reviewed) + para := wordwrap.WrapString(message, 74) + for i, line := range strings.Split(para, "\n") { + if i == 0 { + fmt.Println("*", line) + } else { + fmt.Println(" ", line) + } + } + } } } } @@ -70,3 +105,33 @@ func runError(cmd string, args ...string) ([]byte, error) { } return bytes.TrimSpace(bs), nil } + +func githubIssueTitle(n int) (string, error) { + req, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/syncthing/syncthing/issues/%d", n), nil) + + user, token := os.Getenv("GITHUB_USERNAME"), os.Getenv("GITHUB_TOKEN") + if user != "" && token != "" { + req.SetBasicAuth(user, token) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + bs, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var res struct { + Title string + } + err = json.Unmarshal(bs, &res) + if err != nil { + return "", err + } + + return res.Title, nil +}