Skip to content

Commit f6e0fc3

Browse files
committed
fix(ci): defer BigQuery ADC until tool use
Lazy credentials let offline CI import the agent topology without Application Default Credentials.
1 parent 42ca616 commit f6e0fc3

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

backend/dry_lab/bq.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,41 @@
1313
from typing import Optional
1414

1515
import google.auth
16+
import google.auth.credentials
1617
from google.adk.integrations.bigquery import BigQueryCredentialsConfig, BigQueryToolset
1718
from google.adk.integrations.bigquery.config import BigQueryToolConfig, WriteMode
1819

1920
from .config import settings
2021

22+
23+
class _LazyApplicationDefaultCredentials(google.auth.credentials.Credentials):
24+
"""Defer google.auth.default until the tool actually needs a token (offline CI can import the agent)."""
25+
26+
def __init__(self, scopes: list[str]) -> None:
27+
self._scopes = scopes
28+
self._inner: google.auth.credentials.Credentials | None = None
29+
super().__init__()
30+
31+
def _load(self) -> google.auth.credentials.Credentials:
32+
if self._inner is None:
33+
self._inner, _ = google.auth.default(scopes=self._scopes)
34+
return self._inner
35+
36+
def __getattr__(self, name: str):
37+
if name.startswith("_"):
38+
raise AttributeError(name)
39+
return getattr(self._load(), name)
40+
41+
def refresh(self, request) -> None:
42+
self._load().refresh(request)
43+
44+
def apply(self, headers, token=None) -> None:
45+
self._load().apply(headers, token=token)
46+
47+
def before_request(self, request, method, url, headers) -> None:
48+
self._load().before_request(request, method, url, headers)
49+
50+
2151
_BQ_SCOPES = ["https://www.googleapis.com/auth/bigquery"]
2252

2353
# Keep the agent-facing surface crisp: the investigator only needs to inspect schema + run read-only SELECTs.
@@ -31,7 +61,7 @@ def build_bigquery_toolset(tool_filter: Optional[list[str]] = None) -> BigQueryT
3161
dataset lives in US on settings.project). Pass tool_filter to scope the exposed tools (e.g. the investigator
3262
only gets get_table_info + execute_sql so tool selection stays crisp).
3363
"""
34-
credentials, _ = google.auth.default(scopes=_BQ_SCOPES)
64+
credentials = _LazyApplicationDefaultCredentials(_BQ_SCOPES)
3565
kwargs = dict(
3666
credentials_config=BigQueryCredentialsConfig(credentials=credentials),
3767
bigquery_tool_config=BigQueryToolConfig(

0 commit comments

Comments
 (0)