Skip to content

Commit 34a5814

Browse files
authored
fix(ci): improve setup_aws.sh retry resilience and add download jitter (mongodb#732)
## Problem CI setup tasks are failing intermittently during retries due to: 1. **Thundering herd**: When CI retries trigger, multiple tasks start simultaneously and overwhelm external download endpoints 2. **Weak retry params**: `setup_aws.sh` was missed in PR mongodb#720 and had weaker retry parameters (3s delay, 180s timeout vs 10s/600s) 3. **No error visibility**: `--fail` flag hides HTTP error responses, making debugging difficult 4. **External API dependency**: Fetching `stable.txt` from `dl.k8s.io` adds an extra failure point 5. **Single endpoint**: No fallback if `dl.k8s.io` is temporarily unavailable (503 errors) ## Solution ### 1. Shared `curl_with_retry()` function Created a shared wrapper in `scripts/funcs/install` with: - **Random jitter (0-30s)** before downloads to spread out concurrent requests - **Consistent retry params**: 5 retries, 10s delay, 600s timeout - **`--fail-with-body`** instead of `--fail` to show HTTP error responses in logs - **`SKIP_DOWNLOAD_JITTER=1`** env var to disable jitter for local development ### 2. Pin kubectl version - Added `KUBECTL_VERSION=v1.35.0` to `root-context` (like `HELM_VERSION`) - Eliminates external API call to `stable.txt` endpoint - Deterministic builds with same kubectl version every time ### 3. CDN fallback for kubectl - If `dl.k8s.io` fails, automatically tries `cdn.dl.k8s.io` directly - Provides resilience against temporary endpoint outages (503 errors) ### 4. Remove redundant shellcheck setup - Removed `setup_shellcheck.sh` - pre-commit already handles shellcheck via `.pre-commit-config.yaml`
1 parent b7e7163 commit 34a5814

17 files changed

Lines changed: 95 additions & 65 deletions

.evergreen-functions.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,6 @@ functions:
128128
working_dir: src/github.com/mongodb/mongodb-kubernetes
129129
binary: scripts/evergreen/setup_kubectl.sh
130130

131-
setup_shellcheck:
132-
command: subprocess.exec
133-
type: setup
134-
params:
135-
working_dir: src/github.com/mongodb/mongodb-kubernetes
136-
add_to_path:
137-
- ${workdir}/bin
138-
binary: scripts/evergreen/setup_shellcheck.sh
139-
140131
setup_aws: &setup_aws
141132
command: subprocess.exec
142133
type: setup

.evergreen.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ tasks:
327327
- func: clone
328328
- func: python_venv
329329
- func: download_kube_tools
330-
- func: setup_shellcheck
331330
- command: github.generate_token
332331
params:
333332
expansion_name: GH_TOKEN
@@ -637,7 +636,6 @@ task_groups:
637636
- func: clone
638637
- func: python_venv
639638
- func: download_kube_tools
640-
- func: setup_shellcheck
641639
tasks:
642640
- lint_repo
643641
- unit_tests_golang

scripts/dev/contexts/root-context

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,6 @@ export RELEASE_INITIAL_VERSION="1.3.0"
154154
export CLUSTER_TYPE=kind
155155
export OPERATOR_CLUSTER_SCOPED=false
156156

157-
# for downloading helm binaries
157+
# for downloading helm and kubectl binaries
158158
export HELM_VERSION="v3.19.4"
159+
export KUBECTL_VERSION="v1.35.0"

scripts/dev/setup_evg_host.sh

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,20 @@ download_kind() {
4545
}
4646

4747
download_kubectl() {
48-
kubectl_version=$(curl --retry 5 -Ls https://dl.k8s.io/release/stable.txt)
49-
echo "Downloading kubectl ${kubectl_version}..."
50-
kubectl_version=$(echo "${kubectl_version}" | tail -n1 | tr -d '\n')
51-
52-
curl --retry 5 -LOs "https://dl.k8s.io/release/${kubectl_version}/bin/linux/${ARCH}/kubectl"
53-
chmod +x kubectl
48+
# Use pinned version (KUBECTL_VERSION from root-context)
49+
# Falls back to fetching stable.txt if KUBECTL_VERSION is not set
50+
local version="${KUBECTL_VERSION:-}"
51+
if [[ -z "${version}" ]]; then
52+
version=$(curl_with_retry -Ls https://dl.k8s.io/release/stable.txt | tail -n1 | tr -d '\n')
53+
fi
54+
55+
download_kubectl_binary "${version}" "${ARCH}"
5456
sudo mv kubectl /usr/local/bin/kubectl
5557
}
5658

5759
download_helm() {
58-
echo "Downloading helm..."
59-
curl -s -o helm.tar.gz -L "https://get.helm.sh/helm-${HELM_VERSION}-linux-${ARCH}tar.gz"
60-
tar -xf helm.tar.gz 2>/dev/null
61-
sudo mv linux-"${ARCH}"helm /usr/local/bin/helm
62-
rm helm.tar.gz
60+
download_helm_binary "${HELM_VERSION}" "${ARCH}"
61+
sudo mv linux-"${ARCH}"/helm /usr/local/bin/helm
6362
rm -rf linux-"${ARCH}/"
6463
}
6564

scripts/evergreen/lint_code.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
set -Eeou pipefail
33

44
source scripts/dev/set_env_context.sh
5+
source scripts/funcs/install
56

67
# Set required version
78
required_version="v2.0.2"
89

910
# Install or update golangci-lint if not installed or version is incorrect
1011
if ! [[ -x "$(command -v golangci-lint)" ]]; then
1112
echo "Installing/updating golangci-lint to version ${required_version}..."
12-
curl --retry 5 --retry-delay 3 --retry-all-errors --fail --show-error --max-time 180 -sSL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$(go env GOPATH)"/bin "${required_version}"
13+
curl_with_retry -sSL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$(go env GOPATH)"/bin "${required_version}"
1314
else
1415
echo "golangci-lint is already installed"
1516
fi

scripts/evergreen/setup_aws.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ install_aws_cli_binary() {
1919
cd "${temp_dir}"
2020

2121
echo "Downloading AWS CLI v2 for ${aws_arch}..."
22-
curl --retry 5 --retry-delay 3 --retry-all-errors --fail --show-error --max-time 180 -s "https://awscli.amazonaws.com/awscli-exe-linux-${aws_arch}.zip" -o "awscliv2.zip"
22+
curl_with_retry -s "https://awscli.amazonaws.com/awscli-exe-linux-${aws_arch}.zip" -o "awscliv2.zip"
2323

2424
unzip -q awscliv2.zip
2525
sudo ./aws/install --update

scripts/evergreen/setup_gcloud_cli.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
set -Eeou pipefail
33

44
source scripts/dev/set_env_context.sh
5+
source scripts/funcs/install
56

6-
curl --retry 5 --retry-delay 3 --retry-all-errors --fail --show-error --max-time 180 --silent -LO "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz"
7+
curl_with_retry --silent -LO "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz"
78
tar xf google-cloud-cli-linux-x86_64.tar.gz -C "${workdir}"
89
"${workdir}"/google-cloud-sdk/install.sh --quiet
910
source "${workdir}/google-cloud-sdk/path.bash.inc"

scripts/evergreen/setup_jq.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ source scripts/funcs/install
1212
jq_arch=$(detect_architecture "jq")
1313
echo "Detected architecture: ${jq_arch}"
1414

15-
download_and_install_binary "${PROJECT_DIR:-${workdir}}/bin" jq "https://github.com/stedolan/jq/releases/download/jq-1.8.1/jq-linux-${jq_arch}"
15+
# Use jqlang/jq (canonical repo) directly to avoid redirect from stedolan/jq
16+
download_and_install_binary "${PROJECT_DIR:-${workdir}}/bin" jq "https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-linux-${jq_arch}"

scripts/evergreen/setup_kind.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ latest_version="v0.29.0"
1515
if [[ "${arch_suffix}" == "amd64" || "${arch_suffix}" == "arm64" ]]; then
1616
mkdir -p "${PROJECT_DIR}/bin/"
1717
echo "Saving kind to ${PROJECT_DIR}/bin"
18-
curl --retry 5 --retry-delay 5 --retry-all-errors --fail --show-error --max-time 600 -L "https://github.com/kubernetes-sigs/kind/releases/download/${latest_version}/kind-${os}-${arch_suffix}" -o kind
18+
curl_with_retry -L "https://github.com/kubernetes-sigs/kind/releases/download/${latest_version}/kind-${os}-${arch_suffix}" -o kind
1919

2020
chmod +x kind
2121
sudo mv kind "${PROJECT_DIR}/bin"

scripts/evergreen/setup_kubectl.sh

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,16 @@ bindir="${PROJECT_DIR}/bin"
1212
tmpdir="${PROJECT_DIR}/tmp"
1313
mkdir -p "${bindir}" "${tmpdir}"
1414

15-
kubectl_version=$(curl --retry 5 --retry-delay 5 --retry-all-errors --fail --max-time 120 -Ls https://dl.k8s.io/release/stable.txt)
16-
echo "Downloading kubectl ${kubectl_version} for ${ARCH}"
17-
kubectl_version=$(echo "${kubectl_version}" | tail -n1 | tr -d '\n')
18-
19-
curl --retry 5 --retry-delay 5 --retry-all-errors --fail --show-error --max-time 600 -LOs "https://dl.k8s.io/release/${kubectl_version}/bin/linux/${ARCH}/kubectl"
20-
chmod +x kubectl
15+
# Use pinned version from root-context (no external API call needed)
16+
download_kubectl_binary "${KUBECTL_VERSION}" "${ARCH}"
2117
echo "kubectl version --client"
2218
./kubectl version --client
2319
mv kubectl "${bindir}"
2420

25-
echo "Downloading helm ${HELM_VERSION} for ${ARCH}"
26-
helm_archive="${tmpdir}/helm.tgz"
27-
curl --retry 5 --retry-delay 5 --retry-all-errors --fail --show-error --max-time 600 -s "https://get.helm.sh/helm-${HELM_VERSION}-linux-${ARCH}.tar.gz" --output "${helm_archive}"
21+
pushd "${tmpdir}" > /dev/null
22+
download_helm_binary "${HELM_VERSION}" "${ARCH}"
23+
mv "linux-${ARCH}/helm" "${bindir}"
24+
rm -rf "linux-${ARCH}/"
25+
popd > /dev/null
2826

29-
tar xfz "${helm_archive}" -C "${tmpdir}" &> /dev/null
30-
mv "${tmpdir}/linux-${ARCH}/helm" "${bindir}"
3127
"${bindir}"/helm version

0 commit comments

Comments
 (0)