From a2ee3cdbca3336dc44bde4e5a577dbe434d48e83 Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Mon, 12 Oct 2026 16:41:14 -0700 Subject: [PATCH] fix(dfns): authenticate the latest-release lookup with GITHUB_TOKEN RemoteDfnRegistry.latest_tag called the GitHub API without a token, so `mf dfns sync` hit the unauthenticated rate limit on shared CI runners. Send GITHUB_TOKEN when set, like the rest of devtools (get_request). Co-Authored-By: Claude Opus 5.5 --- autotest/dfns/test_registry.py | 13 +++++++++---- modflow_devtools/dfns/registry.py | 7 ++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/autotest/dfns/test_registry.py b/autotest/dfns/test_registry.py index c0cff018..db2dfd18 100644 --- a/autotest/dfns/test_registry.py +++ b/autotest/dfns/test_registry.py @@ -13,7 +13,12 @@ def test_latest_tag_exact_tag(): assert registry._latest is None # no network call, nothing cached -def test_latest_tag_resolves_via_api(): +@pytest.mark.parametrize("token", [None, "abc"]) +def test_latest_tag_resolves_via_api(monkeypatch, token): + if token: + monkeypatch.setenv("GITHUB_TOKEN", token) + else: + monkeypatch.delenv("GITHUB_TOKEN", raising=False) registry = RemoteDfnRegistry(release_id="MODFLOW-ORG/modflow6@latest") mock_response = MagicMock() @@ -29,9 +34,9 @@ def test_latest_tag_resolves_via_api(): assert tag == "v6.6.1" assert registry._latest == "v6.6.1" - mock_open.assert_called_once_with( - "https://api.github.com/repos/MODFLOW-ORG/modflow6/releases/latest" - ) + (request,), _ = mock_open.call_args + assert request.full_url == "https://api.github.com/repos/MODFLOW-ORG/modflow6/releases/latest" + assert request.get_header("Authorization") == (f"Bearer {token}" if token else None) def test_latest_tag_cached(): diff --git a/modflow_devtools/dfns/registry.py b/modflow_devtools/dfns/registry.py index 90c157cc..6669aa1f 100644 --- a/modflow_devtools/dfns/registry.py +++ b/modflow_devtools/dfns/registry.py @@ -13,6 +13,7 @@ from modflow_devtools.dfn import schema as dfn from modflow_devtools.dfns import schema as dfns +from modflow_devtools.download import get_request __all__ = [ "DfnRegistry", @@ -75,9 +76,9 @@ def latest_tag(self) -> str: return tag if self._latest is None: owner, name = repo.split("/") - with urllib.request.urlopen( - f"https://api.github.com/repos/{owner}/{name}/releases/latest" - ) as resp: + # authenticated if GITHUB_TOKEN is set, to bypass the rate limit + url = f"https://api.github.com/repos/{owner}/{name}/releases/latest" + with urllib.request.urlopen(get_request(url)) as resp: self._latest = json.loads(resp.read())["tag_name"] return self._latest