Skip to content

Commit

Permalink
[workspace] Add upgrade automation for all remaining dependencies (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwnimmer-tri authored Aug 28, 2023
1 parent deef51d commit 1c728b3
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 65 deletions.
34 changes: 11 additions & 23 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

workspace(name = "drake_blender")

load("//tools:workspace_versions.bzl", "WORKSPACE_VERSIONS")
load(
"@bazel_tools//tools/build_defs/repo:http.bzl",
"http_archive",
Expand All @@ -10,9 +11,13 @@ load(

http_archive(
name = "rules_python",
sha256 = "ffc7b877c95413c82bfd5482c017edcf759a6250d8b24e82f41f3c8b8d9e287e",
strip_prefix = "rules_python-0.19.0",
url = "https://github.com/bazelbuild/rules_python/releases/download/0.19.0/rules_python-0.19.0.tar.gz",
sha256 = WORKSPACE_VERSIONS["rules_python"]["sha256"],
strip_prefix = "rules_python-{version}".format(
version = WORKSPACE_VERSIONS["rules_python"]["version"],
),
url = "https://github.com/bazelbuild/rules_python/releases/download/{version}/rules_python-{version}.tar.gz".format(
version = WORKSPACE_VERSIONS["rules_python"]["version"],
),
)

load("@rules_python//python:repositories.bzl", "py_repositories")
Expand Down Expand Up @@ -49,29 +54,12 @@ pip_parse(
name = name,
executable = True,
sha256 = sha256,
url = "https://github.com/bazelbuild/buildtools/releases/download/{}/{}".format(
"v6.1.2",
url = "https://github.com/bazelbuild/buildtools/releases/download/v{}/{}".format(
WORKSPACE_VERSIONS["buildifier"]["version"],
name,
),
)
for name, sha256 in [
(
"buildifier-darwin-amd64",
"e2f4a67691c5f55634fbfb3850eb97dd91be0edd059d947b6c83d120682e0216",
),
(
"buildifier-darwin-arm64",
"7549b5f535219ac957aa2a6069d46fbfc9ea3f74abd85fd3d460af4b1a2099a6",
),
(
"buildifier-linux-amd64",
"51bc947dabb7b14ec6fb1224464fbcf7a7cb138f1a10a3b328f00835f72852ce",
),
(
"buildifier-linux-arm64",
"0ba6e8e3208b5a029164e542ddb5509e618f87b639ffe8cc2f54770022853080",
),
]
for name, sha256 in WORKSPACE_VERSIONS["buildifier"]["binaries"].items()
]

load("@examples_requirements//:requirements.bzl", "install_deps")
Expand Down
22 changes: 11 additions & 11 deletions bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ from pathlib import Path
import sys
import urllib.request as request

# The pinned version and checksum of bazelisk.
_VERSION = "1.17.0"
_SHA256 = "94655ff9cb5286677ee56cd5ac2e82cb91be4385ceb790b0a83369bc79a796b9"
_URL = f"https://raw.githubusercontent.com/bazelbuild/bazelisk/v{_VERSION}/bazelisk.py" # noqa

def _fetch_bazelisk():
# Specify the file we want to fetch.
# TODO(jwnimmer-tri) Find a way to automate bumping this version number.
url = "https://raw.githubusercontent.com/bazelbuild/bazelisk/v1.17.0/bazelisk.py" # noqa
sha256 = "94655ff9cb5286677ee56cd5ac2e82cb91be4385ceb790b0a83369bc79a796b9"

# Create a home for it.
def _fetch_bazelisk():
# Create a home for our downloaded bazelisk.
dot_bazel = Path(__file__).resolve().with_name(".bazel")
dot_bazel.mkdir(exist_ok=True)
bazelisk = dot_bazel / "bazelisk"
Expand All @@ -35,20 +35,20 @@ def _fetch_bazelisk():
hasher = hashlib.sha256()
with open(bazelisk, "rb") as f:
hasher.update(f.read())
if hasher.hexdigest() == sha256:
if hasher.hexdigest() == _SHA256:
return bazelisk
except IOError:
pass

# Fetch it.
print(f"Downloading {url} ...")
with request.urlopen(url=url, timeout=10) as response:
print(f"Downloading {_URL} ...")
with request.urlopen(url=_URL, timeout=10) as response:
content = response.read()
hasher = hashlib.sha256()
hasher.update(content)
digest = hasher.hexdigest()
if digest != sha256:
raise RuntimeError(f"Got wrong sha256 {digest} but wanted {sha256}.")
if digest != _SHA256:
raise RuntimeError(f"Got wrong sha256 {digest} but wanted {_SHA256}.")
with open(bazelisk, "wb") as f:
f.write(content)
bazelisk.chmod(0o755)
Expand Down
2 changes: 1 addition & 1 deletion examples/requirements.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT-0

# To compile this file into requirements.txt, run:
# ../tools/requirements_upgrade.sh
# ../tools/upgrade.sh

drake

Expand Down
2 changes: 1 addition & 1 deletion requirements.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-2-Clause

# To compile this file into requirements.txt, run:
# ./tools/requirements_upgrade.sh
# ./tools/upgrade.sh

bpy
flask
2 changes: 1 addition & 1 deletion test/requirements.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-2-Clause

# To compile this file into requirements.txt, run:
# ../tools/requirements_upgrade.sh
# ../tools/upgrade.sh

black
isort
Expand Down
3 changes: 2 additions & 1 deletion tools/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ bazel_lint_test(
srcs = [
"BUILD.bazel",
"defs.bzl",
"workspace_versions.bzl",
],
)

Expand All @@ -94,6 +95,6 @@ py_lint_test(
"black_main.py",
"isort_main.py",
"pycodestyle_main.py",
"requirements_upgrade_bazel.py",
"upgrade_helper.py",
],
)
20 changes: 0 additions & 20 deletions tools/requirements_upgrade_bazel.py

This file was deleted.

10 changes: 3 additions & 7 deletions tools/requirements_upgrade.sh → tools/upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@
# This script is intended for use by drake-blender developers.
# Users of the project do not need to run it.

# This script upgrades the pinned version of all dependencies, as captured
# by the requirements.txt files that are commited into git as well as the
# bazeliskrc file.

# It does not automatically upgrade our version of bazelisk, which is for now
# hard-coded inside our `./bazel` wrapper file.
# This script upgrades the pinned version of all dependencies.

set -eu -o pipefail

me=$(python3 -c 'import os; print(os.path.realpath("'"$0"'"))')
cd $(dirname "$me")/..

python3 -B ./tools/requirements_upgrade_bazel.py
python3 -B ./tools/upgrade_helper.py
./bazel run //tools:buildifier tools/workspace_versions.bzl

./bazel run //:requirements.update -- --upgrade
./bazel run //:test_requirements.update -- --upgrade
Expand Down
172 changes: 172 additions & 0 deletions tools/upgrade_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Do not run this by hand. Instead, run the full tools/upgrade.sh.

import ast
import hashlib
import json
from pprint import pformat
from urllib.request import urlopen


def _get_current_bazelisk_version() -> str:
"""Parses ``./bazel`` for the old version of bazelisk."""
with open("bazel", encoding="utf-8") as f:
lines = f.read().splitlines()
prefix = "_VERSION = "
for line in lines:
if line.startswith(prefix):
return line.removeprefix(prefix).strip('"')
raise RuntimeError(f"Could not find a line starting with {prefix!r}")


def _write_bazelisk_version(new, sha256):
"""Updates ``./bazel`` with the new version of bazelisk."""
with open("bazel", encoding="utf-8") as f:
lines = f.read().splitlines()
for prefix, value in (("_VERSION = ", new), ("_SHA256 = ", sha256)):
for i in range(len(lines)):
if lines[i].startswith(prefix):
lines[i] = f'{prefix}"{value}"'
break
else:
raise RuntimeError(f"Could not find line starting with {prefix!r}")
new_content = "\n".join(lines) + "\n"
with open("bazel", "w", encoding="utf-8") as f:
f.write(new_content)


def _get_current_bazel_version() -> str:
"""Parses ``.bazeliskrc`` for the old version of bazel."""
with open(".bazeliskrc", encoding="utf-8") as f:
lines = f.read().splitlines()
line = lines[-1]
prefix = "USE_BAZEL_VERSION="
assert line.startswith(prefix), line
return line.removeprefix(prefix)


def _write_bazel_version(new):
"""Overwrites ``.bazeliskrc`` with the new version of bazel."""
with open(".bazeliskrc", "w", encoding="utf-8") as f:
f.write("# SPDX-License-Identifier: BSD-2-Clause\n\n")
f.write(f"USE_BAZEL_VERSION={new}\n")


def _get_current_workspace_versions():
"""Parses ``workspace_versions.bzl`` for the old versions."""
with open("tools/workspace_versions.bzl", encoding="utf-8") as f:
content = f.read()
prefix = "WORKSPACE_VERSIONS = "
assert content.startswith(prefix)
return ast.literal_eval(content.removeprefix(prefix))


def _write_workspace_versions(new):
"""Overwrites ``workspace_versions.bzl`` with the new versions.
We assume that tools/update.sh will run buildifier formatting afterwards.
"""
prefix = "WORKSPACE_VERSIONS = "
content = prefix + pformat(new, width=1, sort_dicts=False)
with open("tools/workspace_versions.bzl", "w", encoding="utf-8") as f:
f.write(content)


def _find_latest_github_release(repo) -> str:
"""Finds the highest-numbered release (excluding prereleases)."""
response = urlopen(f"https://api.github.com/repos/{repo}/releases")
body = response.read()
encoding = response.info().get_content_charset("iso-8859-1")
releases = json.loads(body.decode(encoding))
tags = sorted(
[
release["tag_name"].lstrip("v")
for release in releases
if not release["prerelease"]
],
key=lambda tag: tuple(int(n) for n in tag.split(".")),
reverse=True,
)
return tags[0]


def _get_url_checksum(url) -> str:
"""Returns the sha256sum string of the given url."""
print(f"Downloading {url} ...")
hasher = hashlib.sha256()
with urlopen(url) as response:
while True:
data = response.read(4096)
if not data:
break
hasher.update(data)
return hasher.hexdigest()


def _upgrade_bazelisk():
"""Upgrades bazelisk to its latest version (if necessary)."""
old = _get_current_bazelisk_version()
new = _find_latest_github_release("bazelbuild/bazelisk")
if new == old:
print(f"bazelisk is already at the latest version {new}")
return
print(f"bazelisk will be upgraded to version {new}")
raw_download = "https://raw.githubusercontent.com/bazelbuild/bazelisk"
sha256 = _get_url_checksum(f"{raw_download}/v{new}/bazelisk.py")
_write_bazelisk_version(new, sha256)


def _upgrade_bazel():
"""Upgrades bazel to its latest version (if necessary)."""
old = _get_current_bazel_version()
new = _find_latest_github_release("bazelbuild/bazel")
if new == old:
print(f"bazel is already at the latest version {new}")
return
print(f"bazel will be upgraded to version {new}")
_write_bazel_version(new)


def _upgrade_buildifier():
"""Upgrades buildifier to its latest version (if necessary)."""
workspace_versions = _get_current_workspace_versions()
old = workspace_versions["buildifier"]["version"]
new = _find_latest_github_release("bazelbuild/buildtools")
if new == old:
print(f"buildifier is already at the latest version {new}")
return
print(f"buildifier will be upgraded to version {new}")
workspace_versions["buildifier"]["version"] = new
names = list(workspace_versions["buildifier"]["binaries"].keys())
releases = "https://github.com/bazelbuild/buildtools/releases"
for name in names:
workspace_versions["buildifier"]["binaries"][name] = _get_url_checksum(
f"{releases}/download/v{new}/{name}"
)
_write_workspace_versions(workspace_versions)


def _upgrade_rules_python():
"""Upgrades rules_python to its latest version (if necessary)."""
workspace_versions = _get_current_workspace_versions()
old = workspace_versions["rules_python"]["version"]
new = _find_latest_github_release("bazelbuild/rules_python")
if new == old:
print(f"rules_python is already at the latest version {new}")
return
print(f"rules_python will be upgraded to version {new}")
workspace_versions["rules_python"]["version"] = new
releases = "https://github.com/bazelbuild/rules_python/releases"
workspace_versions["rules_python"]["sha256"] = _get_url_checksum(
f"{releases}/download/{new}/rules_python-{new}.tar.gz"
)
_write_workspace_versions(workspace_versions)


def _main():
_upgrade_bazelisk()
_upgrade_bazel()
_upgrade_buildifier()
_upgrade_rules_python()


assert __name__ == "__main__"
_main()
15 changes: 15 additions & 0 deletions tools/workspace_versions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
WORKSPACE_VERSIONS = {
"buildifier": {
"version": "6.1.2",
"binaries": {
"buildifier-darwin-amd64": "e2f4a67691c5f55634fbfb3850eb97dd91be0edd059d947b6c83d120682e0216",
"buildifier-darwin-arm64": "7549b5f535219ac957aa2a6069d46fbfc9ea3f74abd85fd3d460af4b1a2099a6",
"buildifier-linux-amd64": "51bc947dabb7b14ec6fb1224464fbcf7a7cb138f1a10a3b328f00835f72852ce",
"buildifier-linux-arm64": "0ba6e8e3208b5a029164e542ddb5509e618f87b639ffe8cc2f54770022853080",
},
},
"rules_python": {
"version": "0.19.0",
"sha256": "ffc7b877c95413c82bfd5482c017edcf759a6250d8b24e82f41f3c8b8d9e287e",
},
}

0 comments on commit 1c728b3

Please sign in to comment.