|
|
@ -1,9 +1,17 @@ |
|
|
|
package base |
|
|
|
package base |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
|
|
|
|
"encoding/json" |
|
|
|
|
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
|
|
|
|
"io" |
|
|
|
|
|
|
|
"io/ioutil" |
|
|
|
|
|
|
|
"net/http" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"os/exec" |
|
|
|
"os/exec" |
|
|
|
|
|
|
|
"regexp" |
|
|
|
|
|
|
|
"strings" |
|
|
|
|
|
|
|
"time" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// GoGet go get path.
|
|
|
|
// GoGet go get path.
|
|
|
@ -19,3 +27,200 @@ func GoGet(path ...string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type ReleaseInfo struct { |
|
|
|
|
|
|
|
Author struct { |
|
|
|
|
|
|
|
Login string `json:"login"` |
|
|
|
|
|
|
|
} `json:"author"` |
|
|
|
|
|
|
|
PublishedAt string `json:"published_at"` |
|
|
|
|
|
|
|
Body string `json:"body"` |
|
|
|
|
|
|
|
HtmlUrl string `json:"html_url"` |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type CommitInfo struct { |
|
|
|
|
|
|
|
Commit struct { |
|
|
|
|
|
|
|
Message string `json:"message"` |
|
|
|
|
|
|
|
} `json:"commit"` |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type ErrorInfo struct { |
|
|
|
|
|
|
|
Message string |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type GithubApi struct { |
|
|
|
|
|
|
|
Owner string |
|
|
|
|
|
|
|
Repo string |
|
|
|
|
|
|
|
Token string |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetReleaseInfo for getting kratos release info.
|
|
|
|
|
|
|
|
func (g *GithubApi) GetReleaseInfo(version string) ReleaseInfo { |
|
|
|
|
|
|
|
api := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", g.Owner, g.Repo) |
|
|
|
|
|
|
|
if version != "latest" { |
|
|
|
|
|
|
|
api = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", g.Owner, g.Repo, version) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
resp, code := requestGithubAPI(api, "GET", nil, g.Token) |
|
|
|
|
|
|
|
if code != 200 { |
|
|
|
|
|
|
|
printGithubErrorInfo(resp) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
releaseInfo := ReleaseInfo{} |
|
|
|
|
|
|
|
err := json.Unmarshal(resp, &releaseInfo) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return releaseInfo |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetCommitsInfo for getting kratos commits info.
|
|
|
|
|
|
|
|
func (g *GithubApi) GetCommitsInfo() []CommitInfo { |
|
|
|
|
|
|
|
info := g.GetReleaseInfo("latest") |
|
|
|
|
|
|
|
page := 1 |
|
|
|
|
|
|
|
var list []CommitInfo |
|
|
|
|
|
|
|
for { |
|
|
|
|
|
|
|
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?page=%d&since=%s", g.Owner, g.Repo, page, info.PublishedAt) |
|
|
|
|
|
|
|
resp, code := requestGithubAPI(url, "GET", nil, g.Token) |
|
|
|
|
|
|
|
if code != 200 { |
|
|
|
|
|
|
|
printGithubErrorInfo(resp) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var res []CommitInfo |
|
|
|
|
|
|
|
err := json.Unmarshal(resp, &res) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
list = append(list, res...) |
|
|
|
|
|
|
|
if len(res) < 30 || len(res) == 0 { |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
page++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return list |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func printGithubErrorInfo(body []byte) { |
|
|
|
|
|
|
|
errorInfo := &ErrorInfo{} |
|
|
|
|
|
|
|
err := json.Unmarshal(body, errorInfo) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
fatal(errors.New(errorInfo.Message)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func requestGithubAPI(url string, method string, body io.Reader, token string) ([]byte, int) { |
|
|
|
|
|
|
|
cli := &http.Client{Timeout: 60 * time.Second} |
|
|
|
|
|
|
|
request, err := http.NewRequest(method, url, body) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if token != "" { |
|
|
|
|
|
|
|
request.Header.Add("Authorization", token) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
resp, err := cli.Do(request) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer resp.Body.Close() |
|
|
|
|
|
|
|
resBody, err := ioutil.ReadAll(resp.Body) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
fatal(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return resBody, resp.StatusCode |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func ParseCommitsInfo(info []CommitInfo) string { |
|
|
|
|
|
|
|
group := map[string][]string{ |
|
|
|
|
|
|
|
"fix": {}, |
|
|
|
|
|
|
|
"feat": {}, |
|
|
|
|
|
|
|
"deps": {}, |
|
|
|
|
|
|
|
"break": {}, |
|
|
|
|
|
|
|
"other": {}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for i, commitInfo := range info { |
|
|
|
|
|
|
|
msg := commitInfo.Commit.Message |
|
|
|
|
|
|
|
index := strings.Index(fmt.Sprintf("%q", msg), `\n`) |
|
|
|
|
|
|
|
if index != -1 { |
|
|
|
|
|
|
|
msg = commitInfo.Commit.Message[:index-1] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
prefix := []string{"fix", "feat", "deps", "break"} |
|
|
|
|
|
|
|
for _, v := range prefix { |
|
|
|
|
|
|
|
if strings.HasPrefix(msg, v) { |
|
|
|
|
|
|
|
group[v] = append(group[v], msg) |
|
|
|
|
|
|
|
info = append(info[:i], info[i+1:]...) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// other
|
|
|
|
|
|
|
|
for _, value := range info { |
|
|
|
|
|
|
|
msg := value.Commit.Message |
|
|
|
|
|
|
|
index := strings.Index(fmt.Sprintf("%q", msg), `\n`) |
|
|
|
|
|
|
|
if index != -1 { |
|
|
|
|
|
|
|
msg = value.Commit.Message[:index-1] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
group["other"] = append(group["other"], msg) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
md := make(map[string]string) |
|
|
|
|
|
|
|
for key, value := range group { |
|
|
|
|
|
|
|
var text string |
|
|
|
|
|
|
|
switch key { |
|
|
|
|
|
|
|
case "break": |
|
|
|
|
|
|
|
text = "### Breaking Changes\n" |
|
|
|
|
|
|
|
case "deps": |
|
|
|
|
|
|
|
text = "### Dependencies\n" |
|
|
|
|
|
|
|
case "feat": |
|
|
|
|
|
|
|
text = "### New Features\n" |
|
|
|
|
|
|
|
case "fix": |
|
|
|
|
|
|
|
text = "### Bug Fixes\n" |
|
|
|
|
|
|
|
case "other": |
|
|
|
|
|
|
|
text = "### Others\n" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if len(value) > 0 { |
|
|
|
|
|
|
|
md[key] += text |
|
|
|
|
|
|
|
for _, value := range value { |
|
|
|
|
|
|
|
md[key] += fmt.Sprintf("- %s\n", value) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return fmt.Sprint(md["break"], md["deps"], md["feat"], md["fix"], md["other"]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func ParseReleaseInfo(info ReleaseInfo) string { |
|
|
|
|
|
|
|
reg := regexp.MustCompile(`(?m)^\s*$[\r\n]*|[\r\n]+\s+\z|<[\S\s]+?>`) |
|
|
|
|
|
|
|
body := reg.ReplaceAll([]byte(info.Body), []byte("")) |
|
|
|
|
|
|
|
if string(body) == "" { |
|
|
|
|
|
|
|
body = []byte("no release info") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
splitters := "--------------------------------------------" |
|
|
|
|
|
|
|
return fmt.Sprintf( |
|
|
|
|
|
|
|
"Author: %s\nDate: %s\nUrl: %s\n\n%s\n\n%s\n\n%s\n", |
|
|
|
|
|
|
|
info.Author.Login, |
|
|
|
|
|
|
|
info.PublishedAt, |
|
|
|
|
|
|
|
info.HtmlUrl, |
|
|
|
|
|
|
|
splitters, |
|
|
|
|
|
|
|
body, |
|
|
|
|
|
|
|
splitters, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func ParseGithubUrl(url string) (owner string, repo string) { |
|
|
|
|
|
|
|
var start int |
|
|
|
|
|
|
|
start = strings.Index(url, "//") |
|
|
|
|
|
|
|
if start == -1 { |
|
|
|
|
|
|
|
start = strings.Index(url, ":") + 1 |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
start += 2 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
end := strings.LastIndex(url, "/") |
|
|
|
|
|
|
|
gitIndex := strings.LastIndex(url, ".git") |
|
|
|
|
|
|
|
if gitIndex == -1 { |
|
|
|
|
|
|
|
repo = url[strings.LastIndex(url, "/")+1:] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
repo = url[strings.LastIndex(url, "/")+1 : gitIndex] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
tmp := url[start:end] |
|
|
|
|
|
|
|
owner = tmp[strings.Index(tmp, "/")+1:] |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func fatal(err error) { |
|
|
|
|
|
|
|
fmt.Fprintf(os.Stderr, "\033[31mERROR: %s\033[m\n", err) |
|
|
|
|
|
|
|
os.Exit(1) |
|
|
|
|
|
|
|
} |
|
|
|