Skip to content

Commit 04d2c0b

Browse files
leliaclaude
andauthored
Harden PyPI install verification against stale cache (#102)
* fix(ci): refresh PyPI install verification * fix(ci): extend PyPI verify budget to 30 minutes and log index staleness Match the socket-python-cli release workflow hardening (PR #290 there): the 2026-08-05 propagation delay exceeded 10 minutes from the release runner's vantage point, so extend the retry budget to 30 minutes, and log when the JSON API already has the version but the Simple index does not, making CDN propagation delay distinguishable from a failed publish in the logs. 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 8ad17ae commit 04d2c0b

1 file changed

Lines changed: 25 additions & 11 deletions

File tree

.github/workflows/release.yml

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
REF_NAME: ${{ github.ref_name }}
2828
run: |
2929
RAW_VERSION=$(hatch version)
30-
echo "VERSION=$RAW_VERSION" >> $GITHUB_ENV
30+
echo "VERSION=$RAW_VERSION" >> "$GITHUB_ENV"
3131
if [ "v$RAW_VERSION" != "$REF_NAME" ]; then
3232
echo "Error: Git tag ($REF_NAME) does not match hatch version (v$RAW_VERSION)"
3333
exit 1
@@ -38,12 +38,12 @@ jobs:
3838
env:
3939
VERSION: ${{ env.VERSION }}
4040
run: |
41-
if curl -s -f https://pypi.org/pypi/socketdev/$VERSION/json > /dev/null; then
41+
if curl -s -f "https://pypi.org/pypi/socketdev/$VERSION/json" > /dev/null; then
4242
echo "Version ${VERSION} already exists on PyPI"
43-
echo "pypi_exists=true" >> $GITHUB_OUTPUT
43+
echo "pypi_exists=true" >> "$GITHUB_OUTPUT"
4444
else
4545
echo "Version ${VERSION} not found on PyPI - proceeding with PyPI deployment"
46-
echo "pypi_exists=false" >> $GITHUB_OUTPUT
46+
echo "pypi_exists=false" >> "$GITHUB_OUTPUT"
4747
fi
4848
4949
- name: Build package
@@ -60,15 +60,29 @@ jobs:
6060
env:
6161
VERSION: ${{ env.VERSION }}
6262
run: |
63-
for i in {1..30}; do
64-
if pip install socketdev==${VERSION}; then
63+
# The first lookup can race PyPI's Simple-index propagation, and a delayed
64+
# CDN purge can leave the index stale well after a successful upload.
65+
# pip caches HTTP responses by default, so without --no-cache-dir every
66+
# retry can reuse that initial stale response instead of checking whether
67+
# the release has appeared. Budget: 30 minutes.
68+
MAX_ATTEMPTS=60
69+
for i in $(seq 1 "$MAX_ATTEMPTS"); do
70+
if python -m pip install \
71+
--no-cache-dir \
72+
--index-url https://pypi.org/simple/ \
73+
"socketdev==${VERSION}"; then
6574
echo "Package ${VERSION} is now available and installable on PyPI"
66-
pip uninstall -y socketdev
67-
echo "success=true" >> $GITHUB_OUTPUT
75+
python -m pip uninstall -y socketdev
76+
echo "success=true" >> "$GITHUB_OUTPUT"
6877
exit 0
6978
fi
70-
echo "Attempt $i: Package not yet installable, waiting 20s... (${i}/30)"
71-
sleep 20
79+
if curl -s -f "https://pypi.org/pypi/socketdev/${VERSION}/json" > /dev/null; then
80+
echo "Release ${VERSION} exists on PyPI (JSON API) but is not in the Simple index yet - CDN propagation delay"
81+
fi
82+
if [ "$i" -lt "$MAX_ATTEMPTS" ]; then
83+
echo "Attempt $i: Package not yet installable, waiting 30s... (${i}/${MAX_ATTEMPTS})"
84+
sleep 30
85+
fi
7286
done
73-
echo "success=false" >> $GITHUB_OUTPUT
87+
echo "success=false" >> "$GITHUB_OUTPUT"
7488
exit 1

0 commit comments

Comments
 (0)