From faf2f9fd0a885b45645f277d5fcb7485f0d5b48e Mon Sep 17 00:00:00 2001 From: Dave Rolsky Date: Tue, 24 Dec 2024 11:35:28 -0600 Subject: [PATCH] Include the hash of the `cross` binary in the cache key This protects against changes to the Docker images that `cross` uses. --- README.md | 4 +++ action.yml | 2 +- parse-and-set-rust-cache-parameters.py | 49 ++++++++++++++++++++++++++ parse-rust-cache-parameters.py | 28 --------------- 4 files changed, 54 insertions(+), 29 deletions(-) create mode 100755 parse-and-set-rust-cache-parameters.py delete mode 100755 parse-rust-cache-parameters.py diff --git a/README.md b/README.md index c510515..ab0ef06 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,10 @@ When running `cargo` on a Linux system, it will also include the output of runni system libraries. If those library versions change across OS versions (e.g. Ubuntu 20.04 to 22.04), then the cache will be broken for these cases. +When running `cross`, the hash of the `cross` binary will be included in the cache key. This is done +because the Docker images that `cross` uses can change when `cross` is updated. We want to make sure +that we do not re-use the cache across changes when these images change. + Finally, it will run `strip` to strip the binaries it builds if the `strip` parameter is true. This is only possible for builds that are not done via `cross`. In addition, Windows builds for `aarch64` cannot be stripped either. diff --git a/action.yml b/action.yml index fe7650e..cf4b3fd 100644 --- a/action.yml +++ b/action.yml @@ -140,7 +140,7 @@ runs: fi # This will get the inputs JSON from the `RUST_CACHE_PARAMETERS` env var. This avoids # any string interpolation issues, since the inputs will contain quotes. - parse-rust-cache-parameters.py "${{ inputs.target }}" "${{ steps.set-build-command.outputs.build-command }}" "$OS_VERSION" + parse-and-set-rust-cache-parameters.py "${{ inputs.target }}" "${{ steps.set-build-command.outputs.build-command }}" "$OS_VERSION" env: RUST_CACHE_PARAMETERS: ${{ inputs.rust-cache-parameters }} if: inputs.use-rust-cache == 'true' diff --git a/parse-and-set-rust-cache-parameters.py b/parse-and-set-rust-cache-parameters.py new file mode 100755 index 0000000..e584e28 --- /dev/null +++ b/parse-and-set-rust-cache-parameters.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import json +import os +import sys +import hashlib + + +def main(): + target = sys.argv[1] + build_command = sys.argv[2] + + os_version = sys.argv[3] + + parameters = json.loads(os.environ["RUST_CACHE_PARAMETERS"]) + if "key" not in parameters: + parameters["key"] = target + else: + parameters["key"] += "-{}".format(target) + + if build_command == "cargo": + # If we're running cargo, we need to add the OS version to the cache. Otherwise things that link + # against system packages, like openssl, can break when we use the same cache across different + # versions of the runner OS. For example, when going from Ubuntu 20.04 to 22.04, we move from + # OpenSSL 1.1.x to 3.x. + parameters["key"] += "-{}".format(os_version) + else: + # Otherwise we want to include the `cross` binary's hash. The Docker images that `cross` + # uses can change when the binary is updated. This protects us from using the same cache + # inside containers that have changed. + parameters["key"] += "-cross-binary-hash-{}".format( + get_file_hash(build_command) + ) + + file = os.environ["GITHUB_OUTPUT"] + with open(file, "w") as f: + for key, value in parameters.items(): + f.write(f"{key}={value}") + + +def get_file_hash(build_command): + with open(build_command, "rb") as f: + file_hash = hashlib.sha256() + while chunk := f.read(65536): + file_hash.update(chunk) + return file_hash.hexdigest() + + +main() diff --git a/parse-rust-cache-parameters.py b/parse-rust-cache-parameters.py deleted file mode 100755 index bedc822..0000000 --- a/parse-rust-cache-parameters.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import json -import os -import sys - -target = sys.argv[1] -build_command = sys.argv[2] - -os_version = sys.argv[3] - -parameters = json.loads(os.environ["RUST_CACHE_PARAMETERS"]) -if "key" not in parameters: - parameters["key"] = target -else: - parameters["key"] = "{}-{}".format(parameters["key"], target) - -# If we're running cargo, we need to add the OS version to the cache. Otherwise things that link -# against system packages, like openssl, can break when we use the same cache across different -# versions of the runner OS. For example, when going from Ubuntu 20.04 to 22.04, we move from -# OpenSSL 1.1.x to 3.x. -if build_command == "cargo": - parameters["key"] = "{}-{}".format(parameters["key"], os_version) - -file = os.environ["GITHUB_OUTPUT"] -with open(file, "w") as f: - for key, value in parameters.items(): - f.write(f"{key}={value}")