Skip to content

Fix Windows CI downloads failing on offline CA revocation - #885

Open
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
ci-janitor/windows-curl-revocation
Open

Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
ci-janitor/windows-curl-revocation

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Windows legs fail at the download step, before any test runs. curl on the Windows runners uses schannel, and schannel refuses the TLS handshake when the CA's revocation (CRL/OCSP) server is unreachable:

curl: (35) schannel: next InitializeSecurityContext failed: CRYPT_E_REVOCATION_OFFLINE (0x80092013) - The revocation function was unable to check revocation because the revocation server was offline.

Seen in the last 3 days (2026-10-03 to 10-05):

run / job leg step
37314136032 / 111787133371 gradle 8.14.3 / jdk 21 / hosted / windows-latest Install Gradle 8.14.3 (services.gradle.org)
37317887822 / 111789147270 composer 2.2.30 / php 8.3 / windows-latest Download and verify composer (getcomposer.org)

Each one turns the whole run red and needs the matrix re-run (Gradle ~40 legs, Composer 19). Most of the other red Gradle/Composer runs in this window were PR bugs that failed every leg, or registry blips inside the tests. Those aren't touched here.

Separately, gradle-compatibility.yml still downloads Maven and Gradle with plain --retry 3. That doesn't retry a refused connection (exit 7) or a TLS error (exit 35). #868 fixed this in ci.yml and composer-compatibility.yml but missed this file, and the failed Install Gradle step above made exactly one attempt.

Root cause

schannel treats "revocation server unreachable" as a hard failure. The outage is on the CA's side, not the download host's, and can outlast curl's retry backoff (~31 s with --retry 5). So --retry-all-errors alone (#868) doesn't reliably cover it.

Fix

  • Add --ssl-revoke-best-effort to every download that runs on Windows legs and is checked against a digest:

    • ci.yml: the Windows vexctl download (pinned sha256), the Maven and Gradle installs in e2e (sha512/sha256)
    • composer-compatibility.yml: the phar and its .sha256sum (pinned + published sha256)
    • gradle-compatibility.yml: Maven and Gradle (sha512/sha256)

    The flag only skips the revocation check when the revocation server is unreachable. A certificate that is actually revoked still fails, and each body is checked against a digest right after. On other TLS backends (OpenSSL on Linux, macOS) curl accepts the flag and ignores it.

  • gradle-compatibility.yml: --retry 3 → --retry 5 --retry-all-errors, the same as Retry Composer/Maven/Gradle downloads on connect and TLS errors #868 and ci.yml's copy of these two steps.

Proof

  • curl 8.5.0 accepts --ssl-revoke-best-effort on Linux/OpenSSL (the flag dates from curl 7.70; the runners ship 8.x). I can't reproduce a schannel revocation outage from Linux. The flag's documented purpose is exactly this error.
  • The three workflow files still parse (PyYAML). actionlint 1.7.7 gives the same 9 findings before and after, all from the existing YAML anchors.
  • python3 -B -m unittest discover -s scripts/tests → 254 tests OK (it includes the parser for ci.yml's vlt rows).

Also in this PR: 4d8cad2 ports #878's fix, which routes the Gradle/JVM digests through utils::digest. main currently fails production_digests_go_through_the_helpers, which makes coverage/test/test-release red on every PR. The port becomes a no-op once #878 lands.

Where tests run

No test, job, matrix leg or check name changes. Only the flags on 11 download commands change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LS9AJhpVngXZxng8TRA2Kd


Note

Low Risk
Workflow-only curl flags and a behavior-preserving digest refactor; no runtime security weakening beyond skipping unreachable revocation checks on Windows CI downloads that remain hash-verified.

Overview
CI downloads on Windows were failing before tests ran when schannel could not reach the CA revocation server (CRYPT_E_REVOCATION_OFFLINE). Every digest-verified curl in ci.yml, composer-compatibility.yml, and gradle-compatibility.yml now passes --ssl-revoke-best-effort, which only relaxes the check when revocation is unreachable; revoked certs still fail and post-download hash checks are unchanged. On non-Windows runners the flag is ignored.

gradle-compatibility.yml Maven/Gradle installs are aligned with the other workflows: --retry 3 becomes --retry 5 --retry-all-errors so TLS and connection errors are retried like in #868.

Gradle/JVM patching routes SHA-1/SHA-256 hex output through crate::utils::digest in gradle_cache, jvm_jar, and Maven sidecar code instead of ad hoc sha1/sha2 + hex::encode, matching the production-digest helper policy (ported from #878).

Reviewed by Cursor Bugbot for commit 4d8cad2. Configure here.


Generated by Claude Code

Windows curl uses schannel, which fails the TLS handshake with
CRYPT_E_REVOCATION_OFFLINE (exit 35) whenever the CA's revocation
server can't be reached. That turned Gradle's Install step and
Composer's download step red before any test ran.
--ssl-revoke-best-effort skips the revocation check only when the
server is unreachable. A revoked certificate still fails, and every
one of these downloads is checked against a digest right afterwards.
On other TLS backends the flag does nothing.

gradle-compatibility.yml also still used plain `--retry 3`, which
doesn't retry refused connections or TLS errors. #868 fixed that
for ci.yml and composer-compatibility.yml but missed this file.

Claude-Session: https://claude.ai/code/session_01LS9AJhpVngXZxng8TRA2Kd
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko Mikola Lysenko (mikolalysenko) added the ci-janitor Opened by the CI janitor routine (flakes, redundant tests, CI perf) label Oct 5, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

utils::digest's production_digests_go_through_the_helpers fails on
main: three Gradle/JVM files compute digests inline. That makes
`coverage`, `test` and `test-release` red on every PR. #878 routes
them through utils::digest. This is the same change, ported so this
PR's CI is green. It becomes a no-op once #878 lands.

Claude-Session: https://claude.ai/code/session_01LS9AJhpVngXZxng8TRA2Kd
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

coverage failed on e1c6a50 in utils::digest::tests::production_digests_go_through_the_helpers (-p socket-patch-core --lib). That test is red on main itself: crawlers/gradle_cache.rs, patch/jvm_jar.rs and patch/sidecars/maven.rs compute digests inline. This PR only touches workflow files, so the failure isn't from this change. #878 fixes it, so 4d8cad2 ports that same +7/−13 change here. It becomes a no-op once #878 merges. Locally, the digest tests pass, cargo clippy -p socket-patch-core -- -D warnings is clean, and rustfmt is clean on the three files.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

gradle 8.14.3 / jdk 21 / vendor / ubuntu-latest failed on e1c6a50 in gradle_vendor_395_mixed_root (e2e_vendor_gradle_build). The test's Maven half (mvn dependency:build-classpath) couldn't resolve maven-dependency-plugin:3.5.0: Failed to read artifact descriptor for org.apache.maven:maven-artifact:jar:3.0, after a Downloading from central: …/maven-artifact-3.0.pom that never completed.

This failure isn't from this PR. The steps this PR changes (Install Maven 3.9.16 and Install Gradle 8.14.3) both passed in that job, and the failure is a download from Maven Central made inside the test itself. The same test failed the same way earlier today on an unrelated PR (run 37350580840, status code: 502 from repo.maven.apache.org). No fix exists yet. I'm leaving it for a separate ci-janitor run rather than widening this PR. The Gradle workflow is running again on 4d8cad2, which counts as the one re-run.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

CI status on 4d8cad2: every red or cancelled job (17 of them, across CI, Composer, npm, pnpm and Gradle) has the same GitHub annotation: The job was not acquired by Runner of type hosted even after multiple attempts. This is a hosted-runner capacity outage. No test or step in this PR failed. The scan performance job hit a runner shutdown (exit 143) partway through. Its re-run passed, and every scenario was unchanged or faster.

I re-ran the npm and pnpm workflows once already, and they lost their runners again. CI, Composer and Gradle (including the Windows legs this PR targets) need a re-run once runner capacity recovers. Nothing in the diff needs to change.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 4d8cad2. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 5, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Burn-down agent: labeled Ready for review at 4d8cad2 (4d8cad2802f99d65152574c4ad2060c42838f98c).

  • CI: 451/451 checks green on the head commit (6 skipped by matrix rule), after one re-run of the npm/pnpm jobs the GitHub Actions runner outage cancelled. No test failed.
  • Bugbot: reviewed 4d8cad2 (re-requested this run, because the last review covered e1c6a50) with no new issues, and no review threads are open.
  • Mergeable against main, with no conflicts.

Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-janitor Opened by the CI janitor routine (flakes, redundant tests, CI perf) Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants