Commit f9082e461e for openssl.org

commit f9082e461e6f395c5dfde19ace61d92f62fae5e0
Author: Dmitry Misharov <dmitry@openssl.org>
Date:   Mon Oct 12 08:57:03 2026 +0200

    CI: retry environment steps before failing the job

    The VS2013 toolchain image pull, the cross-compile apt installs and the
    DJGPP PPA fail transiently and turn a push red with nothing in the log
    about the change. Try each up to three times, 30 seconds apart. When all
    attempts fail, report it as an environment failure in an error annotation
    and the job summary, so it is not mistaken for a test failure.

    Assisted-by: Claude:claude-opus-5-5
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Merge-date: Wed Oct 21 17:07:51 2026
    Merged-from: https://github.com/openssl/openssl/pull/33198

diff --git a/.gitattributes b/.gitattributes
index a292d2b25d..99f380c30e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -17,3 +17,6 @@ krb5                                    export-ignore
 pyca-cryptography                       export-ignore
 dev                                     export-ignore
 gost-engine                             export-ignore
+
+# Run on Windows runners, which check text files out with CRLF.
+/.github/retry text eol=lf
diff --git a/.github/retry b/.github/retry
new file mode 100755
index 0000000000..47c32ab2fc
--- /dev/null
+++ b/.github/retry
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Run a command that only fails because of the runner or the network, such as a
+# package install or an image pull, up to three times, 30 seconds apart. When
+# every attempt fails, report an environment failure in an error annotation and
+# the job summary, so it is not mistaken for a test failure.
+#
+# Usage: .github/retry COMMAND [ARGUMENT...]
+# Commands that must be retried together: retry sh -c '... && ...'
+
+attempts=3
+
+attempt=1
+while :; do
+    "$@" && exit 0
+    [ "$attempt" -ge $attempts ] && break
+    attempt=$((attempt + 1))
+    sleep 30
+done
+
+cmd="$*"
+cmd=$(printf '%s' "${cmd#sh -c }" | head -n 1 | cut -c 1-100)
+msg="'$cmd' failed $attempts times; this is a runner or network problem, not a test failure"
+echo "::error title=Environment failure::$msg"
+echo "Environment failure: $msg" >> "$GITHUB_STEP_SUMMARY"
+exit 1
diff --git a/.github/workflows/avx512-sde.yml b/.github/workflows/avx512-sde.yml
index db108cdc09..656568ccf2 100644
--- a/.github/workflows/avx512-sde.yml
+++ b/.github/workflows/avx512-sde.yml
@@ -131,7 +131,7 @@ jobs:
         if: github.repository == 'openssl/openssl'
         run: |
           $installer = "nasm-3.01-installer-x64.exe"
-          Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+          Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
           $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
           $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
           if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
@@ -149,7 +149,7 @@ jobs:
         if: github.repository == 'openssl/openssl'
         run: |
           mkdir C:\jom
-          Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+          Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
           $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
           $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
           if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e048b9b0cc..5d780f11a5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -785,8 +785,9 @@ jobs:
       run: |
         mkdir nss
         cd nss
-        git clone --depth 1 --branch NSS_3_112_3_RTM https://github.com/nss-dev/nss.git
-        hg clone https://hg.mozilla.org/projects/nspr -r NSPR_4_36_BRANCH
+        # A failed clone leaves a partial directory behind; remove it before each attempt.
+        "$GITHUB_WORKSPACE"/.github/retry sh -c 'rm -rf nss && git clone --depth 1 --branch NSS_3_112_3_RTM https://github.com/nss-dev/nss.git'
+        "$GITHUB_WORKSPACE"/.github/retry sh -c 'rm -rf nspr && hg clone https://hg.mozilla.org/projects/nspr -r NSPR_4_36_BRANCH'
         cd nss
         USE_64=1 make nss_build_all
         USE_64=1 make install
diff --git a/.github/workflows/compiler-zoo.yml b/.github/workflows/compiler-zoo.yml
index eb475a573b..6c759a0142 100644
--- a/.github/workflows/compiler-zoo.yml
+++ b/.github/workflows/compiler-zoo.yml
@@ -61,14 +61,12 @@ jobs:
         gcc: [gcc-9, gcc-10, gcc-11, gcc-12, gcc-13, gcc-14]
     runs-on: ubuntu-24.04
     steps:
-    - name: install packages
-      run: |
-        sudo apt-get update
-        sudo apt-get -y install ${{ matrix.gcc }}
     - uses: actions/checkout@v6
       with:
         persist-credentials: false
         ref: ${{ github.event.inputs.head_sha || github.sha }}
+    - name: install packages
+      run: .github/retry sh -c "sudo apt-get update && sudo apt-get -y install ${{ matrix.gcc }}"
     - name: checkout fuzz/corpora submodule
       run: git submodule update --init --depth 1 fuzz/corpora
     - name: config
@@ -115,8 +113,8 @@ jobs:
     - name: checkout fuzz/corpora submodule
       run: git submodule update --init --depth 1 fuzz/corpora
     - name: pull the VS2013 toolchain image
-      shell: cmd
-      run: docker pull %IMAGE%
+      shell: bash
+      run: bash .github/retry docker pull "$IMAGE"
     - name: config
       run: |
         $chain = @(
@@ -160,18 +158,17 @@ jobs:
         clang: [clang-11, clang-12, clang-13, clang-14, clang-15, clang-16, clang-17, clang-18, clang-19, clang-20, clang-21]
     runs-on: ubuntu-22.04
     steps:
+    - uses: actions/checkout@v6
+      with:
+        persist-credentials: false
+        ref: ${{ github.event.inputs.head_sha || github.sha }}
     - name: install packages
       run: |
         set -euo pipefail
         VERSION=$(awk -F- '{print $NF}' <<< ${{ matrix.clang }})
-        wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
+        .github/retry sudo wget -qO /etc/apt/trusted.gpg.d/apt.llvm.org.asc https://apt.llvm.org/llvm-snapshot.gpg.key
         echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-$VERSION main" | sudo tee -a /etc/apt/sources.list
-        sudo apt-get update || true
-        sudo apt-get -y install ${{ matrix.clang }}
-    - uses: actions/checkout@v6
-      with:
-        persist-credentials: false
-        ref: ${{ github.event.inputs.head_sha || github.sha }}
+        .github/retry sh -c "sudo apt-get update; sudo apt-get -y install ${{ matrix.clang }}"
     - name: checkout fuzz/corpora submodule
       run: git submodule update --init --depth 1 fuzz/corpora
     - name: config
diff --git a/.github/workflows/cross-compiles.yml b/.github/workflows/cross-compiles.yml
index e43f4c0429..25d43a438d 100644
--- a/.github/workflows/cross-compiles.yml
+++ b/.github/workflows/cross-compiles.yml
@@ -347,33 +347,32 @@ jobs:
         ]
     runs-on: ubuntu-latest
     steps:
+    - uses: actions/checkout@v6
+      with:
+        persist-credentials: false
     - name: install package repository
       if: matrix.platform.ppa != ''
-      run: |
-        sudo add-apt-repository ppa:${{ matrix.platform.ppa }}
+      run: .github/retry sudo add-apt-repository ppa:${{ matrix.platform.ppa }}
     - name: install packages (GCC)
       if: matrix.platform.compiler != 'clang'
       run: |
-        sudo apt-get update
-        sudo apt-get -yq --allow-unauthenticated --allow-downgrades --allow-remove-essential --allow-change-held-packages install \
+        .github/retry sh -c "sudo apt-get update &&
+          sudo apt-get -yq --allow-unauthenticated --allow-downgrades --allow-remove-essential --allow-change-held-packages install \
             gcc-${{ matrix.platform.arch }} \
-            ${{ matrix.platform.libs }}
+            ${{ matrix.platform.libs }}"
     - name: install packages (Clang)
       if: matrix.platform.compiler == 'clang'
       run: |
-        sudo apt-get update
-        sudo apt-get -yq --allow-unauthenticated --allow-downgrades --allow-remove-essential --allow-change-held-packages install \
+        .github/retry sh -c "sudo apt-get update &&
+          sudo apt-get -yq --allow-unauthenticated --allow-downgrades --allow-remove-essential --allow-change-held-packages install \
             clang \
             binutils-${{ matrix.platform.arch }} \
             gcc-${{ matrix.platform.arch }} \
-            ${{ matrix.platform.libs }}
+            ${{ matrix.platform.libs }}"
         # Detect sysroot: Ubuntu <=22.04 uses .../sys-root, 24.04+ installs directly.
         SYSROOT=/usr/${{ matrix.platform.arch }}/sys-root
         [ -d "$SYSROOT" ] || SYSROOT=/usr/${{ matrix.platform.arch }}
         echo "CROSS_SYSROOT=$SYSROOT" >> $GITHUB_ENV
-    - uses: actions/checkout@v6
-      with:
-        persist-credentials: false
     - name: checkout fuzz/corpora submodule
       run: git submodule update --init --depth 1 fuzz/corpora

diff --git a/.github/workflows/os-zoo.yml b/.github/workflows/os-zoo.yml
index e0a9397780..81eb5db7f6 100644
--- a/.github/workflows/os-zoo.yml
+++ b/.github/workflows/os-zoo.yml
@@ -106,9 +106,10 @@ jobs:
             # Debian 11 LTS ended 2026-08-31: bullseye-security metadata is
             # expired and its pool has been pruned.  Use the snapshot repos
             # the image pins itself.
-            install: |
+            setup: |
               sed -i -e 's|^deb |#deb |' \
-                    -e 's|^# deb http://snapshot|deb http://snapshot|' /etc/apt/sources.list && \
+                    -e 's|^# deb http://snapshot|deb http://snapshot|' /etc/apt/sources.list
+            install: |
               apt-get -o Acquire::Check-Valid-Until=false update && \
               apt-get install -y gcc make perl
           - image: docker.io/library/debian:12
@@ -132,10 +133,10 @@ jobs:
           - image: docker.io/library/fedora:45
             install: dnf install -y gcc make perl-core
           - image: docker.io/library/centos:8
-            install: |
+            setup: |
               sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \
-              sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && \
-              dnf install -y gcc make perl-core
+              sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
+            install: dnf install -y gcc make perl-core
           - image: docker.io/rockylinux/rockylinux:8
             install: dnf install -y gcc make perl-core
           - image: docker.io/rockylinux/rockylinux:9
@@ -149,8 +150,13 @@ jobs:
       with:
         persist-credentials: false
         ref: ${{ github.event.inputs.head_sha || github.sha }}
+    - name: prepare package sources
+      if: matrix.zoo.setup != ''
+      run: ${{ matrix.zoo.setup }}
     - name: install packages
-      run: ${{ matrix.zoo.install }}
+      env:
+        INSTALL: ${{ matrix.zoo.install }}
+      run: .github/retry sh -c "$INSTALL"
     - name: config
       run: ./config
     - name: config dump
@@ -220,7 +226,7 @@ jobs:
     - name: install nasm
       run: |
         $installer = "nasm-3.01-installer-x64.exe"
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
         $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
@@ -229,7 +235,7 @@ jobs:
     - name: install jom
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -252,7 +258,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: get cpu info
       working-directory: _build
       run: |
@@ -287,7 +293,7 @@ jobs:
     - name: install jom
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
diff --git a/.github/workflows/run_quic_interop.yml b/.github/workflows/run_quic_interop.yml
index f7fca6f373..d91b0bfe7a 100644
--- a/.github/workflows/run_quic_interop.yml
+++ b/.github/workflows/run_quic_interop.yml
@@ -76,18 +76,20 @@ jobs:
           repository: 'quic-interop/quic-interop-runner'
           fetch-depth: 0
           persist-credentials: false
+      - uses: actions/checkout@v6
+        with:
+          path: .openssl
+          sparse-checkout: .github/retry
+          sparse-checkout-cone-mode: false
+          persist-credentials: false
       - name: Install python requirements
-        run: |
-          for i in {1..3}; do pip install -r requirements.txt && break; sleep 10; done
+        run: .openssl/.github/retry pip install -r requirements.txt
       - name: Add tshark repo
-        run: |
-          for i in {1..3}; do sudo add-apt-repository ppa:wireshark-dev/stable && break; sleep 10; done
+        run: .openssl/.github/retry sudo add-apt-repository ppa:wireshark-dev/stable
       - name: Update apt repos
-        run: |
-          for i in {1..3}; do sudo apt-get update && break; sleep 10; done
+        run: .openssl/.github/retry sudo apt-get update
       - name: Install tshark
-        run: |
-          for i in {1..3}; do sudo apt-get install -y tshark && break; sleep 10; done
+        run: .openssl/.github/retry sudo apt-get install -y tshark
       - name: Patch implementations file
         run: |
           jq '. + {
@@ -134,18 +136,20 @@ jobs:
           repository: 'quic-interop/quic-interop-runner'
           fetch-depth: 0
           persist-credentials: false
+      - uses: actions/checkout@v6
+        with:
+          path: .openssl
+          sparse-checkout: .github/retry
+          sparse-checkout-cone-mode: false
+          persist-credentials: false
       - name: Install python requirements
-        run: |
-          for i in {1..3}; do pip install -r requirements.txt && break; done
+        run: .openssl/.github/retry pip install -r requirements.txt
       - name: Add tshark repo
-        run: |
-          for i in {1..3}; do sudo add-apt-repository ppa:wireshark-dev/stable && break; done
+        run: .openssl/.github/retry sudo add-apt-repository ppa:wireshark-dev/stable
       - name: Update apt repos
-        run: |
-          for i in {1..3}; do sudo apt-get update && break; done
+        run: .openssl/.github/retry sudo apt-get update
       - name: Install tshark
-        run: |
-          for i in {1..3}; do sudo apt-get install -y tshark && break; done
+        run: .openssl/.github/retry sudo apt-get install -y tshark
       - name: Patch implementations file
         run: |
           jq '. + {
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 79e4d3a770..407dedfc24 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -60,7 +60,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         $installer = "nasm-3.01-installer-${{ matrix.platform.arch == 'x86' && 'x86' || 'x64' }}.exe"
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
         $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
@@ -77,7 +77,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -107,7 +107,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: Gather openssl version info
       working-directory: _build
       run: |
@@ -166,7 +166,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -194,7 +194,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: get cpu info
       working-directory: _build
       continue-on-error: true
@@ -221,7 +221,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -276,7 +276,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -304,7 +304,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: get cpu info
       working-directory: _build
       continue-on-error: true
@@ -335,7 +335,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         $installer = "nasm-3.01-installer-x64.exe"
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
         $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
diff --git a/.github/workflows/windows_comp.yml b/.github/workflows/windows_comp.yml
index 349ed24b89..4f938c9dd4 100644
--- a/.github/workflows/windows_comp.yml
+++ b/.github/workflows/windows_comp.yml
@@ -32,7 +32,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         $installer = "nasm-3.01-installer-x64.exe"
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
         $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
@@ -49,7 +49,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -97,7 +97,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: get cpu info
       working-directory: _build
       continue-on-error: true
@@ -124,7 +124,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         $installer = "nasm-3.01-installer-x64.exe"
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/$installer" -OutFile $installer -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).$installer
         $actual = (Get-FileHash $installer -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for $installer (expected $expected, got $actual)" }
@@ -141,7 +141,7 @@ jobs:
       if: github.repository == 'openssl/openssl'
       run: |
         mkdir C:\jom
-        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe
+        Invoke-WebRequest -Uri "https://openssl-library.org/ci-deps/jom-1.1.7.exe" -OutFile C:\jom\jom.exe -MaximumRetryCount 3 -RetryIntervalSec 30
         $expected = (Get-Content "$env:GITHUB_WORKSPACE\.github\ci-deps.json" -Raw | ConvertFrom-Json).'jom-1.1.7.exe'
         $actual = (Get-FileHash C:\jom\jom.exe -Algorithm SHA256).Hash
         if ($actual -ne $expected) { throw "SHA256 mismatch for jom.exe (expected $expected, got $actual)" }
@@ -189,7 +189,7 @@ jobs:
     - name: download coreinfo
       run: |
         mkdir _build\coreinfo
-        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip"
+        Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Coreinfo.zip" -outfile "_build\coreinfo\Coreinfo.zip" -MaximumRetryCount 3 -RetryIntervalSec 30
     - name: get cpu info
       working-directory: _build
       continue-on-error: true