@@ -3,8 +3,12 @@ package web
33import (
44 "context"
55 "encoding/json"
6+ "fmt"
67 "net/http"
8+ "strings"
79 "time"
10+
11+ "github.com/Masterminds/semver/v3"
812)
913
1014// checkNewVersion checks if a new version is available from github releases
@@ -31,15 +35,16 @@ func (s *Server) checkNewVersionWrapper(ctx context.Context) {
3135 }
3236}
3337
34- // checkNewVersion checks if a new version is available from GitHub releases
38+ // checkNewVersion checks if new versions are available from GitHub releases
3539func (s * Server ) checkNewVersion () error {
36- s .logger .Info ("Checking for new version ..." )
40+ s .logger .Info ("Checking for new versions ..." )
3741
38- // get latest release from GitHub
42+ // Get all releases from GitHub
3943 httpClient := http .DefaultClient
4044 httpClient .Timeout = time .Second * 10
4145
42- resp , err := httpClient .Get ("https://api.github.com/repos/sxwebdev/sentinel/releases/latest" )
46+ // Get multiple pages of releases to ensure we don't miss any
47+ resp , err := httpClient .Get ("https://api.github.com/repos/sxwebdev/sentinel/releases?per_page=100" )
4348 if err != nil {
4449 return nil
4550 }
@@ -49,25 +54,106 @@ func (s *Server) checkNewVersion() error {
4954 return nil
5055 }
5156
52- var releaseInfo struct {
53- TagName string `json:"tag_name"`
54- Body string `json:"body"`
57+ var releases []struct {
58+ TagName string `json:"tag_name"`
59+ Body string `json:"body"`
60+ PublishedAt string `json:"published_at"`
61+ Draft bool `json:"draft"`
62+ Prerelease bool `json:"prerelease"`
5563 }
56- if err := json .NewDecoder (resp .Body ).Decode (& releaseInfo ); err != nil {
64+ if err := json .NewDecoder (resp .Body ).Decode (& releases ); err != nil {
5765 return nil
5866 }
5967
60- // Compare with current version
61- if releaseInfo .TagName != s .serverInfo .Version {
62- s .logger .Infof ("New version available: %s" , releaseInfo .TagName )
68+ // Parse current version
69+ var currentVersion * semver.Version
70+
71+ // Handle special cases like "local", "dev", etc.
72+ if s .serverInfo .Version == "local" || s .serverInfo .Version == "dev" || s .serverInfo .Version == "" {
73+ // For development versions, consider them as version 0.0.0
74+ s .logger .Debugf ("Development version detected (%s), treating as 0.0.0 for comparison" , s .serverInfo .Version )
75+ currentVersion , err = semver .NewVersion ("0.0.0" )
76+ } else {
77+ currentVersion , err = semver .NewVersion (s .serverInfo .Version )
78+ }
79+
80+ if err != nil {
81+ s .logger .Warnf ("Failed to parse current version %s: %v" , s .serverInfo .Version , err )
82+ return nil
83+ }
84+
85+ // Find newer releases (excluding drafts and prereleases)
86+ var newerReleases []struct {
87+ TagName string
88+ Body string
89+ PublishedAt string
90+ Version * semver.Version
91+ }
92+
93+ for _ , release := range releases {
94+ // Skip drafts and prereleases
95+ if release .Draft || release .Prerelease {
96+ continue
97+ }
98+
99+ // Parse release version
100+ releaseVersion , err := semver .NewVersion (release .TagName )
101+ if err != nil {
102+ continue // Skip invalid version tags
103+ }
63104
64- s .serverInfo .AvailableUpdate = & AvailableUpdate {
65- IsAvailableManual : s .config .Upgrader .IsEnabled ,
66- TagName : releaseInfo .TagName ,
67- URL : "https://github.com/sxwebdev/sentinel/releases/tag/" + releaseInfo .TagName ,
68- Description : releaseInfo .Body ,
105+ // Check if release is newer than current version
106+ if releaseVersion .GreaterThan (currentVersion ) {
107+ newerReleases = append (newerReleases , struct {
108+ TagName string
109+ Body string
110+ PublishedAt string
111+ Version * semver.Version
112+ }{
113+ TagName : release .TagName ,
114+ Body : release .Body ,
115+ PublishedAt : release .PublishedAt ,
116+ Version : releaseVersion ,
117+ })
69118 }
70119 }
71120
121+ // If no newer releases found, clear the update info
122+ if len (newerReleases ) == 0 {
123+ s .serverInfo .AvailableUpdate = nil
124+ return nil
125+ }
126+
127+ // Sort newer releases by version (oldest to newest)
128+ // sort.Slice(newerReleases, func(i, j int) bool {
129+ // return newerReleases[i].Version.LessThan(newerReleases[j].Version)
130+ // })
131+
132+ // Get the latest version info
133+ latestRelease := newerReleases [len (newerReleases )- 1 ]
134+
135+ // Combine descriptions from all newer releases
136+ var combinedBody strings.Builder
137+ combinedBody .WriteString (fmt .Sprintf ("# Found %d newer version(s):\n \n " , len (newerReleases )))
138+
139+ for _ , release := range newerReleases {
140+ combinedBody .WriteString (fmt .Sprintf ("## Version %s\n " , release .TagName ))
141+ if release .Body != "" {
142+ combinedBody .WriteString (release .Body )
143+ } else {
144+ combinedBody .WriteString ("No release notes available." )
145+ }
146+ combinedBody .WriteString ("\n \n ---\n \n " )
147+ }
148+
149+ s .logger .Infof ("Found %d newer version(s), latest: %s" , len (newerReleases ), latestRelease .TagName )
150+
151+ s .serverInfo .AvailableUpdate = & AvailableUpdate {
152+ IsAvailableManual : s .config .Upgrader .IsEnabled ,
153+ TagName : latestRelease .TagName ,
154+ URL : "https://github.com/sxwebdev/sentinel/releases/tag/" + latestRelease .TagName ,
155+ Description : combinedBody .String (),
156+ }
157+
72158 return nil
73159}
0 commit comments