@@ -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+
2936func 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+
251344func getUserKeys (users map [string ]string ) []string {
252345 keys := make ([]string , 0 , len (users ))
253346
0 commit comments