PerformUpdate downloads and installs the latest version.
(currentVersion string, opts Options)
| 93 | |
| 94 | // PerformUpdate downloads and installs the latest version. |
| 95 | func PerformUpdate(currentVersion string, opts Options) (*CheckResult, error) { |
| 96 | client := &http.Client{Timeout: checkTimeout} |
| 97 | resp, err := client.Get(opts.releasesURL()) |
| 98 | if err != nil { |
| 99 | return nil, fmt.Errorf("fetching latest release: %w", err) |
| 100 | } |
| 101 | defer resp.Body.Close() |
| 102 | |
| 103 | if resp.StatusCode == http.StatusForbidden { |
| 104 | return nil, ErrRateLimited |
| 105 | } |
| 106 | if resp.StatusCode != http.StatusOK { |
| 107 | return nil, fmt.Errorf("GitHub API returned status %d", resp.StatusCode) |
| 108 | } |
| 109 | |
| 110 | var release Release |
| 111 | if err := json.NewDecoder(resp.Body).Decode(&release); err != nil { |
| 112 | return nil, fmt.Errorf("parsing release response: %w", err) |
| 113 | } |
| 114 | |
| 115 | latest := normalizeVersion(release.TagName) |
| 116 | current := normalizeVersion(currentVersion) |
| 117 | |
| 118 | if baseVersion(current) == latest { |
| 119 | return &CheckResult{ |
| 120 | CurrentVersion: current, |
| 121 | LatestVersion: latest, |
| 122 | UpdateAvailable: false, |
| 123 | }, nil |
| 124 | } |
| 125 | |
| 126 | // Find the binary asset for this OS/arch |
| 127 | binaryAsset, checksumAsset := findAssets(release.Assets, runtime.GOOS, runtime.GOARCH) |
| 128 | if binaryAsset == nil { |
| 129 | return nil, fmt.Errorf("no binary available for %s/%s", runtime.GOOS, runtime.GOARCH) |
| 130 | } |
| 131 | |
| 132 | // Get the current binary path |
| 133 | binaryPath, err := os.Executable() |
| 134 | if err != nil { |
| 135 | return nil, fmt.Errorf("finding current binary path: %w", err) |
| 136 | } |
| 137 | binaryPath, err = filepath.EvalSymlinks(binaryPath) |
| 138 | if err != nil { |
| 139 | return nil, fmt.Errorf("resolving binary path: %w", err) |
| 140 | } |
| 141 | |
| 142 | // Check write permissions |
| 143 | dir := filepath.Dir(binaryPath) |
| 144 | if err := checkWritePermission(dir); err != nil { |
| 145 | return nil, fmt.Errorf("Permission denied. Run 'sudo chief update' to upgrade.") |
| 146 | } |
| 147 | |
| 148 | // Download binary to temp file |
| 149 | tmpFile, err := downloadToTemp(binaryAsset.BrowserDownloadURL, dir) |
| 150 | if err != nil { |
| 151 | return nil, fmt.Errorf("downloading update: %w", err) |
| 152 | } |