Skip to content

ci(wheels): cache SHA-verified source distfiles + vcpkg assets to survive upstream host outages #974

Description

@MAfarrag

Context

The release wheel-bundling workflow (bundle-pypi-wheels.yml) builds GDAL from source on Linux and via
vcpkg on win_arm64. Both paths re-download every dependency on every run: the Linux from-source build
pulls ~26 SHA256-pinned tarballs from ~30 upstream hosts, and the win_arm64 vcpkg build re-fetches every
port's source. A single 503/429/outage from any one host (e.g. the DKRZ libaec host, lcms2, libwebp,
openjpeg) fails the whole build — this repeatedly broke releases during GitHub/CDN incidents.

Delivered on branch ci/cache-source-distfiles (PR #970).

Problem / Current Behaviour

The existing compiled-stack cache stores built binaries and is deliberately gated off the release
(workflow_run) path to avoid a cache-poisoning-to-PyPI vector — so releases always cold-build and
re-download everything
, with no resilience against a flaky upstream host. There was no caching of the
downloaded source itself.

Affected locations

File Symbol Notes
.github/workflows/bundle-pypi-wheels.yml glibc / musl / win_arm64 build jobs new restore/save cache steps
ci/source-build/config.sh fetch() cache-aware download + SHA-verify + persist
ci/source-build/build-gdal-stack.sh DISTFILES_DIR plumbing export dir through the /host mount
.gitignore ignore the new working dirs

Proposed Solution

Cache the downloaded source (not binaries), which is safe to keep on the release path because every
artifact is re-verified after restore:

  • Linux source-distfile cache: fetch() reuses a SHA256-matching cached tarball, else wgets it,
    verifies either way, and persists the verified tarball to a DISTFILES_DIR plumbed through
    cibuildwheel's /host mount. Arch-independent shared key seeds all four glibc/musl jobs.
  • win_arm64 vcpkg downloaded-assets cache over C:\vcpkg\downloads (vcpkg SHA512-verifies on use).
  • Un-gated off workflow_run: per-tarball SHA256/SHA512 re-verification means a stale or tampered
    cache entry can never place non-pin bytes into a published wheel, so the optimization is release-safe.
  • Cache-integrity guards: refresh on SHA mismatch (not only when absent) so a stale same-name distfile
    self-heals; split each cache into restore + save gated on success() and a compiled/installed
    cache miss, so neither a failed mid-fetch nor a build served entirely from the compiled cache can seed
    the write-once key with a partial or empty set.
  • Key the vcpkg downloads cache on the ci/vcpkg-ports/** overlay so the libaec redirect rotates the key.

Out of Scope

  • The compiled-stack / vcpkg-installed caches keep their existing workflow_run gating (unchanged).
  • No change to which wheels are built or published; the DISTFILES_DIR-unset path is byte-for-byte the
    old download-only behaviour.

Effort Estimate

Size: M
Rationale: touched four CI-infra files with subtle GitHub-Actions cache semantics (write-once keys,
restore-keys prefix fallback, restore/save split) and required a live dry-run to prove cache hits.

Definition of Done

  • Linux distfile cache restores and reuses tarballs with zero re-downloads on a warm run
    (proven: run 31634004496 — restore=1, compiled-miss=1, 26 using cached, 0 downloads)
  • Caches are release-safe (SHA re-verify after restore; verified in review)
  • A failed/partial fetch or a compiled-cache-hit run cannot seed the immutable key with a bad set
  • win_arm64 vcpkg downloads cache wired over C:\vcpkg\downloads, keyed on the ports overlay
  • lint / pre-commit / SonarCloud / analyze CI checks green on the PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    devinstallation, cienhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions