mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
fix(ci): PyPI upload token-fallback for per-project scope (#40)
hanzo-iam is owned on PyPI by HANZO_AI_PYPI_TOKEN, not PYPI_TOKEN, so it 403'd. Each upload now tries PYPI_TOKEN then falls back to HANZO_AI_PYPI_TOKEN, so any hanzo-* package publishes regardless of which token owns its project. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
committed by
GitHub
co-authored by
Hanzo Dev
parent
8e6b9bd4ca
commit
4c61d0a9c2
@@ -146,7 +146,13 @@ jobs:
|
||||
- name: Build and publish packages
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.HANZO_PYPI_TOKEN || secrets.PYPI_TOKEN }}
|
||||
# Two tokens cover per-project scope: PYPI_TOKEN owns most hanzo-*
|
||||
# packages; HANZO_AI_PYPI_TOKEN owns the rest (e.g. hanzo-iam, published
|
||||
# before consolidation under a different owner). Each upload tries the
|
||||
# primary then falls back, so a 403 scope-miss on one token is covered by
|
||||
# the other — no package is unpublishable for lack of the matching token.
|
||||
PYPI_TOKEN_PRIMARY: ${{ secrets.PYPI_TOKEN }}
|
||||
PYPI_TOKEN_FALLBACK: ${{ secrets.HANZO_AI_PYPI_TOKEN }}
|
||||
run: |
|
||||
PACKAGES="${{ steps.determine_packages.outputs.PACKAGES }}"
|
||||
|
||||
@@ -176,15 +182,20 @@ jobs:
|
||||
# Build from repo root to avoid stdlib shadowing (hanzoai/types vs types)
|
||||
python -m build "$PKG_DIR" --outdir "$PKG_DIR/dist"
|
||||
|
||||
# Upload to PyPI with backoff. PyPI 429-rate-limits rapid bursts, which
|
||||
# silently dropped the tail of large multi-package publishes. Retry
|
||||
# transient failures so the whole set lands; --skip-existing keeps
|
||||
# retries idempotent (already-uploaded files are skipped).
|
||||
# Upload with token-fallback + 429 backoff. Try the primary token; on
|
||||
# any failure try the fallback token once (covers per-project 403 scope,
|
||||
# e.g. hanzo-iam owned by HANZO_AI_PYPI_TOKEN). --skip-existing keeps
|
||||
# retries idempotent; backoff rides out PyPI's burst 429s. PyPI also
|
||||
# rate-limits NEW-project creation per window — a brand-new name may need
|
||||
# a later re-run once that window resets.
|
||||
attempt=0
|
||||
until python -m twine upload "$PKG_DIR/dist/"* --skip-existing; do
|
||||
until TWINE_PASSWORD="$PYPI_TOKEN_PRIMARY" python -m twine upload "$PKG_DIR/dist/"* --skip-existing; do
|
||||
if [ -n "$PYPI_TOKEN_FALLBACK" ] && TWINE_PASSWORD="$PYPI_TOKEN_FALLBACK" python -m twine upload "$PKG_DIR/dist/"* --skip-existing; then
|
||||
break
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
if [ "$attempt" -ge 5 ]; then
|
||||
echo "Warning: giving up on $package after $attempt attempts (persistent error — e.g. 403 token scope)"
|
||||
echo "Warning: giving up on $package after $attempt attempts (403 on both tokens, or persistent error)"
|
||||
break
|
||||
fi
|
||||
echo "Upload of $package failed (attempt $attempt) — backing off $((attempt * 10))s (PyPI 429?)"
|
||||
|
||||
Reference in New Issue
Block a user