From dd8af2d483d9ca27f96f001c4b647811a7f7326b Mon Sep 17 00:00:00 2001 From: ChrisLovering Date: Sat, 11 Jul 2026 21:17:41 -0400 Subject: [PATCH 1/3] Drop recoverable failures to warnings API timeouts and non-2XX responses fall back to db data anyway, so this isn't a big problem. --- pydis_site/apps/home/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydis_site/apps/home/views.py b/pydis_site/apps/home/views.py index 41415f846..859d5e30d 100644 --- a/pydis_site/apps/home/views.py +++ b/pydis_site/apps/home/views.py @@ -79,10 +79,10 @@ def _get_api_data(self) -> dict[str, RepoAPIData]: api_data: list[dict] = resp.json() except httpx.TimeoutException: - log.error("Request to fetch GitHub repository metadata for timed out!") + log.warning("Request to fetch GitHub repository metadata for timed out!") return repo_dict except httpx.HTTPStatusError as ex: - log.error(f"Received HTTP {ex.response.status_code} from GitHub repository metadata request!") + log.warning(f"Received HTTP {ex.response.status_code} from GitHub repository metadata request!") return repo_dict except JSONDecodeError: log.error("GitHub returned invalid JSON for repository metadata!") From f272dd6fd9620f0b576b880437356eb2b9ceb155 Mon Sep 17 00:00:00 2001 From: ChrisLovering Date: Sat, 11 Jul 2026 21:23:42 -0400 Subject: [PATCH 2/3] Return stale cached tags if github API request fails --- pydis_site/apps/content/tests/test_utils.py | 20 ++++++++++++++++++++ pydis_site/apps/content/utils.py | 15 ++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py index 09b52205d..769084834 100644 --- a/pydis_site/apps/content/tests/test_utils.py +++ b/pydis_site/apps/content/tests/test_utils.py @@ -241,6 +241,26 @@ def test_get_tag_404(self): with self.assertRaises(models.Tag.DoesNotExist): utils.get_tag("fake") + @mock.patch.object(utils, "fetch_tags") + def test_get_tags_falls_back_to_stale_cache_on_error(self, fetch_mock: mock.Mock): + """Test that stale cached tags are served when refreshing from GitHub fails.""" + stale = models.Tag.objects.create(name="stale-tag") + models.Tag.objects.update(last_updated=_time) + fetch_mock.side_effect = httpx.ReadTimeout("The read operation timed out") + + result = utils.get_tags() + + fetch_mock.assert_called_once() + self.assertEqual([stale], result) + + @mock.patch.object(utils, "fetch_tags") + def test_get_tags_reraises_on_error_with_empty_cache(self, fetch_mock: mock.Mock): + """Test that an error is raised when there is no cached data to fall back on.""" + fetch_mock.side_effect = httpx.ReadTimeout("The read operation timed out") + + with self.assertRaises(utils.TagUpdateError): + utils.get_tags() + @mock.patch.object(utils, "get_tag_category") def test_category_pages(self, get_mock: mock.Mock): """Test that the category pages function calls the correct method for tags.""" diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py index bb892d350..2d8f90aed 100644 --- a/pydis_site/apps/content/utils.py +++ b/pydis_site/apps/content/utils.py @@ -23,6 +23,10 @@ log = logging.getLogger(__name__) +class TagUpdateError(Exception): + """Raised when tags cannot be fetched from GitHub and no cached data is available.""" + + def github_client(**kwargs) -> httpx.Client: """Get a client to access the GitHub API with important settings pre-configured.""" client = httpx.Client( @@ -228,7 +232,16 @@ def get_tags() -> list[Tag]: if settings.STATIC_BUILD: # pragma: no cover tags = get_tags_static() else: - tags = fetch_tags() + try: + tags = fetch_tags() + except httpx.HTTPError as error: + # return the stale cache if we have one, otherwise raise the error + if last_update is not None: + log.warning("Failed to refresh tags from GitHub: %r", error) + return list(Tag.objects.all()) + raise TagUpdateError( + "Failed to fetch tags from GitHub, also have no stale cache to fall back on." + ) from error record_tags(tags) return tags From 90d3ec544630ac2bab03fa58f6ad3a3f94b03d5e Mon Sep 17 00:00:00 2001 From: ChrisLovering Date: Sat, 11 Jul 2026 21:25:07 -0400 Subject: [PATCH 3/3] Bump pre-commit-hooks version --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f379ad04..65dc6f340 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: check-merge-conflict - id: check-toml