downloadCopilot downloads and installs the Copilot CLI to installDir. It returns the path to the installed Copilot binary.
(httpClient *http.Client, ios *iostreams.IOStreams, installDir, localPath string)
| 236 | // downloadCopilot downloads and installs the Copilot CLI to installDir. |
| 237 | // It returns the path to the installed Copilot binary. |
| 238 | func downloadCopilot(httpClient *http.Client, ios *iostreams.IOStreams, installDir, localPath string) (string, error) { |
| 239 | platform := runtime.GOOS |
| 240 | if platform == "windows" { |
| 241 | platform = "win32" |
| 242 | } |
| 243 | |
| 244 | arch := runtime.GOARCH |
| 245 | if arch == "amd64" { |
| 246 | arch = "x64" |
| 247 | } |
| 248 | |
| 249 | if arch != "x64" && arch != "arm64" { |
| 250 | return "", fmt.Errorf("unsupported architecture: %s (supported: x64, arm64)", arch) |
| 251 | } |
| 252 | |
| 253 | var archiveURL string |
| 254 | var archiveName string |
| 255 | var isZip bool |
| 256 | switch platform { |
| 257 | case "win32": |
| 258 | archiveName = fmt.Sprintf("copilot-%s-%s.zip", platform, arch) |
| 259 | archiveURL = fmt.Sprintf("https://github.com/github/copilot-cli/releases/latest/download/%s", archiveName) |
| 260 | isZip = true |
| 261 | case "linux", "darwin": |
| 262 | archiveName = fmt.Sprintf("copilot-%s-%s.tar.gz", platform, arch) |
| 263 | archiveURL = fmt.Sprintf("https://github.com/github/copilot-cli/releases/latest/download/%s", archiveName) |
| 264 | default: |
| 265 | return "", fmt.Errorf("unsupported platform: %s (supported: linux, darwin, windows)", platform) |
| 266 | } |
| 267 | |
| 268 | checksumsURL := "https://github.com/github/copilot-cli/releases/latest/download/SHA256SUMS.txt" |
| 269 | |
| 270 | expectedChecksum, err := fetchExpectedChecksum(httpClient, checksumsURL, archiveName) |
| 271 | if err != nil { |
| 272 | return "", fmt.Errorf("failed to fetch checksums: %w", err) |
| 273 | } |
| 274 | |
| 275 | ios.StartProgressIndicatorWithLabel(fmt.Sprintf("Downloading Copilot CLI from %s", archiveURL)) |
| 276 | defer ios.StopProgressIndicator() |
| 277 | |
| 278 | resp, err := httpClient.Get(archiveURL) |
| 279 | if err != nil { |
| 280 | return "", fmt.Errorf("failed to download: %w", err) |
| 281 | } |
| 282 | defer resp.Body.Close() |
| 283 | |
| 284 | if resp.StatusCode != http.StatusOK { |
| 285 | return "", fmt.Errorf("download failed with status: %s", resp.Status) |
| 286 | } |
| 287 | |
| 288 | // Download to temp file while calculating checksum |
| 289 | tmpFile, err := os.CreateTemp("", "copilot-download-*") |
| 290 | if err != nil { |
| 291 | return "", fmt.Errorf("failed to create temp file: %w", err) |
| 292 | } |
| 293 | defer os.Remove(tmpFile.Name()) |
| 294 | defer tmpFile.Close() |
| 295 |