Skip to content

Commit 0b577a9

Browse files
leliaclaude
andauthored
Harden PyPI install verification against stale cache (#290)
* Harden release verify step against PyPI index propagation delays The verify loop assumed a new release appears in PyPI's simple index within its 10-minute budget. Both socketsecurity 2.5.9 and socketdev 3.4.2 (2026-08-05) took longer than that: the upload succeeded and the JSON API showed the release immediately, but the CDN-cached simple index kept serving a stale version list past the loop's last attempt, failing the release and skipping the Docker publish. Extend the retry window to 30 minutes, add --no-cache-dir so each attempt refetches the index rather than revalidating pip's locally cached stale copy, and log when the JSON API already has the version so index staleness is distinguishable from a failed publish. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * Align release verify step with socket-sdk-python hardening Use python -m pip with an explicit production Simple-index URL, quote workflow outputs, and skip the sleep after the final attempt, matching the socket-sdk-python release workflow so the verify step is identical in both repos. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * Trim release-specific details from verify step comment Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> --------- Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 142449b commit 0b577a9

1 file changed

Lines changed: 21 additions & 7 deletions

File tree

.github/workflows/release.yml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,31 @@ jobs:
7979
env:
8080
VERSION: ${{ env.VERSION }}
8181
run: |
82-
for i in {1..30}; do
83-
if pip install socketsecurity==${VERSION}; then
82+
# The first lookup can race PyPI's Simple-index propagation, and a delayed
83+
# CDN purge can leave the index stale well after a successful upload.
84+
# pip caches HTTP responses by default, so without --no-cache-dir every
85+
# retry can reuse that initial stale response instead of checking whether
86+
# the release has appeared. Budget: 30 minutes.
87+
MAX_ATTEMPTS=60
88+
for i in $(seq 1 "$MAX_ATTEMPTS"); do
89+
if python -m pip install \
90+
--no-cache-dir \
91+
--index-url https://pypi.org/simple/ \
92+
"socketsecurity==${VERSION}"; then
8493
echo "Package ${VERSION} is now available and installable on PyPI"
85-
pip uninstall -y socketsecurity
86-
echo "success=true" >> $GITHUB_OUTPUT
94+
python -m pip uninstall -y socketsecurity
95+
echo "success=true" >> "$GITHUB_OUTPUT"
8796
exit 0
8897
fi
89-
echo "Attempt $i: Package not yet installable, waiting 20s... (${i}/30)"
90-
sleep 20
98+
if curl -s -f "https://pypi.org/pypi/socketsecurity/${VERSION}/json" > /dev/null; then
99+
echo "Release ${VERSION} exists on PyPI (JSON API) but is not in the Simple index yet - CDN propagation delay"
100+
fi
101+
if [ "$i" -lt "$MAX_ATTEMPTS" ]; then
102+
echo "Attempt $i: Package not yet installable, waiting 30s... (${i}/${MAX_ATTEMPTS})"
103+
sleep 30
104+
fi
91105
done
92-
echo "success=false" >> $GITHUB_OUTPUT
106+
echo "success=false" >> "$GITHUB_OUTPUT"
93107
exit 1
94108
95109
- name: Build & Push Docker

0 commit comments

Comments
 (0)