@@ -348,26 +348,16 @@ func (app *App) Shutdown() {
}
}
-// checkForUpdates checks for available updates in the background.
+// checkForUpdates checks for available updates.
func (app *App) checkForUpdates(ctx context.Context) {
- // Use a timeout to avoid hanging indefinitely.
- checkCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
+ checkCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
-
- // Check for updates asynchronously.
- updateCh := update.CheckForUpdateAsync(checkCtx, app.config.Options.DataDirectory)
-
- select {
- case info := <-updateCh:
- if info != nil && info.Available {
- // Send update notification through the event system.
- app.events <- pubsub.UpdateAvailableMsg{
- CurrentVersion: info.CurrentVersion,
- LatestVersion: info.LatestVersion,
- }
- }
- case <-checkCtx.Done():
- // Timeout or context cancelled.
+ info, err := update.Check(checkCtx)
+ if err != nil || info == nil || !info.Available {
return
}
+ app.events <- pubsub.UpdateAvailableMsg{
+ CurrentVersion: info.CurrentVersion,
+ LatestVersion: info.LatestVersion,
+ }
}
@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"net/http"
- "os"
"strings"
"time"
@@ -19,23 +18,17 @@ const (
userAgent = "crush/1.0"
)
-// Release represents a GitHub release.
-type Release struct {
- TagName string `json:"tag_name"`
- HTMLURL string `json:"html_url"`
-}
-
-// UpdateInfo contains information about an available update.
-type UpdateInfo struct {
+// Info contains information about an available update.
+type Info struct {
CurrentVersion string
LatestVersion string
ReleaseURL string
Available bool
}
-// CheckForUpdate checks if a new version is available.
-func CheckForUpdate(ctx context.Context) (*UpdateInfo, error) {
- info := &UpdateInfo{
+// Check checks if a new version is available.
+func Check(ctx context.Context) (*Info, error) {
+ info := &Info{
CurrentVersion: version.Version,
}
@@ -62,8 +55,14 @@ func CheckForUpdate(ctx context.Context) (*UpdateInfo, error) {
return info, nil
}
+// githubRelease represents a GitHub release.
+type githubRelease struct {
+ TagName string `json:"tag_name"`
+ HTMLURL string `json:"html_url"`
+}
+
// fetchLatestRelease fetches the latest release information from GitHub.
-func fetchLatestRelease(ctx context.Context) (*Release, error) {
+func fetchLatestRelease(ctx context.Context) (*githubRelease, error) {
client := &http.Client{
Timeout: 30 * time.Second,
}
@@ -86,35 +85,10 @@ func fetchLatestRelease(ctx context.Context) (*Release, error) {
return nil, fmt.Errorf("GitHub API returned status %d: %s", resp.StatusCode, string(body))
}
- var release Release
+ var release githubRelease
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
return nil, err
}
return &release, nil
}
-
-// CheckForUpdateAsync performs an update check in the background and returns immediately.
-// If an update is available, it returns the update info through the channel.
-func CheckForUpdateAsync(ctx context.Context, dataDir string) <-chan *UpdateInfo {
- ch := make(chan *UpdateInfo, 1)
-
- go func() {
- defer close(ch)
-
- // Perform the check.
- info, err := CheckForUpdate(ctx)
- if err != nil {
- // Log error but don't fail.
- fmt.Fprintf(os.Stderr, "Failed to check for updates: %v\n", err)
- return
- }
-
- // Send update info if available.
- if info.Available {
- ch <- info
- }
- }()
-
- return ch
-}
@@ -8,65 +8,6 @@ import (
"github.com/stretchr/testify/require"
)
-func TestCompareVersions(t *testing.T) {
- tests := []struct {
- name string
- v1 string
- v2 string
- expected int
- }{
- {
- name: "equal versions",
- v1: "1.0.0",
- v2: "1.0.0",
- expected: 0,
- },
- {
- name: "v1 less than v2 - patch",
- v1: "1.0.0",
- v2: "1.0.1",
- expected: -1,
- },
- {
- name: "v1 less than v2 - minor",
- v1: "1.0.0",
- v2: "1.1.0",
- expected: -1,
- },
- {
- name: "v1 less than v2 - major",
- v1: "1.0.0",
- v2: "2.0.0",
- expected: -1,
- },
- {
- name: "v1 greater than v2",
- v1: "2.0.0",
- v2: "1.9.9",
- expected: 1,
- },
- {
- name: "with v prefix",
- v1: "v1.0.0",
- v2: "v1.0.1",
- expected: -1,
- },
- {
- name: "different lengths",
- v1: "1.0",
- v2: "1.0.0",
- expected: -1,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := compareVersions(tt.v1, tt.v2)
- require.Equal(t, tt.expected, result)
- })
- }
-}
-
func TestCheckForUpdate_DevelopmentVersion(t *testing.T) {
// Test that development versions don't trigger updates.
ctx := context.Background()
@@ -78,7 +19,7 @@ func TestCheckForUpdate_DevelopmentVersion(t *testing.T) {
version.Version = originalVersion
}()
- info, err := CheckForUpdate(ctx)
+ info, err := Check(ctx)
require.NoError(t, err)
require.NotNil(t, info)
require.False(t, info.Available)