Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion lib/BrowserStack/Local.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use IO::Socket;
use LWP::Simple;
use File::Temp;
use Config;
use POSIX ();
use Cwd;
use File::Temp qw(tempdir);
use File::Path qw(make_path);
Expand Down Expand Up @@ -200,6 +201,9 @@ sub get_available_path {

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.

}
return "http://s3.amazonaws.com/browserStack/browserstack-local/BrowserStackLocal-darwin-x64";
}
elsif ($^O =~ /^Win/) {
Expand All @@ -218,7 +222,21 @@ sub platform_url {
sub download_binary {
my ($self) = @_;
my $url = $self->platform_url();
getstore($url, $self->{binary_path});
my $status = getstore($url, $self->{binary_path});
# If the arm64 binary is not published to the legacy bucket yet, fall back
# to the x64 binary, which still works on Apple Silicon via Rosetta 2 —
# releasing must not turn a working download into a 404.
if (!is_success($status) && $url =~ /-darwin-arm64$/) {
$url =~ s/-darwin-arm64$/-darwin-x64/;
$status = getstore($url, $self->{binary_path});
}
if (!is_success($status)) {
# don't leave the HTTP error body behind as an "installed" binary — it
# would satisfy the -x check in get_binary_path on every later run and
# stick until the user deletes it by hand
unlink $self->{binary_path};
die "Failed to download BrowserStackLocal binary (HTTP $status) from $url\n";
}
chmod 0777, $self->{binary_path};
}

Expand Down
Loading