From 2d66fdb33f0dbb6bcb7770300c170c26a13023c7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 7 Jun 2026 14:49:28 +0000 Subject: [PATCH] Pin downloaded OpenSSL artifact mtimes to the artifact's creation time openssl-sys's build script registers cargo:rerun-if-changed on the OpenSSL include directory, which cargo evaluates by mtime. On Windows and macOS the prebuilt OpenSSL is downloaded and extracted fresh on every CI run, so identical headers get new mtimes and openssl-sys (and everything downstream: openssl, cryptography-openssl, cryptography-cffi) recompiles every run despite a warm rust-cache. The Linux jobs don't have this problem because their OpenSSL builds are restored by actions/cache, which preserves mtimes. Set every extracted file's mtime to the artifact's created_at: an unchanged artifact always looks the same to cargo, while a rebuilt artifact gets a new timestamp and correctly triggers a rebuild. https://claude.ai/code/session_014StKTjk7GBcVdiWKimEsQb --- .github/actions/windows-tests/action.yml | 10 ++++++++ .github/bin/pin_artifact_mtimes.py | 32 ++++++++++++++++++++++++ .github/workflows/ci.yml | 8 ++++++ 3 files changed, 50 insertions(+) create mode 100644 .github/bin/pin_artifact_mtimes.py diff --git a/.github/actions/windows-tests/action.yml b/.github/actions/windows-tests/action.yml index d856c7f5de29..89c745c6a593 100644 --- a/.github/actions/windows-tests/action.yml +++ b/.github/actions/windows-tests/action.yml @@ -42,6 +42,7 @@ runs: shell: bash - uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 + id: ossl-download with: repo: pyca/infra workflow: build-windows-openssl.yml @@ -50,6 +51,15 @@ runs: name: "openssl-${{ inputs.openssl-name }}" path: "C:/openssl-${{ inputs.openssl-name }}/" github_token: ${{ github.token }} + # The fresh extraction gives the headers new mtimes on every run, which + # invalidates openssl-sys's cargo fingerprint (it registers + # rerun-if-changed on the include dir) despite identical content. + - name: Pin OpenSSL artifact mtimes + run: python .github/bin/pin_artifact_mtimes.py "C:/openssl-${OPENSSL_NAME}" "${ARTIFACT_CREATED_AT}" + env: + OPENSSL_NAME: ${{ inputs.openssl-name }} + ARTIFACT_CREATED_AT: ${{ fromJSON(steps.ossl-download.outputs.artifacts)[0].created_at }} + shell: bash - name: Configure run: | echo "OPENSSL_DIR=C:/openssl-${OPENSSL_NAME}" >> $GITHUB_ENV diff --git a/.github/bin/pin_artifact_mtimes.py b/.github/bin/pin_artifact_mtimes.py new file mode 100644 index 000000000000..e452084527d1 --- /dev/null +++ b/.github/bin/pin_artifact_mtimes.py @@ -0,0 +1,32 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +# Set every file in a downloaded artifact to the artifact's own creation +# time. openssl-sys's build script registers cargo:rerun-if-changed on the +# OpenSSL include directory, and cargo evaluates that by mtime, so a +# freshly extracted artifact with identical content would otherwise +# invalidate the cargo cache on every CI run. Using the artifact's +# created_at means an unchanged artifact always looks the same, while a +# rebuilt artifact gets a new timestamp and correctly triggers a rebuild. + +import datetime +import os +import sys + + +def main(root: str, created_at: str) -> None: + mtime = datetime.datetime.fromisoformat( + created_at.replace("Z", "+00:00") + ).timestamp() + count = 0 + for dirpath, _, filenames in os.walk(root): + for filename in filenames: + path = os.path.join(dirpath, filename) + os.utime(path, (mtime, mtime)) + count += 1 + print(f"pinned {count} files in {root} to {created_at}") + + +if __name__ == "__main__": + main(sys.argv[1], sys.argv[2]) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5469e9c75457..3710395a8886 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -315,6 +315,7 @@ jobs: uses: ./.github/actions/fetch-vectors - uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 + id: ossl-download with: repo: pyca/infra workflow: build-macos-openssl.yml @@ -323,6 +324,13 @@ jobs: name: openssl-macos-universal2 path: "../openssl-macos-universal2/" github_token: ${{ secrets.GITHUB_TOKEN }} + # The fresh extraction gives the headers new mtimes on every run, which + # invalidates openssl-sys's cargo fingerprint (it registers + # rerun-if-changed on the include dir) despite identical content. + - name: Pin OpenSSL artifact mtimes + run: python .github/bin/pin_artifact_mtimes.py ../openssl-macos-universal2/ "$ARTIFACT_CREATED_AT" + env: + ARTIFACT_CREATED_AT: ${{ fromJSON(steps.ossl-download.outputs.artifacts)[0].created_at }} - name: Build nox environment run: | OPENSSL_DIR=$(readlink -f ../openssl-macos-universal2/) \