Skip to content

Commit ea15685

Browse files
committed
Drop HTTP Basic auth from cassette-fetch path
The cassette hosting at sciqlop.lpp.polytechnique.fr/data/speasy_cassettes/ is now public-read. Cassettes are content-addressed by sha256 — URLs are unguessable for outsiders and any tampering is caught on download via the existing hash verification in _fetch_cassette. Practical benefits: - Fork PRs can run the cassette-replaying unit tier (previously blocked: GitHub Actions doesn't expose repo secrets to fork PRs). - New contributors need no credential setup to run the tests. - CI workflows lose the SPEASY_CASSETTE_FETCH_USER/PASSWORD env injection (no longer needed). Cassettes are still scrubbed (Set-Cookie response headers and AMDA auth.php hash response bodies) by the before_record_response callback in vcr_config, so no session/credential material reaches the cassette content itself.
1 parent 7c90dbb commit ea15685

5 files changed

Lines changed: 12 additions & 25 deletions

File tree

.github/workflows/contract.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ jobs:
2121
SPEASY_CORE_DISABLED_PROVIDERS: "cdpp3dview"
2222
SPEASY_CORE_HTTP_REWRITE_RULES: '{"https://thisserver_does_not_exists.lpp.polytechnique.fr/pub/":"http://sciqlop.lpp.polytechnique.fr/cdaweb-data/pub/"}'
2323
SPEASY_CORE_HTTP_USER_AGENT: "speasy-test-github-actions"
24-
SPEASY_CASSETTE_FETCH_USER: ${{ secrets.SPEASY_CASSETTE_FETCH_USER }}
25-
SPEASY_CASSETTE_FETCH_PASSWORD: ${{ secrets.SPEASY_CASSETTE_FETCH_PASSWORD }}
2624

2725
steps:
2826
- uses: actions/checkout@v6

.github/workflows/e2e.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ jobs:
1616
SPEASY_AMDA_USERNAME: ${{ secrets.SPEASY_AMDA_USERNAME }}
1717
SPEASY_AMDA_PASSWORD: ${{ secrets.SPEASY_AMDA_PASSWORD }}
1818
SPEASY_CORE_DISABLED_PROVIDERS: "cdpp3dview"
19-
SPEASY_CASSETTE_FETCH_USER: ${{ secrets.SPEASY_CASSETTE_FETCH_USER }}
20-
SPEASY_CASSETTE_FETCH_PASSWORD: ${{ secrets.SPEASY_CASSETTE_FETCH_PASSWORD }}
2119

2220
runs-on: ${{ matrix.os }}
2321
strategy:

.github/workflows/unit.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ jobs:
99
unit:
1010
env:
1111
SPEASY_CORE_DISABLED_PROVIDERS: "cdpp3dview"
12-
SPEASY_CASSETTE_FETCH_USER: ${{ secrets.SPEASY_CASSETTE_FETCH_USER }}
13-
SPEASY_CASSETTE_FETCH_PASSWORD: ${{ secrets.SPEASY_CASSETTE_FETCH_PASSWORD }}
1412

1513
runs-on: ${{ matrix.os }}
1614
strategy:

CONTRIBUTING.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,12 @@ Ready to contribute? Here's how to set up `Speasy` for local development.
110110
pytest's conftest reads ``tests/cassettes_manifest.json``, fetches
111111
any missing cassettes from
112112
``https://sciqlop.lpp.polytechnique.fr/data/speasy_cassettes/``
113-
(HTTP Basic auth, credentials in env vars
114-
``SPEASY_CASSETTE_FETCH_USER`` and ``SPEASY_CASSETTE_FETCH_PASSWORD``,
115-
or ``~/.netrc``), and decompresses them to ``tests/cassettes/``.
113+
(public read, no auth — files are content-addressed by sha256,
114+
making the URLs unguessable for outsiders and tamper-evident on
115+
download), and decompresses them to ``tests/cassettes/``.
116116

117-
To run the unit tier locally, set those env vars in your shell or
118-
add a machine entry for ``sciqlop.lpp.polytechnique.fr`` to your
119-
``~/.netrc``. Ask a maintainer for read credentials.
117+
To run the unit tier locally: no setup needed beyond a working
118+
internet connection.
120119

121120
To add or update a cassette (maintainer-only)::
122121

tests/conftest.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import numpy as np
3232
import pytest
3333
import requests
34-
from requests.auth import HTTPBasicAuth
3534

3635

3736
# ---------------------------------------------------------------------------
@@ -58,7 +57,12 @@
5857

5958

6059
def _fetch_cassette(sha: str) -> Path:
61-
"""Download a cassette by its content hash, cache locally, return path to .yaml.gz."""
60+
"""Download a cassette by its content hash, cache locally, return path to .yaml.gz.
61+
62+
Cassettes are served publicly (no auth) at CASSETTE_BASE_URL. Content
63+
addressing (sha256) makes the file names unguessable for outsiders
64+
and tamper-evident on download.
65+
"""
6266
cached = LOCAL_CACHE / f"{sha}.yaml.gz"
6367
if cached.exists():
6468
# Verify integrity (defensive — corrupted cache yields a clear error).
@@ -68,19 +72,9 @@ def _fetch_cassette(sha: str) -> Path:
6872
return cached
6973
cached.unlink()
7074

71-
user = os.environ.get("SPEASY_CASSETTE_FETCH_USER")
72-
password = os.environ.get("SPEASY_CASSETTE_FETCH_PASSWORD")
73-
if not user or not password:
74-
raise RuntimeError(
75-
f"Cannot fetch cassette {sha[:12]}...: "
76-
"SPEASY_CASSETTE_FETCH_USER and SPEASY_CASSETTE_FETCH_PASSWORD env "
77-
"vars must be set (or use ~/.netrc with a 'machine "
78-
"sciqlop.lpp.polytechnique.fr' entry)."
79-
)
80-
8175
url = f"{CASSETTE_BASE_URL}/{sha}.yaml.gz"
8276
LOCAL_CACHE.mkdir(parents=True, exist_ok=True)
83-
response = requests.get(url, auth=HTTPBasicAuth(user, password), timeout=60)
77+
response = requests.get(url, timeout=60)
8478
response.raise_for_status()
8579

8680
decompressed = gzip.decompress(response.content)

0 commit comments

Comments
 (0)