-
Notifications
You must be signed in to change notification settings - Fork 13
/
changelog.go
122 lines (99 loc) · 2.96 KB
/
changelog.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"bufio"
"fmt"
"io"
"net/url"
"regexp"
"strings"
"time"
"github.com/google/go-github/v58/github"
)
type link struct {
name string
url string
}
// ChangeLog is a struct to generate changelog output from given repository URL
type ChangeLog struct {
repoURL string
out io.Writer
level int
drafts bool
ignore *regexp.Regexp
extract *regexp.Regexp
}
func (cl *ChangeLog) filterReleases(rels []*github.RepositoryRelease) []*github.RepositoryRelease {
if cl.drafts && cl.ignore == nil && cl.extract == nil {
return rels
}
i := 0
for i < len(rels) {
r := rels[i]
t := r.GetTagName()
if !cl.drafts && r.GetDraft() ||
cl.ignore != nil && cl.ignore.MatchString(t) ||
cl.extract != nil && !cl.extract.MatchString(t) {
rels = append(rels[:i], rels[i+1:]...)
} else {
i++
}
}
return rels
}
// Generate generates changelog text from given releases and outputs it to its writer
func (cl *ChangeLog) Generate(rels []*github.RepositoryRelease) error {
rels = cl.filterReleases(rels)
out := bufio.NewWriter(cl.out)
heading := strings.Repeat("#", cl.level)
numRels := len(rels)
relLinks := make([]link, 0, numRels)
for i, rel := range rels {
prevTag := ""
if i+1 < numRels {
prevTag = rels[i+1].GetTagName()
}
title := strings.TrimSpace(rel.GetName())
tag := rel.GetTagName()
if tag == "" {
return fmt.Errorf(
"release %q created at %s is not associated with any tag name. cannot determine a tag name for the release. did you forget setting tag name in the draft release?",
strings.TrimSpace(rel.GetName()),
rel.CreatedAt.Format(time.RFC3339),
)
}
var compareURL string
if prevTag == "" {
compareURL = fmt.Sprintf("%s/tree/%s", cl.repoURL, tag)
} else {
compareURL = fmt.Sprintf("%s/compare/%s...%s", cl.repoURL, prevTag, tag)
}
fmt.Fprintf(out, "<a name=\"%s\"></a>\n", tag)
if title == "" {
title = tag
} else if !strings.Contains(title, tag) {
title = fmt.Sprintf("%s (%s)", title, tag)
}
pageURL := fmt.Sprintf("%s/releases/tag/%s", cl.repoURL, tag)
var created github.Timestamp
if rel.GetDraft() {
created = rel.GetCreatedAt()
} else {
created = rel.GetPublishedAt()
}
fmt.Fprintf(out, "%s [%s](%s) - %s\n\n", heading, title, pageURL, created.Format("02 Jan 2006"))
fmt.Fprint(out, LinkRefs(strings.Replace(rel.GetBody(), "\r", "", -1), cl.repoURL))
fmt.Fprintf(out, "\n\n[Changes][%s]\n\n\n", tag)
relLinks = append(relLinks, link{tag, compareURL})
}
for _, link := range relLinks {
fmt.Fprintf(out, "[%s]: %s\n", link.name, link.url)
}
fmt.Fprintf(out, "\n<!-- Generated by https://github.com/rhysd/changelog-from-release %s -->\n", version)
return out.Flush()
}
// NewChangeLog creates a new ChangeLog instance
func NewChangeLog(w io.Writer, u *url.URL, l int, d bool, i, e *regexp.Regexp) *ChangeLog {
// Strip credentials in the repository URL (#9)
u.User = nil
return &ChangeLog{strings.TrimSuffix(u.String(), ".git"), w, l, d, i, e}
}