@@ -24,18 +24,23 @@ import (
2424
2525 "github.com/Songmu/retry"
2626 "github.com/pkg/errors"
27+ "helm.sh/helm/v3/pkg/chart"
2728
29+ "github.com/blang/semver"
2830 "github.com/google/go-github/v56/github"
2931 "golang.org/x/oauth2"
3032)
3133
34+ // Define a custom error for no releases found
35+ var ErrNoReleasesFound = errors .New ("no releases found" )
36+
3237type Release struct {
33- Name string
34- Description string
35- Assets []* Asset
36- Commit string
37- GenerateReleaseNotes bool
38- MakeLatest string
38+ Name string
39+ Description string
40+ Assets []* Asset
41+ Commit string
42+ MakeLatest string
43+ SemVer semver. Version
3944}
4045
4146type Asset struct {
@@ -102,15 +107,75 @@ func (c *Client) GetRelease(_ context.Context, tag string) (*Release, error) {
102107 return result , nil
103108}
104109
110+ // GetLatestChartRelease queries the GitHub API for the previous release of a chart
111+ func (c * Client ) GetLatestChartRelease (_ context.Context , prefix string ) (* Release , error ) {
112+ // Append hyphen to prefix unless already present
113+ prefix = strings .TrimSuffix (prefix , "-" ) + "-"
114+
115+ // Find all versions with tags matching prefix
116+ opt := & github.ListOptions {
117+ PerPage : 100 ,
118+ }
119+ var versions []semver.Version
120+ for {
121+ rels , resp , err := c .Repositories .ListReleases (context .TODO (), c .owner , c .repo , opt )
122+ if err != nil {
123+ return nil , err
124+ }
125+ for _ , rel := range rels {
126+ if strings .HasPrefix (* rel .TagName , prefix ) {
127+ version := semver .MustParse (strings .TrimPrefix (* rel .TagName , prefix ))
128+ versions = append (versions , version )
129+ }
130+ }
131+ if resp .NextPage == 0 {
132+ break
133+ }
134+ opt .Page = resp .NextPage
135+ }
136+
137+ if len (versions ) == 0 {
138+ return nil , ErrNoReleasesFound
139+ }
140+
141+ // Sort versions ascending
142+ semver .Sort (versions )
143+
144+ // Find highest version
145+ latestVersion := versions [len (versions )- 1 ]
146+ var release * github.RepositoryRelease
147+ if rel , _ , err := c .Repositories .GetReleaseByTag (context .TODO (), c .owner , c .repo , prefix + latestVersion .String ()); err == nil {
148+ release = rel
149+ }
150+
151+ result := & Release {
152+ Name : * release .TagName ,
153+ Commit : * release .TargetCommitish ,
154+ SemVer : latestVersion ,
155+ }
156+ return result , nil
157+ }
158+
159+ // GenerateReleaseNotes generates the release notes for a release
160+ func (c * Client ) GenerateReleaseNotes (_ context.Context , latestRelease * Release , chart * chart.Chart ) (string , error ) {
161+ notes , _ , err := c .Repositories .GenerateReleaseNotes (context .TODO (), c .owner , c .repo , & github.GenerateNotesOptions {
162+ TagName : chart .Metadata .Name + "-" + chart .Metadata .Version ,
163+ PreviousTagName : & latestRelease .Name ,
164+ })
165+ if err != nil {
166+ return "" , err
167+ }
168+ return notes .Body , err
169+ }
170+
105171// CreateRelease creates a new release object in the GitHub API
106172func (c * Client ) CreateRelease (_ context.Context , input * Release ) error {
107173 req := & github.RepositoryRelease {
108- Name : & input .Name ,
109- Body : & input .Description ,
110- TagName : & input .Name ,
111- TargetCommitish : & input .Commit ,
112- GenerateReleaseNotes : & input .GenerateReleaseNotes ,
113- MakeLatest : & input .MakeLatest ,
174+ Name : & input .Name ,
175+ Body : & input .Description ,
176+ TagName : & input .Name ,
177+ TargetCommitish : & input .Commit ,
178+ MakeLatest : & input .MakeLatest ,
114179 }
115180
116181 release , _ , err := c .Repositories .CreateRelease (context .TODO (), c .owner , c .repo , req )
0 commit comments