diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index 6819ee7c4..44a9cbab4 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -371,14 +371,28 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { } platform, ext := m.platform() + isMacARM := platform == "darwin-arm64" + trueARMBinary := false + var asset *releaseAsset for _, a := range r.Assets { if strings.HasSuffix(a.Name, platform+ext) { asset = &a + trueARMBinary = isMacARM break } } + // if an arm64 binary is unavailable, fall back to amd64 if it can be executed through Rosetta 2 + if asset == nil && isMacARM && hasRosetta() { + for _, a := range r.Assets { + if strings.HasSuffix(a.Name, "darwin-amd64") { + asset = &a + break + } + } + } + if asset == nil { return fmt.Errorf( "%[1]s unsupported for %[2]s. Open an issue: `gh issue create -R %[3]s/%[1]s -t'Support %[2]s'`", @@ -404,6 +418,11 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { if err != nil { return fmt.Errorf("failed to download asset %s: %w", asset.Name, err) } + if trueARMBinary { + if err := codesignBinary(binPath); err != nil { + return fmt.Errorf("failed to codesign downloaded binary: %w", err) + } + } } manifest := binManifest{ @@ -844,3 +863,17 @@ func possibleDists() []string { "windows-arm", } } + +func hasRosetta() bool { + _, err := os.Stat("/Library/Apple/usr/libexec/oah/libRosettaRuntime") + return err == nil +} + +func codesignBinary(binPath string) error { + codesignExe, err := safeexec.LookPath("codesign") + if err != nil { + return err + } + cmd := exec.Command(codesignExe, "--sign", "-", "--force", "--preserve-metadata=entitlements,requirements,flags,runtime", binPath) + return cmd.Run() +}