[6d7fb817] chore(deps): upgrade pydantic-settings from 2.14.1 to 2.14.2 to fix GHSA-4xgf-cpjx-pc3j (#238) (#240) (#241)

- Add pydantic-settings>=2.14.2 constraint in pyproject.toml
- Regenerate uv.lock: pydantic_settings-2.14.1 -> pydantic_settings-2.14.2
- Fix pre-existing xenon CC=12 in _fetch_latest_ci_run (self-heal CI signal
  commit introduced the complexity): extract HTTP retry loop into
  _get_ci_runs_response helper, bringing both methods to rank B

All acceptance criteria verified: uv.lock shows 2.14.2, pip-audit
--ignore-vuln CVE-2025-3000 exits 0 with no GHSA-4xgf-cpjx-pc3j mention,
make gate (ruff/mypy/xenon) exits 0, no GHSA suppression in Makefile or
pyproject.toml.

Co-authored-by: Backend Developer 1 <be-dev-1@agents.roboco.dev>
This commit is contained in:
Renzo F
2026-06-20 20:25:08 +02:00
committed by GitHub
co-authored by Backend Developer 1
parent af5adf8c03
commit 028b49161b
3 changed files with 43 additions and 32 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ requires-python = ">=3.10,<3.15"
dependencies = [ dependencies = [
# Core # Core
"pydantic", "pydantic",
"pydantic-settings", "pydantic-settings>=2.14.2",
# API # API
"fastapi", "fastapi",
"uvicorn[standard]", "uvicorn[standard]",
+38 -27
View File
@@ -1719,6 +1719,43 @@ class GitService(BaseService):
"completed_at": run.get("updated_at"), "completed_at": run.get("updated_at"),
} }
async def _get_ci_runs_response(
self,
project_slug: str,
url: str,
headers: dict[str, str],
params: dict[str, str | int],
) -> httpx.Response | None:
"""GET *url* with retry/back-off; return the successful response or None."""
resp: httpx.Response | None = None
for attempt in range(_CI_FETCH_ATTEMPTS):
last = attempt + 1 == _CI_FETCH_ATTEMPTS
try:
async with httpx.AsyncClient(timeout=_default_git_timeout()) as client:
resp = await client.get(url, headers=headers, params=params)
except httpx.HTTPError as e:
if last:
self.log.warning(
"get_latest_ci_conclusion request failed",
project=project_slug,
error=str(e),
)
return None
await asyncio.sleep(_CI_FETCH_BACKOFF_SECONDS * (attempt + 1))
continue
if resp.is_success:
return resp
if resp.status_code in _CI_RETRYABLE_STATUS and not last:
await asyncio.sleep(_CI_FETCH_BACKOFF_SECONDS * (attempt + 1))
continue
self.log.warning(
"get_latest_ci_conclusion non-2xx",
project=project_slug,
status=resp.status_code,
)
return None
return resp
async def _fetch_latest_ci_run( async def _fetch_latest_ci_run(
self, self,
project_slug: str, project_slug: str,
@@ -1756,33 +1793,7 @@ class GitService(BaseService):
"status": "completed", "status": "completed",
"per_page": _CI_RUN_WINDOW, "per_page": _CI_RUN_WINDOW,
} }
resp: httpx.Response | None = None resp = await self._get_ci_runs_response(project_slug, url, headers, params)
for attempt in range(_CI_FETCH_ATTEMPTS):
last = attempt + 1 == _CI_FETCH_ATTEMPTS
try:
async with httpx.AsyncClient(timeout=_default_git_timeout()) as client:
resp = await client.get(url, headers=headers, params=params)
except httpx.HTTPError as e:
if last:
self.log.warning(
"get_latest_ci_conclusion request failed",
project=project_slug,
error=str(e),
)
return None
await asyncio.sleep(_CI_FETCH_BACKOFF_SECONDS * (attempt + 1))
continue
if resp.is_success:
break
if resp.status_code in _CI_RETRYABLE_STATUS and not last:
await asyncio.sleep(_CI_FETCH_BACKOFF_SECONDS * (attempt + 1))
continue
self.log.warning(
"get_latest_ci_conclusion non-2xx",
project=project_slug,
status=resp.status_code,
)
return None
if resp is None or not resp.is_success: if resp is None or not resp.is_success:
return None return None
data = resp.json() data = resp.json()
Generated
+4 -4
View File
@@ -2505,16 +2505,16 @@ wheels = [
[[package]] [[package]]
name = "pydantic-settings" name = "pydantic-settings"
version = "2.14.1" version = "2.14.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "pydantic" }, { name = "pydantic" },
{ name = "python-dotenv" }, { name = "python-dotenv" },
{ name = "typing-inspection" }, { name = "typing-inspection" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" },
] ]
[[package]] [[package]]
@@ -3076,7 +3076,7 @@ requires-dist = [
{ name = "passlib", extras = ["bcrypt"] }, { name = "passlib", extras = ["bcrypt"] },
{ name = "pip-audit", marker = "extra == 'dev'" }, { name = "pip-audit", marker = "extra == 'dev'" },
{ name = "pydantic" }, { name = "pydantic" },
{ name = "pydantic-settings" }, { name = "pydantic-settings", specifier = ">=2.14.2" },
{ name = "pytest", marker = "extra == 'dev'" }, { name = "pytest", marker = "extra == 'dev'" },
{ name = "pytest-asyncio", marker = "extra == 'dev'" }, { name = "pytest-asyncio", marker = "extra == 'dev'" },
{ name = "pytest-cov", marker = "extra == 'dev'" }, { name = "pytest-cov", marker = "extra == 'dev'" },