Skip to content

LOC-7291: download darwin-arm64 binary on Apple Silicon - #15

Open
vivianludrick wants to merge 2 commits into
masterfrom
feat/LOC-7291-darwin-arm64-support
Open

LOC-7291: download darwin-arm64 binary on Apple Silicon#15
vivianludrick wants to merge 2 commits into
masterfrom
feat/LOC-7291-darwin-arm64-support

Conversation

@vivianludrick

@vivianludrick vivianludrick commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

What

On macOS, the binding now downloads BrowserStackLocal-darwin-arm64 when the runtime reports arm64; x64 runtimes (including x64-under-Rosetta) keep BrowserStackLocal-darwin-x64, preserving current behavior.

Detection: (POSIX::uname())[4] =~ /arm64|aarch64/.

Why

The Local binary now ships a native Apple Silicon build (browserstack/browserStackTunnel#980). macOS 27 (fall 2026) removes Rosetta 2, so arm64 Macs need the native binary.

Testing

perl -c syntax OK; platform_url() returns the arm64 URL on an Apple Silicon Mac.

⚠ Release ordering

Do not release this before:

  • browserstack/browserStackTunnel#980 is merged and a master build has published binaries/master/BrowserStackLocal-darwin-arm64.zip (public ACL line is already in the Jenkins job) — otherwise arm64 Macs get download failures.
  • This binding downloads from the legacy S3 path (s3.amazonaws.com/browserStack/browserstack-local/). Per review, the download now verifies the HTTP result and falls back to the x64 binary (works via Rosetta 2) when the arm64 object is missing, and never leaves an HTTP error body behind as the "installed" binary — so release ordering is no longer a correctness gate here. Publishing the darwin-arm64 object to that bucket is still wanted so arm64 users get the native binary.

Related Jira

LOC-7291 / epic LOC-7287 (LOC-7285 = binary PR)

🤖 Generated with Claude Code

On macOS the binding now selects BrowserStackLocal-darwin-arm64 when
the runtime reports arm64/aarch64; x64 runtimes (including
x64-under-Rosetta) keep BrowserStackLocal-darwin-x64, preserving
current behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vivianludrick
vivianludrick requested a review from a team as a code owner August 18, 2026 06:26

@07souravkunda 07souravkunda left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detection logic is correct — (POSIX::uname())[4] against arm64/aarch64 is the right call here since $Config{archname} reflects the perl build rather than the host, and adding use POSIX () with the empty import list avoids polluting the namespace. x64-under-Rosetta correctly keeps the x64 binary.

No code objection. The one thing to resolve before release is the legacy-bucket gap you flagged yourself: unlike the bindings that resolve their URL from Rails, this one hardcodes s3.amazonaws.com/browserStack/browserstack-local/, so it regresses on release day rather than degrading later — and because getstore's status is unchecked, the resulting 404 is written to the binary path and short-circuits every later run. Details inline.

Comment thread lib/BrowserStack/Local.pm
sub platform_url {
if ($^O =~ "darwin") {
if ((POSIX::uname())[4] =~ /arm64|aarch64/) {
return "http://s3.amazonaws.com/browserStack/browserstack-local/BrowserStackLocal-darwin-arm64";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL has no object behind it and no publisher, so releasing this turns a working download into a hard 404 on Apple Silicon.

You've documented it in the PR body, but it's worth separating this binding from the others: nodejs/python/ruby/java/csharp resolve their source URL from Rails / bstack-local-prod, so they only degrade once Rosetta is gone. perl and php hardcode the legacy s3.amazonaws.com/browserStack/browserstack-local/ host, so they break immediately on release — an arm64 Mac that works today via the Rosetta x64 binary starts failing at download.

And the failure is sticky. download_binary ignores getstore's return status, so the error response lands at $self->{binary_path} and gets chmod 0777'd. get_binary_path then short-circuits on the -x/-X check on every subsequent run, so the user stays broken until they delete the file by hand.

Fix — either:

  1. Gate the release on BrowserStackLocal-darwin-arm64 being published to that bucket, and added to whatever publishes the other legacy objects; or
  2. Check getstore's status and fall back to the x64 URL on failure, so the regression can't fire even if the release ordering slips.

Given the sticky-file behaviour, option 2 looks worth doing regardless of ordering.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with option 2 (plus the sticky-file fix) — done in the latest commit:

  • getstore's status is now checked (is_success).
  • A failed -darwin-arm64 download falls back to the -darwin-x64 URL (still works on Apple Silicon via Rosetta 2), so release ordering can't turn a working download into a 404.
  • If every attempt fails, the file is unlinked and the error is raised — get_binary_path's -x check can no longer short-circuit on a saved error body.

Verified with a stubbed-getstore harness: arm64 404 → x64 fallback succeeds; both-fail → dies with no poisoned file left. Option 1 (publishing arm64 to the legacy bucket) stays on the release-ordering list so arm64 users eventually get the native binary here too, but it's no longer a correctness gate.

Per review on PR #15: this binding hardcodes the legacy S3 host, where
the arm64 object may not exist yet — and getstore's status was ignored,
so an HTTP error body would be saved as the binary and satisfy the -x
check forever. Now: getstore status is checked; a failed
-darwin-arm64 download falls back to the x64 binary (works on Apple
Silicon via Rosetta 2); if everything fails, the file is removed and
the error is raised instead of left on disk.

Verified with a stubbed-getstore harness: arm64 404 -> x64 fallback
succeeds; both-fail -> dies, no poisoned file left.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants