Skip to content

fix(build): bound retries for Bicep downloads - #13291

Merged
nicolejms merged 6 commits into
mainfrom
nicolejms-fix-bicep-download-failure
Oct 14, 2026
Merged

nicolejms merged 6 commits into
mainfrom
nicolejms-fix-bicep-download-failure

Conversation

@nicolejms

Copy link
Copy Markdown
Contributor

Summary

Extend the Bicep installer's download retry budget without retrying permanent errors or whole CI jobs. Add offline regression tests to make test.

Reason for change

Fixes #13141

In run 36507816832, three noncloud jobs exhausted five retries while the Bicep release download returned HTTP 500. That policy allowed about 31 seconds of retry delays. #13189 added --retry-all-errors, which covers more error types but does not extend the HTTP 500 retry budget.

This change gives each request a shared 300-second budget and up to 10 retries. Delays double from 1 second to a 60-second cap. Connection setup has a 15-second timeout. Each transfer has a timeout of at most 60 seconds, reduced to the remaining budget.

Retry HTTP 408, 429, 500, 502, 503, and 504, DNS and connection failures, timeouts, incomplete transfers, and dropped connections. Other failures, including HTTP 403/404, certificate errors, and local write errors, stop at once. The same budget covers a mix of HTTP and transport failures. Checksum validation still occurs before the installed binary is replaced.

A small Bash policy is needed here: curl's built-in --retry omits dropped connections, while --retry-all-errors also retries permanent HTTP and certificate errors. The Go retry package cannot be used by this standalone Bash installer. A verified download cache is a possible later change, but needs separate cache storage and trust rules. Neither approach can guarantee success during a long upstream outage.

How to test

  • bash -n build/scripts/install-bicep.sh build/scripts/install-bicep_test.sh - passed.
  • bash build/scripts/install-bicep_test.sh - passed. Covers all retryable status classes, permanent errors, six HTTP 500 responses followed by success, increasing delays, shared time budget, attempt timeout, retry-count limit, latest-version resolution, partial output replacement, and checksum validation.
  • PowerShell: for ($i = 1; $i -le 20; $i++) { bash build/scripts/install-bicep_test.sh; if ($LASTEXITCODE -ne 0) { throw "Bicep test run $i failed" }; Write-Output "PASS: $i/20" } - passed, all 20 runs.
  • shellcheck --rcfile=.github/linters/.shellcheckrc build/scripts/install-bicep.sh build/scripts/install-bicep_test.sh - passed with ShellCheck v0.11.0.
  • pnpm exec markdownlint-cli2 docs/contributing/contributing-code/contributing-code-shell-and-make/README.md --config .github/linters/.markdownlint-cli2.yaml - passed.
  • pnpm exec markdown-table-formatter docs/contributing/contributing-code/contributing-code-shell-and-make/README.md --check - passed.
  • cspell lint --config .github/linters/.cspell.yml --no-progress docs/contributing/contributing-code/contributing-code-shell-and-make/README.md - passed.
  • git diff --check - passed.

Also passed a local HTTP server check with real curl: six HTTP 500 responses then success; HTTP 404 with one attempt; HTTP 500 then HTTP 404 with no further attempt; a connection dropped during transfer then success with complete output; and persistent HTTP 500 stopped at the retry-count limit. The fixture replaces only the URL/protocol and sleep so the test needs no public service or long waits. The committed tests use a fake clock to check the time limits.

make test-install-bicep could not run because GNU Make is not installed on this Windows host. Its exact Bash test command ran directly, including the 20-run loop. One full run takes about 19 seconds on this host, so the repeat check uses the 20-run minimum, not the 100-run target for fast tests. Earlier 100-run loops were stopped before completion and are not counted as passes. The full Go and cluster-based functional suites were not run; no Go code or cluster behavior changed.

File change summary

File Summary of change
build/scripts/install-bicep.sh Add selective, bounded retries; keep latest-version resolution and checksum checks.
build/scripts/install-bicep_test.sh Add offline tests for retry policy, timeout limits, and install safety.
build/test.mk Add test-install-bicep to the unit-test prerequisites.
docs/contributing/contributing-code/contributing-code-shell-and-make/README.md Document the retry limits and test command.

nicolejms and others added 2 commits October 14, 2026 10:05
Allow transient GitHub failures to recover beyond the old five-retry
budget. Limit each request to 300 seconds and up to ten retries, with
connection and transfer timeouts. Stop on permanent HTTP and certificate
errors, but keep retries for dropped connections.

Add offline regression tests to make test and document the policy.

Fixes: #13141

Signed-off-by: nicolejms <nicolej@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: nicolejms <nicolej@microsoft.com>
Use Bash line counts to reduce process starts, and support shasum when sha256sum is not installed.

Signed-off-by: nicolejms <nicolej@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@nicolejms
nicolejms requested review from a team as code owners October 14, 2026 17:26
Copilot AI balanced review requested due to automatic review settings October 14, 2026 17:26
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added the pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable label Oct 14, 2026
@nicolejms nicolejms added the pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work label Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Unit Tests

    2 files  ±0    448 suites  ±0   15m 42s ⏱️ + 3m 0s
7 319 tests ±0  7 317 ✅ ±0  2 💤 ±0  0 ❌ ±0 
8 752 runs  ±0  8 750 ✅ ±0  2 💤 ±0  0 ❌ ±0 

Results for commit 5ac8441. ± Comparison against base commit ffd051c.

♻️ This comment has been updated with latest results.

Copilot AI 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.

🟢 Approval recommended

The retry policy is bounded, selectively handles transient failures, and has comprehensive offline regression coverage.

0 open findings

What changed in this PR

Adds bounded, selective retries to make Bicep downloads more resilient without retrying permanent failures.

Changes:

  • Implements a shared retry deadline, backoff, and selective error handling.
  • Adds offline regression tests and integrates them into make test.
  • Documents the retry policy and test command.
File Description
build/​scripts/​install-bicep.sh Implements bounded download retries and preserves checksum safety.
build/​scripts/​install-bicep_test.sh Tests retry classes, limits, timeouts, and installation safety.
build/​test.mk Adds the installer tests to the unit-test target.
docs/​contributing/​contributing-code/​contributing-code-shell-and-make/​README.md Documents retry behavior and verification.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Seed a stale installed binary so Linux does not reuse a valid checksum fixture. Assert that the corrupt download is requested and rejected, and that the stale binary is preserved.

Signed-off-by: nicolejms <nicolej@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@nicolejms

nicolejms commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Fixed the Linux checksum fixture in a2f61d9. The test previously left a valid installed binary in place, so Linux reused it and never attempted the corrupt download. It now starts with a stale binary and checks that one download occurs, checksum verification fails, and the old binary remains unchanged.

Reproduced the failure under Ubuntu before the change. After the change, make -f build/test.mk test-install-bicep passed under Ubuntu, the full shell suite passed 100/100 Linux runs, and bash build/scripts/install-bicep_test.sh passed on Windows. ShellCheck, Bash syntax, and git diff --check passed. The new commit is GPG-signed and signed off. The full unit-test workflow will run on the pushed commit.

CI result: run 38608297263 passed the full Run make test (unit tests) step. The later CLI integration step was canceled when the job reached its 30-minute limit. The unit-test failure is fixed; the overall job is not green because of that later timeout.

@nicolejms
nicolejms enabled auto-merge October 14, 2026 17:45
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.56%. Comparing base (ffd051c) to head (5ac8441).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13291      +/-   ##
==========================================
- Coverage   60.57%   60.56%   -0.01%     
==========================================
  Files         771      771              
  Lines       45608    45608              
==========================================
- Hits        27625    27624       -1     
- Misses      17983    17984       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread build/scripts/install-bicep.sh Resolved
Comment thread build/scripts/install-bicep.sh Resolved
@github-actions github-actions Bot added pr:waiting-for-author The author needs to address human review feedback or human-endorsed inline feedback and removed pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable labels Oct 14, 2026
Retry HTTP/2 stream resets and honor Retry-After seconds and HTTP dates within the existing shared deadline. Add coverage for server waits, redirect headers, date parsing, and bounded stream-reset retries.

Signed-off-by: nicolejms <nicolej@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable and removed pr:waiting-for-author The author needs to address human review feedback or human-endorsed inline feedback labels Oct 14, 2026
@radius-functional-tests

radius-functional-tests Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository radius-project/radius
Commit ref 5ac8441
Unique ID func63504b0a25
Image tag pr-func63504b0a25
  • Dapr: 1.14.4
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-func63504b0a25
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-func63504b0a25
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-func63504b0a25
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func63504b0a25
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func63504b0a25
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

@github-actions github-actions Bot added pr:review-approved Required reviews are approved; checks may still be pending and removed pr:waiting-for-review A reviewer owns the next action; required approval is pending or unverifiable labels Oct 14, 2026
@nicolejms
nicolejms added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit 507806b Oct 14, 2026
94 checks passed
@nicolejms
nicolejms deleted the nicolejms-fix-bicep-download-failure branch October 14, 2026 21:08
@github-actions github-actions Bot removed the pr:review-approved Required reviews are approved; checks may still be pending label Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:standard Ongoing maintenance, minor improvements, documentation updates, and routine development work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scheduled functional test (noncloud) failed - Run ID: 36507816832

3 participants