git-ea/blog/release.go

109 lines
2.6 KiB
Go

package blog
import (
"bytes"
_ "embed"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"text/template"
"time"
"github.com/skratchdot/open-golang/open"
)
var (
mergedURLFmt = "https://api.github.com/search/issues?q=repo:go-gitea/gitea+is:pr+is:merged+milestone:%s"
changelogURLFmt = "https://api.github.com/search/issues?q=repo:go-gitea/gitea+is:pr+is:merged+Changelog+%s"
//go:embed release.md
tmplContent string
tmpl = template.Must(template.New("").Parse(tmplContent))
)
// Merged is the API response for getting count of merged PRs in a milestone
type Merged struct {
TotalCount int `json:"total_count"`
}
// FormatRelease formats a release template and injects author, milestone, changelog, and merged PR counts
func FormatRelease(author, milestone, changelog string) ([]byte, error) {
resp, err := http.Get(fmt.Sprintf(mergedURLFmt, milestone))
if err != nil {
return nil, err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var merged Merged
if err := json.Unmarshal(body, &merged); err != nil {
return nil, err
}
date := time.Now()
m := map[string]interface{}{
"Author": author,
"Milestone": milestone,
"Changelog": changelog,
"Merged": merged.TotalCount,
"DateLong": date.Format("2006-01-02T15:04:05+07:00"),
"DateShort": date.Format("2006-01-02"),
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Release is the API response for a release
type Release struct {
Name string `json:"name"`
PublishedAt time.Time `json:"published_at"`
}
// LatestRelease gets the latest release, used as a default for the generator
func LatestRelease() (Release, error) {
var rel Release
resp, err := http.Get("https://api.github.com/repos/go-gitea/gitea/releases/latest")
if err != nil {
return rel, err
}
defer resp.Body.Close()
return rel, json.NewDecoder(resp.Body).Decode(&rel)
}
// ChangelogPR is the API response when searching for the milestone changelog PR
type ChangelogPR struct {
Items []struct {
HTMLURL string `json:"html_url"`
} `json:"items"`
}
// OpenChangelogPullRequest attempts to open a browser to the changelog PR of a given milestone
func OpenChangelogPullRequest(milestone string) error {
resp, err := http.Get(fmt.Sprintf(changelogURLFmt, milestone))
if err != nil {
return err
}
defer resp.Body.Close()
var pr ChangelogPR
if err := json.NewDecoder(resp.Body).Decode(&pr); err != nil {
return err
}
if len(pr.Items) == 0 {
return errors.New("could not find changelog PR")
}
return open.Start(pr.Items[0].HTMLURL + "/files")
}