@@ -26,10 +26,8 @@ import (
2626 "net/http"
2727 "net/url"
2828 "os"
29- "os/exec"
3029 "path"
3130 "path/filepath"
32- "regexp"
3331 "runtime"
3432 "strings"
3533 "time"
@@ -41,8 +39,8 @@ import (
4139
4240const (
4341 latestSuffix = "LATEST"
44- finishedFileMode = 0555
45- writingFileMode = 0600 // Allow reads so that another process can check if there's a flock.
42+ finishedFileMode = 0o555
43+ writingFileMode = 0o600 // Allow reads so that another process can check if there's a flock.
4644)
4745
4846const (
@@ -58,39 +56,42 @@ const (
5856// for testing purposes.
5957const releaseDataURL = "https://raw.githubusercontent.com/cockroachdb/docs/main/src/current/_data/releases.yml"
6058
61- var muslRE = regexp .MustCompile (`(?i)\bmusl\b` )
62-
6359// GetDownloadURL returns the URL of a CRDB download. It creates the URL for
6460// downloading a CRDB binary for current runtime OS. If desiredVersion is
6561// specified, it will return the URL of the specified version. Otherwise, it
6662// will return the URL of the latest stable cockroach binary. If nonStable is
6763// true, the latest cockroach binary will be used.
6864func GetDownloadURL (desiredVersion string , nonStable bool ) (string , string , error ) {
69- goos := runtime .GOOS
70- if goos == "linux" {
71- goos += func () string {
72- // Detect which C library is present on the system. See
73- // https://unix.stackexchange.com/a/120381.
74- cmd := exec .Command ("ldd" , "--version" )
75- out , err := cmd .Output ()
76- if err != nil {
77- log .Printf ("%s: %s: out=%q err=%v" , testserverMessagePrefix , cmd .Args , out , err )
78- } else if muslRE .Match (out ) {
79- return "-musl"
80- }
81- return "-gnu"
82- }()
65+ return GetDownloadURLWithPlatform (desiredVersion , nonStable , runtime .GOOS , runtime .GOARCH )
66+ }
67+
68+ // GetDownloadURLWithPlatform returns the URL of a CRDB download for the specified
69+ // platform and architecture. If desiredVersion is specified, it will return the URL
70+ // of the specified version. Otherwise, it will return the URL of the latest stable
71+ // cockroach binary. If nonStable is true, the latest cockroach binary will be used.
72+ func GetDownloadURLWithPlatform (
73+ desiredVersion string , nonStable bool , goos , goarch string ,
74+ ) (string , string , error ) {
75+ targetGoos := goos
76+ if targetGoos == "linux" {
77+ targetGoos += "-gnu"
78+ }
79+ // For unstable builds, macOS ARM64 binaries have ".unsigned" at the end
80+ var binaryName string
81+ if nonStable && goos == "darwin" && goarch == "arm64" {
82+ binaryName = fmt .Sprintf ("cockroach.%s-%s.unsigned" , targetGoos , goarch )
83+ } else {
84+ binaryName = fmt .Sprintf ("cockroach.%s-%s" , targetGoos , goarch )
8385 }
84- binaryName := fmt .Sprintf ("cockroach.%s-%s" , goos , runtime .GOARCH )
85- if runtime .GOOS == "windows" {
86+ if goos == "windows" {
8687 binaryName += ".exe"
8788 }
8889
8990 var dbUrl string
9091 var err error
9192
9293 if desiredVersion != "" {
93- dbUrl = getDownloadUrlForVersion (desiredVersion )
94+ dbUrl = getDownloadUrlForVersionWithPlatform (desiredVersion , goos , goarch )
9495 } else if nonStable {
9596 // For the latest (beta) CRDB, we use the `edge-binaries.cockroachdb.com` host.
9697 u := & url.URL {
@@ -137,16 +138,46 @@ func DownloadFromURL(downloadURL string) (*http.Response, error) {
137138// To download the latest STABLE version of CRDB, set `nonStable` to false.
138139// To download the bleeding edge version of CRDB, set `nonStable` to true.
139140func DownloadBinary (tc * TestConfig , desiredVersion string , nonStable bool ) (string , error ) {
140- dbUrl , desiredVersion , err := GetDownloadURL (desiredVersion , nonStable )
141+ return DownloadBinaryWithPlatform (tc , desiredVersion , nonStable , runtime .GOOS , runtime .GOARCH , "" )
142+ }
143+
144+ // DownloadBinaryWithPlatform saves the specified version of CRDB for the given
145+ // platform and architecture into a local binary file, and returns the path for
146+ // this local binary.
147+ // To download a specific cockroach version, specify desiredVersion. Otherwise,
148+ // the latest stable or non-stable version will be chosen.
149+ // To download the latest STABLE version of CRDB, set `nonStable` to false.
150+ // To download the bleeding edge version of CRDB, set `nonStable` to true.
151+ // If outputDir is specified, the binary will be saved there, otherwise to temp directory.
152+ func DownloadBinaryWithPlatform (
153+ tc * TestConfig , desiredVersion string , nonStable bool , goos , goarch , outputDir string ,
154+ ) (string , error ) {
155+ dbUrl , desiredVersion , err := GetDownloadURLWithPlatform (desiredVersion , nonStable , goos , goarch )
141156 if err != nil {
142157 return "" , err
143158 }
144159
145- filename , err := GetDownloadFilename (desiredVersion )
160+ // For unstable builds, use "latest" as the version for filename generation
161+ filenameVersion := desiredVersion
162+ if nonStable && desiredVersion == "" {
163+ filenameVersion = "latest"
164+ }
165+
166+ filename , err := GetDownloadFilenameWithPlatform (filenameVersion , goos )
146167 if err != nil {
147168 return "" , err
148169 }
149- localFile := filepath .Join (os .TempDir (), filename )
170+
171+ var localFile string
172+ if outputDir != "" {
173+ // Create output directory if it doesn't exist
174+ if err := os .MkdirAll (outputDir , 0o755 ); err != nil {
175+ return "" , fmt .Errorf ("failed to create output directory %s: %w" , outputDir , err )
176+ }
177+ localFile = filepath .Join (outputDir , filename )
178+ } else {
179+ localFile = filepath .Join (os .TempDir (), filename )
180+ }
150181
151182 // Short circuit if the file already exists and is in the finished state.
152183 info , err := os .Stat (localFile )
@@ -224,7 +255,7 @@ func DownloadBinary(tc *TestConfig, desiredVersion string, nonStable bool) (stri
224255 if nonStable {
225256 downloadMethod = downloadBinaryFromResponse
226257 } else {
227- if runtime . GOOS == "windows" {
258+ if goos == "windows" {
228259 downloadMethod = downloadBinaryFromZip
229260 } else {
230261 downloadMethod = downloadBinaryFromTar
@@ -253,8 +284,14 @@ func DownloadBinary(tc *TestConfig, desiredVersion string, nonStable bool) (stri
253284
254285// GetDownloadFilename returns the local filename of the downloaded CRDB binary file.
255286func GetDownloadFilename (desiredVersion string ) (string , error ) {
287+ return GetDownloadFilenameWithPlatform (desiredVersion , runtime .GOOS )
288+ }
289+
290+ // GetDownloadFilenameWithPlatform returns the local filename of the downloaded CRDB binary file
291+ // for the specified platform.
292+ func GetDownloadFilenameWithPlatform (desiredVersion , goos string ) (string , error ) {
256293 filename := fmt .Sprintf ("cockroach-%s" , desiredVersion )
257- if runtime . GOOS == "windows" {
294+ if goos == "windows" {
258295 filename += ".exe"
259296 }
260297 return filename , nil
@@ -320,28 +357,28 @@ func getLatestStableVersionInfo() (string, string, error) {
320357 }
321358 }
322359
323- downloadUrl := getDownloadUrlForVersion (latestStableVersion .String ())
360+ downloadUrl := getDownloadUrlForVersionWithPlatform (latestStableVersion .String (), runtime . GOOS , runtime . GOARCH )
324361
325362 latestStableVerFormatted := strings .ReplaceAll (latestStableVersion .String (), "." , "-" )
326363 return downloadUrl , latestStableVerFormatted , nil
327364}
328365
329- func getDownloadUrlForVersion (version string ) string {
330- switch runtime . GOOS {
366+ func getDownloadUrlForVersionWithPlatform (version , goos , goarch string ) string {
367+ switch goos {
331368 case "linux" :
332- return fmt .Sprintf (linuxUrlpat , version , runtime . GOARCH )
369+ return fmt .Sprintf (linuxUrlpat , version , goarch )
333370 case "darwin" :
334- switch runtime . GOARCH {
371+ switch goarch {
335372 case "arm64" :
336- return fmt .Sprintf (macUrlpat , version , "11.0" , runtime . GOARCH )
373+ return fmt .Sprintf (macUrlpat , version , "11.0" , goarch )
337374 case "amd64" :
338- return fmt .Sprintf (macUrlpat , version , "10.9" , runtime . GOARCH )
375+ return fmt .Sprintf (macUrlpat , version , "10.9" , goarch )
339376 }
340377 case "windows" :
341378 return fmt .Sprintf (winUrlpat , version )
342379 }
343380
344- panic (errors . New ( "could not get supported go os version" ))
381+ panic (fmt . Errorf ( "unsupported platform/architecture combination: %s-%s" , goos , goarch ))
345382}
346383
347384// downloadBinaryFromResponse copies the http response's body directly into a local binary.
0 commit comments