Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rudimentary Bazel Download Retry Logic #495

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
38 changes: 23 additions & 15 deletions bazelisk.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@ def get_version_history(bazelisk_directory):
),
# This only handles versions with numeric components, but that is fine
# since prerelease versions have been excluded.
key=lambda version: tuple(int(component)
for component in version.split('.')),
key=lambda version: tuple(int(component) for component in version.split(".")),
reverse=True,
)

Expand Down Expand Up @@ -339,21 +338,30 @@ def download_bazel_into_directory(version, is_commit, directory):
return destination_path


def download(url, destination_path):
sys.stderr.write("Downloading {}...\n".format(url))
request = Request(url)
if "BAZELISK_BASE_URL" in os.environ:
parts = urlparse(url)
creds = None
def download(url, destination_path, retries=5, wait_seconds=5):
while retries > 0:
retries -= 1
try:
creds = netrc.netrc().hosts.get(parts.netloc)
sys.stderr.write("Downloading {}...\n".format(url))
request = Request(url)
if "BAZELISK_BASE_URL" in os.environ:
parts = urlparse(url)
creds = None
try:
creds = netrc.netrc().hosts.get(parts.netloc)
except Exception:
pass
if creds is not None:
auth = base64.b64encode(("%s:%s" % (creds[0], creds[2])).encode("ascii"))
request.add_header("Authorization", "Basic %s" % auth.decode("utf-8"))

Choose a reason for hiding this comment

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

Can we construct auth and request once and use them across retries ?

Copy link
Author

Choose a reason for hiding this comment

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

I don't see why not. I've made the changes but I'm hitting issues testing it locally. Don't think it's related to the changes, seems it's just unable to download a specific Bazel checksum file; specifically https://storage.googleapis.com/bazel-builds/artifacts/ubuntu1404/f3aa4184c0b53864f597ecfb8969938e9a2a8287/bazel.sha256

I'll go ahead and push my changes and then try reverting them locally to see if the old code in this PR works or if this is indeed an issue accessing that resource.

Copy link
Author

@celestialorb celestialorb Sep 14, 2023

Choose a reason for hiding this comment

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

As a side note I also added configuration of the retry logic via environment variables to this PR. If you'd like me to change those variables or how those settings are sourced just let me know.

Copy link
Author

Choose a reason for hiding this comment

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

I don't see why not. I've made the changes but I'm hitting issues testing it locally. Don't think it's related to the changes, seems it's just unable to download a specific Bazel checksum file; specifically https://storage.googleapis.com/bazel-builds/artifacts/ubuntu1404/f3aa4184c0b53864f597ecfb8969938e9a2a8287/bazel.sha256

I'll go ahead and push my changes and then try reverting them locally to see if the old code in this PR works or if this is indeed an issue accessing that resource.

Figured it out, didn't realize that for the checksum the outer scope was expecting a 404 HTTPError to be thrown if the checksum doesn't exist for the specific Bazel version.


with closing(urlopen(request)) as response, open(destination_path, "wb") as file:
shutil.copyfileobj(response, file)
return
except Exception:
pass
if creds is not None:
auth = base64.b64encode(("%s:%s" % (creds[0], creds[2])).encode("ascii"))
request.add_header("Authorization", "Basic %s" % auth.decode("utf-8"))
with closing(urlopen(request)) as response, open(destination_path, "wb") as file:
shutil.copyfileobj(response, file)
if retries <= 0:
raise
time.sleep(wait_seconds)


def get_bazelisk_directory():
Expand Down