Skip to content

Commit 47c0e06

Browse files
fix(ci): authenticate the nightly dependency-bump API calls (#11042)
The "Bump Backend dependencies" workflow has failed every night for the last two weeks. #11012 fixed one cause (repos renamed under localai-org); what is left is rate limiting. bump_deps.sh fans out to ~25 parallel matrix jobs that each query api.github.com anonymously. Anonymous calls are capped at 60/hour per source IP and GitHub-hosted runners egress through shared NAT addresses, so a random handful of jobs draw HTTP 403 and die at curl exit 22 with an empty response. Last night that hit ggml-org/whisper.cpp and mudler/depth-anything.cpp -- both public and resolvable, nothing wrong with either pin. Route every bump script through a shared gh_curl helper that sends GITHUB_TOKEN when present (1000/hour instead of 60) and retries transient failures, including the 403s that plain --retry ignores. The helper suppresses xtrace around the call so the Authorization header cannot land in a public job log. bump_docs.sh had a sharper version of the same bug: it piped an unchecked response into `jq -r .tag_name`, so a throttled request resolved to the string "null" and would have been published as the docs version. It now refuses to write anything it cannot resolve to a tag. Verified locally by running all four scripts end to end against their real upstreams: correct SHAs/tags written, exit 0; a nonexistent repo now fails with a named diagnostic instead of a bare exit 22 and leaves the pinned file untouched; the token is absent from the xtrace output; and the scripts still work unauthenticated. Assisted-by: Claude:opus-4.8 [Claude Code] Co-authored-by: localai-org-maint-bot <306269227+localai-org-maint-bot@users.noreply.github.com>
1 parent 5c96e09 commit 47c0e06

7 files changed

Lines changed: 82 additions & 8 deletions

File tree

.github/bump_deps.sh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/bin/bash
22
set -xe
3+
4+
source "$(dirname "${BASH_SOURCE[0]}")/gh_curl.sh"
5+
36
REPO=$1
47
BRANCH=$2
58
VAR=$3
@@ -9,10 +12,11 @@ if [ -z "$FILE" ]; then
912
FILE="Makefile"
1013
fi
1114

12-
# -L so a renamed/transferred upstream repo (GitHub answers 301) still
13-
# resolves instead of handing us the redirect body, and -f so an HTTP error
14-
# aborts the run rather than letting an error page reach sed below.
15-
LAST_COMMIT=$(curl -sfL -H "Accept: application/vnd.github.VERSION.sha" "https://api.github.com/repos/$REPO/commits/$BRANCH")
15+
# gh_curl follows redirects so a renamed/transferred upstream repo (GitHub
16+
# answers 301) still resolves, and fails on HTTP errors rather than letting an
17+
# error page reach sed below. `|| true` keeps a failed lookup from aborting the
18+
# script at exit 22 with no context — the SHA guard below reports it instead.
19+
LAST_COMMIT=$(gh_curl -H "Accept: application/vnd.github.VERSION.sha" "https://api.github.com/repos/$REPO/commits/$BRANCH" || true)
1620

1721
# Guard the sed input: anything that is not a bare 40-hex SHA (an API error
1822
# body, an empty response) would otherwise be spliced into the Makefile pin —

.github/bump_docs.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
#!/bin/bash
22
set -xe
3+
4+
source "$(dirname "${BASH_SOURCE[0]}")/gh_curl.sh"
5+
36
REPO=$1
47

5-
LATEST_TAG=$(curl -s "https://api.github.com/repos/$REPO/releases/latest" | jq -r '.tag_name')
8+
LATEST_TAG=$(gh_curl -H "Accept: application/vnd.github+json" \
9+
"https://api.github.com/repos/$REPO/releases/latest" | jq -r '.tag_name')
10+
11+
# jq prints the string "null" for a missing key, so a throttled or otherwise
12+
# unexpected API response would otherwise be published as the docs version.
13+
if [ -z "$LATEST_TAG" ] || [ "$LATEST_TAG" = "null" ]; then
14+
echo "Refusing to bump docs version: could not resolve the latest release tag for $REPO." >&2
15+
exit 1
16+
fi
617

718
cat <<< $(jq ".version = \"$LATEST_TAG\"" docs/data/version.json) > docs/data/version.json

.github/bump_vllm_metal.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
# darwin build can only use the exact vLLM version vllm-metal supports, so it may
1212
# lag the Linux pin (requirements-cublas13-after.txt) until vllm-metal catches up.
1313
set -xe
14+
15+
source "$(dirname "${BASH_SOURCE[0]}")/gh_curl.sh"
16+
1417
REPO=$1 # vllm-project/vllm-metal
1518
FILE=$2 # backend/python/vllm/install.sh
1619
VAR=$3 # VLLM_METAL_VERSION (used for the workflow's output file names)
@@ -22,12 +25,12 @@ fi
2225

2326
# vllm-metal ships frequent dev releases, all flagged as non-prerelease, so
2427
# /releases/latest returns the newest one (with its cp312 wheel asset).
25-
LATEST_TAG=$(curl -sS -H "Accept: application/vnd.github+json" \
28+
LATEST_TAG=$(gh_curl -H "Accept: application/vnd.github+json" \
2629
"https://api.github.com/repos/$REPO/releases/latest" \
2730
| python3 -c "import json,sys; print(json.load(sys.stdin)['tag_name'])")
2831

2932
# The coupled vLLM source version lives in vllm-metal's installer at that tag.
30-
NEW_VLLM_VERSION=$(curl -fsSL \
33+
NEW_VLLM_VERSION=$(gh_curl \
3134
"https://raw.githubusercontent.com/$REPO/$LATEST_TAG/install.sh" \
3235
| grep -oE 'vllm_v="[0-9]+\.[0-9]+\.[0-9]+"' | head -1 | cut -d'"' -f2)
3336

.github/bump_vllm_wheel.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
# vars in Makefiles; this script handles the two-value rewrite specific to the
1010
# vLLM requirements file.
1111
set -xe
12+
13+
source "$(dirname "${BASH_SOURCE[0]}")/gh_curl.sh"
14+
1215
REPO=$1 # vllm-project/vllm
1316
FILE=$2 # backend/python/vllm/requirements-cublas13-after.txt
1417
VAR=$3 # VLLM_VERSION (used for output file names so the workflow can read them)
@@ -19,7 +22,7 @@ if [ -z "$FILE" ] || [ -z "$REPO" ] || [ -z "$VAR" ]; then
1922
fi
2023

2124
# /releases/latest returns the most recent non-prerelease tag.
22-
LATEST_TAG=$(curl -sS -H "Accept: application/vnd.github+json" \
25+
LATEST_TAG=$(gh_curl -H "Accept: application/vnd.github+json" \
2326
"https://api.github.com/repos/$REPO/releases/latest" \
2427
| python3 -c "import json,sys; print(json.load(sys.stdin)['tag_name'])")
2528

.github/gh_curl.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
# Shared curl wrapper for the nightly dependency-bump scripts.
3+
#
4+
# The bump workflow fans out to ~25 parallel matrix jobs, each querying
5+
# api.github.com. Anonymous API calls are capped at 60/hour per source IP and
6+
# GitHub-hosted runners egress through shared NAT addresses, so a random handful
7+
# of jobs were getting rate-limited (HTTP 403 -> curl exit 22, empty response)
8+
# every single night. Authenticating with GITHUB_TOKEN lifts the ceiling to
9+
# 1000/hour; the retries absorb whatever transient blips remain.
10+
11+
# Wraps curl with GitHub auth (when a token is present) plus retry/timeout
12+
# hardening. Callers pass their own headers and the URL.
13+
gh_curl() {
14+
# The bump scripts run under `set -x`; without this the Authorization header
15+
# would be echoed into the job log on every call.
16+
local had_xtrace=0
17+
case "$-" in
18+
*x*) had_xtrace=1; set +x ;;
19+
esac
20+
21+
local args=(
22+
--silent --show-error --location --fail
23+
# --retry-all-errors so 403 rate-limit responses are retried too; plain
24+
# --retry only covers 408/429/5xx. curl honours Retry-After when sent.
25+
--retry 5 --retry-delay 3 --retry-all-errors
26+
--connect-timeout 15 --max-time 60
27+
)
28+
if [ -n "${GITHUB_TOKEN:-}" ]; then
29+
args+=(--header "Authorization: Bearer ${GITHUB_TOKEN}")
30+
fi
31+
32+
curl "${args[@]}" "$@"
33+
local rc=$?
34+
35+
if [ "$had_xtrace" -eq 1 ]; then
36+
set -x
37+
fi
38+
return $rc
39+
}

.github/workflows/bump_deps.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ jobs:
115115
- uses: actions/checkout@v7
116116
- name: Bump dependencies 🔧
117117
id: bump
118+
env:
119+
# This job fans out to ~25 parallel matrix entries, all querying
120+
# api.github.com from runner IPs that share the 60/hour anonymous
121+
# rate limit. Authenticating raises it to 1000/hour, which is what
122+
# kept a random handful of these red every night.
123+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
118124
run: |
119125
bash .github/bump_deps.sh ${{ matrix.repository }} ${{ matrix.branch }} ${{ matrix.variable }} ${{ matrix.file }}
120126
{
@@ -151,6 +157,8 @@ jobs:
151157
- uses: actions/checkout@v7
152158
- name: Bump vLLM cu130 wheel pin 🔧
153159
id: bump
160+
env:
161+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
154162
run: |
155163
bash .github/bump_vllm_wheel.sh vllm-project/vllm backend/python/vllm/requirements-cublas13-after.txt VLLM_VERSION
156164
{
@@ -187,6 +195,8 @@ jobs:
187195
- uses: actions/checkout@v7
188196
- name: Bump vllm-metal pin 🔧
189197
id: bump
198+
env:
199+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
190200
run: |
191201
bash .github/bump_vllm_metal.sh vllm-project/vllm-metal backend/python/vllm/install.sh VLLM_METAL_VERSION
192202
{

.github/workflows/bump_docs.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v7
1717
- name: Bump dependencies 🔧
18+
env:
19+
# Authenticated API calls get 1000 req/hour instead of the 60/hour
20+
# anonymous cap that is shared across every job on the runner's IP.
21+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1822
run: |
1923
bash .github/bump_docs.sh ${{ matrix.repository }}
2024
- name: Create Pull Request

0 commit comments

Comments
 (0)