diff --git a/changes/issue-5732-workaround-to-build-msi-on-apple-m1 b/changes/issue-5732-workaround-to-build-msi-on-apple-m1 new file mode 100644 index 0000000000..0d7552df94 --- /dev/null +++ b/changes/issue-5732-workaround-to-build-msi-on-apple-m1 @@ -0,0 +1 @@ +* Implemented retries as a workaround for transient failures when building MSI packages on Apple M1. diff --git a/cmd/fleetctl/package.go b/cmd/fleetctl/package.go index a0cb77c07f..6045af1c09 100644 --- a/cmd/fleetctl/package.go +++ b/cmd/fleetctl/package.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "path/filepath" "runtime" + "strings" "time" "github.com/fleetdm/fleet/v4/orbit/pkg/packaging" @@ -220,11 +221,29 @@ func packageCommand() *cli.Command { zlog.Logger = zerolog.Nop() } - fmt.Println("Generating your osquery installer...") - path, err := buildFunc(opt) + const maxAttempts = 9 // see #5732 + var ( + attempts int + path string + err error + ) + for attempts < maxAttempts { + attempts++ + + if attempts > 1 { + fmt.Printf("Generating your osquery installer [attempt %d/%d]...\n\n", attempts, maxAttempts) + } else { + fmt.Println("Generating your osquery installer...") + } + path, err = buildFunc(opt) + if err == nil || !shouldRetry(c.String("type"), opt, err) { + break + } + } if err != nil { return err } + path, _ = filepath.Abs(path) fmt.Printf(` Success! You generated an osquery installer at %s @@ -241,6 +260,25 @@ To add other devices to Fleet, distribute this installer using Chef, Ansible, Ja } } +func shouldRetry(pkgType string, opt packaging.Options, err error) bool { + if pkgType != "msi" || runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" { + return false + } + + // building an MSI on macos M1, check if the error is one that should be retried + errStr := err.Error() + switch { + case strings.Contains(errStr, "package root files: heat failed"): + return true + case strings.Contains(errStr, "build package: candle failed"): + return true + case strings.Contains(errStr, "build package: light failed"): + return true + default: + return false + } +} + func checkPEMCertificate(path string) error { cert, err := ioutil.ReadFile(path) if err != nil {