diff --git a/.github/actions/build-policy-wasm/action.yaml b/.github/actions/build-policy-wasm/action.yaml index 863406d262..d7a44538bc 100644 --- a/.github/actions/build-policy-wasm/action.yaml +++ b/.github/actions/build-policy-wasm/action.yaml @@ -8,6 +8,33 @@ description: > runs: using: composite steps: + # build_policy_wasm.sh already prefers a cached binary at .cache/opa// before reaching + # out to openpolicyagent.org, but nothing ever populated that directory in CI, so every run + # depended on that download — and it has repeatedly failed, taking a required job down with it. + # Restoring the cache means the fetch is only needed the first time a pinned version is seen. + - name: Resolve pinned OPA version + id: opa + shell: bash + env: + REPO_ROOT: ${{ github.action_path }}/../../.. + run: | + # Parse rather than source: the script builds the WASM on execution, so sourcing it here + # would do the work twice (and before the cache is restored). + version="$(sed -n 's/^OPA_VERSION="\${OPA_VERSION:-\([^}]*\)}"/\1/p' "${REPO_ROOT}/script/build_policy_wasm.sh" | head -1)" + if [ -z "${version}" ]; then + echo "Could not parse the pinned OPA version from script/build_policy_wasm.sh" >&2 + echo "If the OPA_VERSION line moved, update this step — a wrong cache key silently disables caching." >&2 + exit 1 + fi + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "Pinned OPA version: ${version}" + + - name: Cache the pinned OPA binary + uses: actions/cache@v4 + with: + path: .cache/opa + key: opa-${{ runner.os }}-${{ runner.arch }}-${{ steps.opa.outputs.version }} + - name: Build policy WASM shell: bash env: diff --git a/script/build_policy_wasm.sh b/script/build_policy_wasm.sh index 90abf84943..dd93be78e5 100755 --- a/script/build_policy_wasm.sh +++ b/script/build_policy_wasm.sh @@ -112,12 +112,20 @@ download_opa() { url="${OPA_DOWNLOAD_BASE_URL}/${OPA_VERSION}/${asset}" sha_url="${url}.sha256" echo "Downloading OPA ${OPA_VERSION} from ${url}..." >&2 - if ! curl -fsSL "${url}" -o "${tmp_bin}"; then + # Bound both a single attempt (--max-time) and the whole retry window (--retry-max-time). + # --max-time RESETS on each retry, so without --retry-max-time the aggregate is unbounded: 4 + # attempts could run for minutes. That matters because callers impose their own ceiling — + # embedded_pdp/policy_wasm.py runs this script with DEFAULT_BUILD_TIMEOUT_SECONDS=120 — and would + # kill the build mid-retry. Budget: <=45s aggregate + <=30s final attempt here, <=15s + <=10s for + # the checksum, leaving headroom for the `opa build` itself inside 120s. + if ! curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \ + --connect-timeout 10 --max-time 30 --retry-max-time 45 "${url}" -o "${tmp_bin}"; then echo "Failed to download OPA binary from ${url}." >&2 print_opa_help "${asset}" exit 1 fi - if ! curl -fsSL "${sha_url}" -o "${tmp_sha}"; then + if ! curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \ + --connect-timeout 10 --max-time 10 --retry-max-time 15 "${sha_url}" -o "${tmp_sha}"; then echo "Failed to download OPA checksum from ${sha_url}." >&2 print_opa_help "${asset}" exit 1