Skip to content

ci: cache the pinned OPA binary and retry its download - #967

Merged
SandyChapman merged 3 commits into
mainfrom
ci-opa-download-resilience/schapman
Jul 29, 2026
Merged

ci: cache the pinned OPA binary and retry its download#967
SandyChapman merged 3 commits into
mainfrom
ci-opa-download-resilience/schapman

Conversation

@SandyChapman

@SandyChapman SandyChapman commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Build OPA policy WASM is a required job, and it has been failing on an unretried download from openpolicyagent.org — twice in three attempts on a single PR (#844), each time also taking down Python e2e tests, which needs its artifact:

Downloading OPA v1.8.0 from https://openpolicyagent.org/downloads/v1.8.0/opa_linux_amd64_static...
Failed to download OPA binary from ...
Unable to prepare OPA v1.8.0.

Two independent gaps, both one-liners.

1. The cache existed but CI never used it

script/build_policy_wasm.sh already prefers a cached binary at .cache/opa/<version>/ before downloading — but nothing in CI ever populated that directory, so every run depended on the network. The composite action now restores and saves it, keyed on the pinned version, so the download is only needed the first time a given version is seen.

The version is parsed out of the script rather than duplicated, so the cache key cannot drift from the pin. It parses rather than sources, because executing the script would build the WASM a second time — and before the cache is restored.

2. The download had no retry

Both curl calls now use --retry 3 --retry-delay 2 --retry-all-errors. --retry-all-errors is the important part: the observed failures were connection-level, which plain --retry does not cover.

Verification

  • Cold cache — downloads and populates .cache/opa/v1.8.0/opa_darwin_arm64_static
  • Warm cache — second run builds policy.wasm with no download at all
  • Retry flags — checked against an unreachable endpoint: 4 attempts (initial + 3) with backoff between
  • Regenerating policy.wasm leaves the tree clean, so output stays reproducible

Scope

Deliberately standalone rather than folded into #844, where I hit this — it is CI infrastructure unrelated to that change, and it benefits every PR.

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of OPA downloads by retrying transient network failures and enforcing connect/overall time limits for both the binary and its checksum.
  • Chores

    • Added CI caching for the pinned OPA binary to reduce repeated downloads and speed up policy WASM builds.

@github-actions github-actions Bot added the ci label Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 28033/35832 78.2% 62.7%
Integration Tests 16273/34550 47.1% 19.6%

@SandyChapman
SandyChapman marked this pull request as ready for review July 29, 2026 16:26
@SandyChapman
SandyChapman requested review from a team as code owners July 29, 2026 16:26
`Build OPA policy WASM` is a required job, and it has been failing on an
unretried download from openpolicyagent.org — twice in three attempts on a
single PR, each time taking `Python e2e tests` (which needs its artifact)
down with it.

`script/build_policy_wasm.sh` already prefers a cached binary at
`.cache/opa/<version>/` before downloading, but nothing in CI ever populated
that directory, so every run depended on the network. The composite action now
restores and saves it, keyed on the pinned version, so the fetch is only needed
the first time a version is seen. The version is parsed out of the script
rather than duplicated, so the key cannot drift from the pin; parsing (not
sourcing) because executing the script would build the WASM a second time, and
before the cache is restored.

Both `curl` calls also gain `--retry 3 --retry-delay 2 --retry-all-errors`.
`--retry-all-errors` matters here: the observed failures were connection-level,
which plain `--retry` does not cover.

Verified locally: cold cache downloads and populates `.cache/opa/<version>/`;
a second run builds with no download at all. The retry flags were checked
against an unreachable endpoint (4 attempts, backoff between). Regenerating
policy.wasm leaves the tree clean, so the output stays reproducible.

Signed-off-by: Sandy Chapman <schapman@nvidia.com>
@SandyChapman
SandyChapman force-pushed the ci-opa-download-resilience/schapman branch from 887edbc to ab4ca1d Compare July 29, 2026 16:27
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 24af4e4b-a550-4ab2-8e11-286e49baef2d

📥 Commits

Reviewing files that changed from the base of the PR and between 9ce6f6d and ecc5ab7.

📒 Files selected for processing (1)
  • script/build_policy_wasm.sh

📝 Walkthrough

Walkthrough

The build action resolves and caches the pinned OPA binary by runner and version, while the build script adds retries and timeouts to OPA binary and checksum downloads.

Changes

OPA WASM build dependency handling

Layer / File(s) Summary
Retryable OPA downloads
script/build_policy_wasm.sh
OPA binary and checksum downloads use retries, connection timeouts, and bounded total times while retaining existing error handling.
Cached OPA acquisition
.github/actions/build-policy-wasm/action.yaml
The action validates and exports OPA_VERSION, then caches .cache/opa using runner, architecture, and version data.

Suggested reviewers: mckornfield, a2bondar, aahunt-nv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: caching the pinned OPA binary and retrying its download.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci-opa-download-resilience/schapman

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/build_policy_wasm.sh`:
- Around line 115-119: Add --connect-timeout and --max-time options to both curl
invocations in the OPA download logic, including the call guarded by the shown
failure check. Keep the existing retry, output, and error-handling behavior
unchanged while ensuring connection and total transfer durations are bounded.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2ee500cd-ccb7-47e0-87f9-44046f38fa89

📥 Commits

Reviewing files that changed from the base of the PR and between 0739242 and ab4ca1d.

📒 Files selected for processing (2)
  • .github/actions/build-policy-wasm/action.yaml
  • script/build_policy_wasm.sh

Comment thread script/build_policy_wasm.sh Outdated
The retries added alongside the cache were only half a fix: with no
--max-time, a stalled connection consumes the entire job and the retries
never get a turn. The failure that motivated this work burned 5m40s before
giving up, which is consistent with exactly that.

Both curl calls now set --connect-timeout 15 with --max-time 120 for the
binary (~25x headroom for ~23 MB on a CI runner) and --max-time 60 for the
much smaller checksum. Retry, output and error handling are unchanged.

Validated: cold cache still downloads and populates .cache/opa/<version>/;
warm cache still skips the network entirely; and against a server that
accepts then never responds, each attempt is now cut short and retried
(curl exit 28) instead of hanging.

Signed-off-by: Sandy Chapman <schapman@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
script/build_policy_wasm.sh (1)

117-124: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Use exponential retry backoff.

--retry-delay 2 forces a fixed two-second delay and disables curl’s default exponential backoff. Remove it or replace it with an explicitly validated backoff strategy to match the PR objective. (curl.se)

Proposed fix
-  if ! curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \
+  if ! curl -fsSL --retry 3 --retry-all-errors \

Apply the same change to the checksum download.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/build_policy_wasm.sh` around lines 117 - 124, Update both curl
invocations in the OPA binary and checksum download flow to remove the fixed
--retry-delay 2 option, allowing curl’s default exponential retry backoff to
apply while preserving the existing retry counts and timeout settings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/build_policy_wasm.sh`:
- Around line 115-124: Update both curl download commands in the OPA binary and
checksum retrieval flow to cap the aggregate retry duration with
--retry-max-time, ensuring it fits within the surrounding 120-second subprocess
timeout. Keep the existing per-attempt --max-time values and retry behavior
unchanged.

---

Nitpick comments:
In `@script/build_policy_wasm.sh`:
- Around line 117-124: Update both curl invocations in the OPA binary and
checksum download flow to remove the fixed --retry-delay 2 option, allowing
curl’s default exponential retry backoff to apply while preserving the existing
retry counts and timeout settings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: df467e26-a56d-49e9-8d81-264770f22b6a

📥 Commits

Reviewing files that changed from the base of the PR and between ab4ca1d and 9ce6f6d.

📒 Files selected for processing (1)
  • script/build_policy_wasm.sh

Comment thread script/build_policy_wasm.sh Outdated

@crookedstorm crookedstorm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

--max-time bounds one transfer and resets on every retry, so adding it
alongside --retry 3 left the aggregate unbounded: worst case 4x120s + delays
= 486s for the binary and 246s for the checksum, 732s combined.

That collides with callers that impose their own ceiling.
embedded_pdp/policy_wasm.py runs this script under
DEFAULT_BUILD_TIMEOUT_SECONDS=120, so the subprocess would be killed
mid-retry — the retries could never even finish, which defeats the point of
adding them.

Both calls now also set --retry-max-time, and the per-attempt budgets are
sized to fit: binary <=45s aggregate + <=30s final attempt, checksum <=15s +
<=10s, so worst case is ~100s and the `opa build` still fits inside 120s.
The coupling to that caller is spelled out in a comment so the numbers are
not re-tuned in isolation.

Validated: cold download still succeeds (7s) and populates the cache; warm
cache still skips the network; and against a server that accepts then never
responds, the aggregate is cut at 62s instead of the ~126s the previous flags
would have allowed.

Signed-off-by: Sandy Chapman <schapman@nvidia.com>
@SandyChapman
SandyChapman enabled auto-merge July 29, 2026 17:17
@SandyChapman
SandyChapman added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit e521260 Jul 29, 2026
75 of 93 checks passed
@SandyChapman
SandyChapman deleted the ci-opa-download-resilience/schapman branch July 29, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants