Skip to content

Commit 7e706d0

Browse files
Implement retry mechanisms for network download functionality (#199)
* write a custom curl retry method * retry SDK install * retry windows install * check windows download for corruption and ensure file length is valid * account for partially installed sdks * add retry logic to install-vsb.ps1 * remove file with retry on windows
1 parent 721a365 commit 7e706d0

File tree

3 files changed

+422
-64
lines changed

3 files changed

+422
-64
lines changed

.github/workflows/scripts/install-and-build-with-sdk.sh

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,91 @@ log() { printf -- "** %s\n" "$*" >&2; }
1717
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
1818
fatal() { error "$@"; exit 1; }
1919

20+
# Retry configuration
21+
CURL_MAX_RETRIES=5
22+
CURL_RETRY_DELAY=5
23+
CURL_TIMEOUT=300
24+
25+
SDK_INSTALL_MAX_RETRIES=5
26+
SDK_INSTALL_INITIAL_RETRY_DELAY=10
27+
28+
curl_with_retry() {
29+
local attempt=1
30+
local exit_code=0
31+
32+
while [ $attempt -le $CURL_MAX_RETRIES ]; do
33+
if [ $attempt -gt 1 ]; then
34+
log "Retry attempt $attempt of $CURL_MAX_RETRIES after ${CURL_RETRY_DELAY}s delay..."
35+
sleep $CURL_RETRY_DELAY
36+
fi
37+
38+
# Run curl with connection timeout and max time limits
39+
if curl --connect-timeout 30 --max-time $CURL_TIMEOUT --retry 3 --retry-delay 2 --retry-max-time 60 "$@"; then
40+
return 0
41+
else
42+
exit_code=$?
43+
log "curl failed with exit code $exit_code on attempt $attempt"
44+
fi
45+
46+
attempt=$((attempt + 1))
47+
done
48+
49+
error "curl failed after $CURL_MAX_RETRIES attempts"
50+
return $exit_code
51+
}
52+
53+
swift_sdk_install_with_retry() {
54+
local swift_executable="$1"
55+
local sdk_url="$2"
56+
local checksum="$3"
57+
local sdk_type="$4"
58+
59+
local attempt=1
60+
local retry_delay=$SDK_INSTALL_INITIAL_RETRY_DELAY
61+
62+
# Extract SDK name from URL for checking if already installed
63+
local sdk_filename
64+
sdk_filename=$(basename "$sdk_url")
65+
local sdk_name="${sdk_filename%.tar.gz}"
66+
67+
while [ $attempt -le $SDK_INSTALL_MAX_RETRIES ]; do
68+
if [ $attempt -gt 1 ]; then
69+
log "Retry attempt $attempt of $SDK_INSTALL_MAX_RETRIES for ${sdk_type} SDK installation after ${retry_delay}s delay..."
70+
71+
# Before retrying, check if SDK was partially installed and remove it
72+
log "Checking for partially installed SDK..."
73+
if "$swift_executable" sdk list 2>/dev/null | grep -q "^${sdk_name}"; then
74+
log "Found partially installed SDK, attempting to remove it..."
75+
if "$swift_executable" sdk remove "$sdk_name" 2>/dev/null; then
76+
log "Successfully removed partially installed SDK"
77+
else
78+
log "Warning: Failed to remove partially installed SDK, continuing anyway..."
79+
fi
80+
fi
81+
82+
sleep $retry_delay
83+
fi
84+
85+
log "Attempt $attempt: Installing ${sdk_type} SDK from ${sdk_url}"
86+
87+
if "$swift_executable" sdk install "$sdk_url" --checksum "$checksum"; then
88+
log "${sdk_type} SDK installed successfully"
89+
return 0
90+
else
91+
local exit_code=$?
92+
log "swift sdk install failed with exit code $exit_code on attempt $attempt"
93+
94+
# Exponential backoff: double the delay each time
95+
retry_delay=$((retry_delay * 2))
96+
fi
97+
98+
attempt=$((attempt + 1))
99+
done
100+
101+
error "${sdk_type} SDK installation failed after $SDK_INSTALL_MAX_RETRIES attempts"
102+
return 1
103+
}
104+
20105
# Parse command line options
21106
INSTALL_ANDROID=false
22107
INSTALL_STATIC_LINUX=false
@@ -125,7 +210,7 @@ find_latest_swift_version() {
125210
log "Fetching releases from swift.org API..."
126211

127212
local releases_json
128-
releases_json=$(curl -fsSL "${SWIFT_API_INSTALL_ROOT}/releases.json") || fatal "Failed to fetch Swift releases"
213+
releases_json=$(curl_with_retry -fsSL "${SWIFT_API_INSTALL_ROOT}/releases.json") || fatal "Failed to fetch Swift releases"
129214

130215
# Find all releases that start with the minor version (e.g, "6.1")
131216
# Sort them and get the latest one
@@ -212,7 +297,7 @@ find_latest_sdk_snapshot() {
212297
log "Fetching development snapshots from swift.org API..."
213298

214299
local sdk_json
215-
sdk_json=$(curl -fsSL "${SWIFT_API_INSTALL_ROOT}/dev/${version}/${sdk_name}-sdk.json") || fatal "Failed to fetch ${sdk_name}-sdk development snapshots"
300+
sdk_json=$(curl_with_retry -fsSL "${SWIFT_API_INSTALL_ROOT}/dev/${version}/${sdk_name}-sdk.json") || fatal "Failed to fetch ${sdk_name}-sdk development snapshots"
216301

217302
# Extract the snapshot tag from the "dir" field of the first (newest) element
218303
local snapshot_tag
@@ -400,16 +485,16 @@ download_and_verify() {
400485
local temp_sig="${output_file}.sig"
401486

402487
log "Downloading ${url}"
403-
curl -fsSL "$url" -o "$output_file"
488+
curl_with_retry -fsSL "$url" -o "$output_file"
404489

405490
log "Downloading signature"
406-
curl -fsSL "$sig_url" -o "$temp_sig"
491+
curl_with_retry -fsSL "$sig_url" -o "$temp_sig"
407492

408493
log "Setting up GPG for verification"
409494
local gnupghome
410495
gnupghome="$(mktemp -d)"
411496
export GNUPGHOME="$gnupghome"
412-
curl -fSsL https://swift.org/keys/all-keys.asc | zcat -f | gpg --import - >/dev/null 2>&1
497+
curl_with_retry -fSsL https://swift.org/keys/all-keys.asc | zcat -f | gpg --import - >/dev/null 2>&1
413498

414499
log "Verifying signature"
415500
if gpg --batch --verify "$temp_sig" "$output_file" >/dev/null 2>&1; then
@@ -445,7 +530,7 @@ download_and_extract_toolchain() {
445530

446531
# Check if toolchain is available
447532
local http_code
448-
http_code=$(curl -sSL --head -w "%{http_code}" -o /dev/null "$toolchain_url")
533+
http_code=$(curl_with_retry -sSL --head -w "%{http_code}" -o /dev/null "$toolchain_url")
449534
if [[ "$http_code" == "404" ]]; then
450535
log "Toolchain not found: ${toolchain_filename}"
451536
log "Exiting workflow..."
@@ -556,11 +641,7 @@ install_android_sdk() {
556641
local android_sdk_filename="${android_sdk_bundle_name}.tar.gz"
557642
local sdk_url="${ANDROID_SDK_DOWNLOAD_ROOT}/${ANDROID_SDK_TAG}/${android_sdk_filename}"
558643

559-
log "Running: ${SWIFT_EXECUTABLE_FOR_ANDROID_SDK} sdk install ${sdk_url} --checksum ${ANDROID_SDK_CHECKSUM}"
560-
561-
if "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK" sdk install "$sdk_url" --checksum "$ANDROID_SDK_CHECKSUM"; then
562-
log "✅ Android Swift SDK installed successfully"
563-
else
644+
if ! swift_sdk_install_with_retry "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK" "$sdk_url" "$ANDROID_SDK_CHECKSUM" "Android Swift"; then
564645
fatal "Failed to install Android Swift SDK"
565646
fi
566647

@@ -579,7 +660,7 @@ install_android_sdk() {
579660
if [[ ! -d "${ANDROID_NDK_HOME:-}" ]]; then
580661
# permit the "--android-ndk" flag to override the default
581662
local android_ndk_version="${ANDROID_NDK_VERSION:-r27d}"
582-
curl -fsSL -o ndk.zip --retry 3 https://dl.google.com/android/repository/android-ndk-"${android_ndk_version}"-"$(uname -s)".zip
663+
curl_with_retry -fsSL -o ndk.zip https://dl.google.com/android/repository/android-ndk-"${android_ndk_version}"-"$(uname -s)".zip
583664
command -v unzip >/dev/null || install_package unzip
584665
unzip -q ndk.zip
585666
rm ndk.zip
@@ -602,11 +683,7 @@ install_static_linux_sdk() {
602683
local static_linux_sdk_filename="${STATIC_LINUX_SDK_TAG}_static-linux-0.0.1.artifactbundle.tar.gz"
603684
local sdk_url="${STATIC_LINUX_SDK_DOWNLOAD_ROOT}/${STATIC_LINUX_SDK_TAG}/${static_linux_sdk_filename}"
604685

605-
log "Running: ${SWIFT_EXECUTABLE_FOR_STATIC_LINUX_SDK} sdk install ${sdk_url} --checksum ${STATIC_LINUX_SDK_CHECKSUM}"
606-
607-
if "$SWIFT_EXECUTABLE_FOR_STATIC_LINUX_SDK" sdk install "$sdk_url" --checksum "$STATIC_LINUX_SDK_CHECKSUM"; then
608-
log "✅ Static Linux Swift SDK installed successfully"
609-
else
686+
if ! swift_sdk_install_with_retry "$SWIFT_EXECUTABLE_FOR_STATIC_LINUX_SDK" "$sdk_url" "$STATIC_LINUX_SDK_CHECKSUM" "Static Linux Swift"; then
610687
fatal "Failed to install Static Linux Swift SDK"
611688
fi
612689

@@ -625,11 +702,7 @@ install_wasm_sdk() {
625702
local wasm_sdk_filename="${WASM_SDK_TAG}_wasm.artifactbundle.tar.gz"
626703
local sdk_url="${WASM_SDK_DOWNLOAD_ROOT}/${WASM_SDK_TAG}/${wasm_sdk_filename}"
627704

628-
log "Running: ${SWIFT_EXECUTABLE_FOR_WASM_SDK} sdk install ${sdk_url} --checksum ${WASM_SDK_CHECKSUM}"
629-
630-
if "$SWIFT_EXECUTABLE_FOR_WASM_SDK" sdk install "$sdk_url" --checksum "$WASM_SDK_CHECKSUM"; then
631-
log "✅ Swift SDK for Wasm installed successfully"
632-
else
705+
if ! swift_sdk_install_with_retry "$SWIFT_EXECUTABLE_FOR_WASM_SDK" "$sdk_url" "$WASM_SDK_CHECKSUM" "Swift Wasm"; then
633706
fatal "Failed to install Swift SDK for Wasm"
634707
fi
635708

0 commit comments

Comments
 (0)