From 5d351c73dd5b2ad1c3371fac3d80e1dc000b2043 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 5 Oct 2026 14:46:21 +0000 Subject: [PATCH] Retry pinned tool downloads on connect/TLS errors The Composer phar, Maven and Gradle downloads used `curl --retry 3`, which only retries timeouts and HTTP 408/429/5xx. A refused connection (exit 7) or a TLS handshake failure (exit 35, e.g. Windows schannel CRYPT_E_REVOCATION_OFFLINE) fails the step on the first try. Both happened on 2026-10-05 in composer-compatibility legs on PRs that don't touch Composer. Use the repo's existing `--retry 5 --retry-all-errors` pattern (the vexctl downloads in ci.yml). Every one of these downloads is checked against a pinned or published digest right after, so retrying any error can't let a bad body through. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01M7YkVUqGY83YbfQPipKzk5 --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/composer-compatibility.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01c91c0cc..3f3d41296 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1350,8 +1350,8 @@ jobs: run: | major="${MAVEN_VERSION%%.*}" url="https://archive.apache.org/dist/maven/maven-${major}/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" - curl -fsSL --retry 3 "$url" -o "$RUNNER_TEMP/maven.tgz" - curl -fsSL --retry 3 "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" + curl -fsSL --retry 5 --retry-all-errors "$url" -o "$RUNNER_TEMP/maven.tgz" + curl -fsSL --retry 5 --retry-all-errors "$url.sha512" -o "$RUNNER_TEMP/maven.sha512" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha512((p/"maven.tgz").read_bytes()).hexdigest() == (p/"maven.sha512").read_text().split()[0]' # Python accepts native Windows paths for both archive and destination. python -m tarfile -e "$RUNNER_TEMP/maven.tgz" "$RUNNER_TEMP" @@ -1366,8 +1366,8 @@ jobs: GRADLE_VERSION: ${{ matrix.gradle }} run: | url="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" - curl -fsSL --retry 3 "$url" -o "$RUNNER_TEMP/gradle.zip" - curl -fsSL --retry 3 "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" + curl -fsSL --retry 5 --retry-all-errors "$url" -o "$RUNNER_TEMP/gradle.zip" + curl -fsSL --retry 5 --retry-all-errors "$url.sha256" -o "$RUNNER_TEMP/gradle.sha256" python -c 'import hashlib, pathlib, os; p=pathlib.Path(os.environ["RUNNER_TEMP"]); assert hashlib.sha256((p/"gradle.zip").read_bytes()).hexdigest() == (p/"gradle.sha256").read_text().strip()' unzip -q "$RUNNER_TEMP/gradle.zip" -d "$RUNNER_TEMP" launcher="$RUNNER_TEMP/gradle-${GRADLE_VERSION}/bin/gradle" diff --git a/.github/workflows/composer-compatibility.yml b/.github/workflows/composer-compatibility.yml index 1b5d7a287..a7f52a09d 100644 --- a/.github/workflows/composer-compatibility.yml +++ b/.github/workflows/composer-compatibility.yml @@ -133,8 +133,8 @@ jobs: fi phar="$dir/composer-$COMPOSER_RELEASE.phar" base="https://getcomposer.org/download/$COMPOSER_RELEASE/composer.phar" - curl -fsSL --retry 3 -o "$phar" "$base" - published="$(curl -fsSL --retry 3 "$base.sha256sum" | cut -d' ' -f1)" + curl -fsSL --retry 5 --retry-all-errors -o "$phar" "$base" + published="$(curl -fsSL --retry 5 --retry-all-errors "$base.sha256sum" | cut -d' ' -f1)" # shellcheck disable=SC2016 # $argv is PHP, not shell actual="$(php -r 'echo hash_file("sha256", $argv[1]);' "$phar")" if [ "$actual" != "$COMPOSER_PHAR_SHA256" ] || [ "$actual" != "$published" ]; then