Skip to content

Commit 0ae03eb

Browse files
committed
Add published Github security advisories to the change log
1 parent aef0135 commit 0ae03eb

File tree

1 file changed

+96
-3
lines changed

1 file changed

+96
-3
lines changed

api/changelog.go

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ type Item struct {
2626
Author string
2727
}
2828

29+
type Cve struct {
30+
Id string
31+
Title string
32+
Url string
33+
Versions []string
34+
}
35+
2936
func Changelog(milestone string, version string) error {
3037
s := spinner.New(spinner.CharSets[11], 120*time.Millisecond)
3138
s.Start()
@@ -36,13 +43,22 @@ func Changelog(milestone string, version string) error {
3643
return err
3744
}
3845

39-
items, err := getItems(milestone, repo.Owner(), repo.Name())
46+
owner := repo.Owner()
47+
name := repo.Name()
48+
49+
items, err := getItems(milestone, owner, name)
4050
if err != nil {
4151
s.Stop()
4252
return err
4353
}
4454

45-
r := strings.NewReader(getContent(items, repo.Owner(), repo.Name(), version))
55+
cves, err := getCves(owner, name)
56+
if err != nil {
57+
s.Stop()
58+
return err
59+
}
60+
61+
r := strings.NewReader(getContent(items, cves, owner, name, version))
4662
atomic.WriteFile("./CHANGELOG.md", r)
4763

4864
s.Stop()
@@ -170,10 +186,56 @@ func search(milestone string, label string, owner string, repo string) ([]Item,
170186
return items, nil
171187
}
172188

173-
func getContent(items []Item, owner string, repo string, version string) string {
189+
func getCves(owner string, repo string) ([]Cve, error) {
190+
args := []string{
191+
"api",
192+
"-X", "GET",
193+
"-F", "state=published",
194+
"repos/" + owner + "/" + repo + "/security-advisories",
195+
}
196+
197+
data, _, err := gh.Exec(args...)
198+
if err != nil {
199+
return nil, err
200+
}
201+
202+
type SecurityAdvisory struct {
203+
Title string `json:"summary"`
204+
Cve string `json:"cve_id"`
205+
Url string `json:"html_url"`
206+
Vulnerabilities []struct {
207+
PatchedVersions string `json:"patched_versions"`
208+
}
209+
}
210+
211+
var s []SecurityAdvisory
212+
213+
err = json.Unmarshal(data.Bytes(), &s)
214+
if err != nil {
215+
return nil, err
216+
}
217+
218+
var cves []Cve
219+
220+
for i := 0; i < len(s); i++ {
221+
var cve Cve
222+
cve.Id = s[i].Cve
223+
cve.Title = s[i].Title
224+
cve.Url = s[i].Url
225+
cve.Versions = strings.Split(s[i].Vulnerabilities[0].PatchedVersions, ", ")
226+
227+
cves = append(cves, cve)
228+
}
229+
230+
return cves, nil
231+
}
232+
233+
func getContent(items []Item, cves []Cve, owner string, repo string, version string) string {
174234
var tags []string
175235
var features []Item
176236
var issues []Item
237+
var security []Cve
238+
var advisories []string
177239

178240
users := make(map[string]string)
179241
prs := make(map[int]string)
@@ -188,8 +250,18 @@ func getContent(items []Item, owner string, repo string, version string) string
188250

189251
for i := 0; i < len(items); i++ {
190252
if items[i].Type == "tag" {
253+
for j := 0; j < len(cves); j++ {
254+
for _, val := range cves[j].Versions {
255+
if val == items[i].Title {
256+
security = append(security, cves[j])
257+
advisories = append(advisories, fmt.Sprintf("[%s]: %s\n", cves[j].Id, cves[j].Url))
258+
}
259+
}
260+
}
261+
191262
content += addSection(&features, &issues)
192263
content += fmt.Sprintf("\n## [%s] (%s)\n", items[i].Title, items[i].Time[0:10])
264+
content += addSecurity(&security)
193265

194266
tags = append(tags, fmt.Sprintf("[%s]: %s/releases/tag/%[1]s\n", items[i].Title, url))
195267
} else {
@@ -204,13 +276,18 @@ func getContent(items []Item, owner string, repo string, version string) string
204276
}
205277
}
206278

279+
content += addSecurity(&security)
207280
content += addSection(&features, &issues)
208281
content += "\n[Semantic Versioning]: https://semver.org/spec/v2.0.0.html\n"
209282

210283
for i := 0; i < len(tags); i++ {
211284
content += tags[i]
212285
}
213286

287+
for i := 0; i < len(advisories); i++ {
288+
content += advisories[i]
289+
}
290+
214291
for _, k := range getUserKeys(users) {
215292
content += users[k]
216293
}
@@ -248,6 +325,22 @@ func addSection(features *[]Item, issues *[]Item) string {
248325
return r
249326
}
250327

328+
func addSecurity(cves *[]Cve) string {
329+
r := ""
330+
331+
if len(*cves) > 0 {
332+
r += "\n**Security fixes:**\n\n"
333+
334+
for _, c := range *cves {
335+
r += fmt.Sprintf("- [%s]: %s\n", c.Id, c.Title)
336+
}
337+
338+
*cves = nil
339+
}
340+
341+
return r
342+
}
343+
251344
func getUserKeys(users map[string]string) []string {
252345
keys := make([]string, 0, len(users))
253346

0 commit comments

Comments
 (0)