@@ -350,14 +350,33 @@ jobs:
350350 source "${VENV_DIR}/bin/activate"
351351 python -m pip install --upgrade pip setuptools wheel numpy
352352
353- # Short sleep to allow TestPyPI to propagate uploaded wheels
354- echo "Sleeping 60s to allow TestPyPI propagation before install..."
355- sleep 60
356-
357- # Determine version from pyalp/pyproject.toml
353+ # Retry pip install from TestPyPI with exponential backoff (bounded attempts)
358354 PYALP_VERSION=$(grep -E '^version\s*=\s*"' pyalp/pyproject.toml | head -n1 | sed -E 's/^version\s*=\s*"([^"]+)".*/\1/')
359- echo "Installing alp-graphblas==${PYALP_VERSION} from TestPyPI"
360- python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple alp-graphblas==${PYALP_VERSION} -v
355+ echo "Installing alp-graphblas==${PYALP_VERSION} from TestPyPI (with retries)"
356+
357+ MAX_ATTEMPTS=6
358+ SLEEP_BASE=10
359+ SUCCESS=0
360+
361+ for attempt in $(seq 1 ${MAX_ATTEMPTS}); do
362+ echo "--- attempt ${attempt} of ${MAX_ATTEMPTS} ---"
363+ # verbose pip output helps debugging in CI logs
364+ python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple alp-graphblas==${PYALP_VERSION} -v && SUCCESS=1 && break
365+ echo "pip install failed on attempt ${attempt}"
366+ if [ "${attempt}" -lt "${MAX_ATTEMPTS}" ]; then
367+ SLEEP_SECONDS=$((SLEEP_BASE * attempt))
368+ echo "Sleeping ${SLEEP_SECONDS}s before retry..."
369+ sleep "${SLEEP_SECONDS}"
370+ fi
371+ done
372+
373+ if [ "${SUCCESS}" -ne 1 ]; then
374+ echo "ERROR: failed to install alp-graphblas from TestPyPI after ${MAX_ATTEMPTS} attempts" >&2
375+ exit 1
376+ fi
377+
378+ # Print a compact JSON summary of installed backends for easy scanning in CI logs
379+ python -c "import json,importlib,sys; print(json.dumps({'backends': importlib.import_module('pyalp').list_backends()}))"
361380
362381 - name : Run in-process backend import smoke test
363382 shell : bash
0 commit comments