Skip to content

Commit e38fed9

Browse files
Ambient Code Botclaude
andcommitted
fix: resolve CodeQL, LIMIT clause, and ruff format issues from PR review
- Sanitize exception output in Jira fetch to prevent credential leakage in tracebacks (CodeQL clear-text logging fix) - Add presence-only credential status logging (set/not set, never values) - Add limit parameter and LIMIT clause to search_github_repos - Replace N+1 per-repo language queries with single batched query - Auto-format all scripts with ruff format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 43dc833 commit e38fed9

4 files changed

Lines changed: 81 additions & 136 deletions

File tree

mcp_server.py

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,7 @@ def _attached_db_schema(db_name: str, build_hint: str) -> str:
117117
count = conn.execute(f"SELECT COUNT(*) FROM {db_name}.[{t['name']}]").fetchone()[0]
118118
lines.append(f"-- {t['name']}: {count:,} rows")
119119
lines.append(t["sql"] + ";\n")
120-
views = conn.execute(
121-
f"SELECT name, sql FROM {db_name}.sqlite_master WHERE type='view' ORDER BY name"
122-
).fetchall()
120+
views = conn.execute(f"SELECT name, sql FROM {db_name}.sqlite_master WHERE type='view' ORDER BY name").fetchall()
123121
if views:
124122
lines.append(f"\n-- {db_name.upper()} VIEWS\n")
125123
for v in views:
@@ -795,9 +793,7 @@ def cloud_pricing_lookup(
795793
"""
796794
conn = _get_conn()
797795
if not _db_attached(conn, "pricing"):
798-
return json.dumps(
799-
{"error": "pricing.db not attached. Run: uv run scripts/fetch_pricing.py"}
800-
)
796+
return json.dumps({"error": "pricing.db not attached. Run: uv run scripts/fetch_pricing.py"})
801797

802798
if not any([provider, service, instance_type, region, model_name, usage_type]):
803799
return json.dumps({"error": "Provide at least one filter"})
@@ -850,17 +846,11 @@ def rosa_cluster_costs() -> str:
850846
"""
851847
conn = _get_conn()
852848
if not _db_attached(conn, "pricing"):
853-
return json.dumps(
854-
{"error": "pricing.db not attached. Run: uv run scripts/fetch_pricing.py"}
855-
)
849+
return json.dumps({"error": "pricing.db not attached. Run: uv run scripts/fetch_pricing.py"})
856850

857-
rows = conn.execute(
858-
"SELECT * FROM pricing.v_rosa_estimated_cost ORDER BY estimated_monthly_cost DESC"
859-
).fetchall()
851+
rows = conn.execute("SELECT * FROM pricing.v_rosa_estimated_cost ORDER BY estimated_monthly_cost DESC").fetchall()
860852
if not rows:
861-
return json.dumps(
862-
{"error": "No ROSA cluster data. Run: uv run scripts/fetch_pricing.py (requires oc access)"}
863-
)
853+
return json.dumps({"error": "No ROSA cluster data. Run: uv run scripts/fetch_pricing.py (requires oc access)"})
864854
return json.dumps({"clusters": _rows_to_dicts(rows), "count": len(rows)}, default=str)
865855

866856

@@ -879,9 +869,7 @@ def github_org_summary() -> str:
879869
"""
880870
conn = _get_conn()
881871
if not _db_attached(conn, "github"):
882-
return json.dumps(
883-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
884-
)
872+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
885873

886874
stats = conn.execute("SELECT * FROM github.v_gh_org_stats").fetchone()
887875
result = dict(stats)
@@ -913,20 +901,21 @@ def search_github_repos(
913901
name: str | None = None,
914902
language: str | None = None,
915903
topic: str | None = None,
904+
limit: int = 50,
916905
) -> str:
917906
"""Search GitHub repos by name, language, or topic. All filters are partial match.
918907
919908
Provide at least one parameter. Returns repo details with language breakdown.
909+
Returns up to `limit` repos (default 50, max 200).
920910
"""
921911
if not any([name, language, topic]):
922912
return json.dumps({"error": "Provide at least one of: name, language, topic"})
923913

924914
conn = _get_conn()
925915
if not _db_attached(conn, "github"):
926-
return json.dumps(
927-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
928-
)
916+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
929917

918+
limit = min(limit, MAX_QUERY_ROWS)
930919
conditions, params = [], []
931920
if name:
932921
conditions.append("r.name LIKE ?")
@@ -944,28 +933,35 @@ def search_github_repos(
944933

945934
where = " AND ".join(conditions)
946935
repos = conn.execute(
947-
f"""SELECT r.name, r.description, r.html_url, r.default_branch,
936+
f"""SELECT r.repo_id, r.name, r.description, r.html_url, r.default_branch,
948937
r.is_fork, r.is_archived, r.stars, r.forks, r.open_issues,
949938
r.size_kb, r.created_at, r.pushed_at,
950939
r.commit_count, r.pr_count, r.merged_pr_count, r.issue_count,
951940
r.contributor_count, r.topics, r.total_language_bytes
952941
FROM github.v_gh_repo_summary r
953942
WHERE {where}
954-
ORDER BY r.commit_count DESC""",
955-
params,
943+
ORDER BY r.commit_count DESC
944+
LIMIT ?""",
945+
[*params, limit],
956946
).fetchall()
957947

948+
# Batch-load languages for all repos to avoid N+1 queries
949+
repo_ids = [repo["repo_id"] for repo in repos]
950+
langs_by_repo: dict[int, list[dict]] = {}
951+
if repo_ids:
952+
ph = ",".join("?" * len(repo_ids))
953+
lang_rows = conn.execute(
954+
f"SELECT repo_id, language, bytes FROM github.gh_repo_language WHERE repo_id IN ({ph}) ORDER BY bytes DESC",
955+
repo_ids,
956+
).fetchall()
957+
for lr in lang_rows:
958+
langs_by_repo.setdefault(lr["repo_id"], []).append({"language": lr["language"], "bytes": lr["bytes"]})
959+
958960
results = []
959961
for repo in repos:
960962
r = dict(repo)
961-
# Add language breakdown
962-
langs = conn.execute(
963-
"SELECT language, bytes FROM github.gh_repo_language "
964-
"WHERE repo_id = (SELECT repo_id FROM github.gh_repo WHERE name = ?) "
965-
"ORDER BY bytes DESC",
966-
(r["name"],),
967-
).fetchall()
968-
r["languages"] = _rows_to_dicts(langs)
963+
rid = r.pop("repo_id")
964+
r["languages"] = langs_by_repo.get(rid, [])
969965
results.append(r)
970966

971967
return json.dumps({"repos": results, "count": len(results)}, default=str)
@@ -991,9 +987,7 @@ def search_github_commits(
991987

992988
conn = _get_conn()
993989
if not _db_attached(conn, "github"):
994-
return json.dumps(
995-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
996-
)
990+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
997991

998992
limit = min(limit, MAX_QUERY_ROWS)
999993
conditions, params = [], []
@@ -1024,9 +1018,7 @@ def search_github_commits(
10241018
LIMIT ?""",
10251019
[*params, limit],
10261020
).fetchall()
1027-
return json.dumps(
1028-
{"commits": _rows_to_dicts(rows), "count": len(rows)}, default=str
1029-
)
1021+
return json.dumps({"commits": _rows_to_dicts(rows), "count": len(rows)}, default=str)
10301022

10311023

10321024
@mcp.tool(
@@ -1048,9 +1040,7 @@ def search_github_prs(
10481040

10491041
conn = _get_conn()
10501042
if not _db_attached(conn, "github"):
1051-
return json.dumps(
1052-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
1053-
)
1043+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
10541044

10551045
limit = min(limit, MAX_QUERY_ROWS)
10561046
conditions, params = [], []
@@ -1109,9 +1099,7 @@ def search_github_issues(
11091099

11101100
conn = _get_conn()
11111101
if not _db_attached(conn, "github"):
1112-
return json.dumps(
1113-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
1114-
)
1102+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
11151103

11161104
limit = min(limit, MAX_QUERY_ROWS)
11171105
conditions, params = [], []
@@ -1155,9 +1143,7 @@ def github_code_stats(repo: str | None = None) -> str:
11551143
"""
11561144
conn = _get_conn()
11571145
if not _db_attached(conn, "github"):
1158-
return json.dumps(
1159-
{"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"}
1160-
)
1146+
return json.dumps({"error": "github.db not attached. Run: uv run scripts/fetch_github.py --org YOUR_ORG"})
11611147

11621148
result: dict = {}
11631149

scripts/fetch_github.py

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,7 @@ def fetch_repos(conn: sqlite3.Connection, org: str, now: str) -> list[dict]:
551551
return repos
552552

553553

554-
def fetch_languages(
555-
conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str
556-
) -> None:
554+
def fetch_languages(conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str) -> None:
557555
"""Fetch language breakdown for a repo."""
558556
langs = gh_api_simple(f"/repos/{org}/{name}/languages")
559557
if not langs or not isinstance(langs, dict):
@@ -566,13 +564,9 @@ def fetch_languages(
566564
)
567565

568566

569-
def fetch_contributors(
570-
conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str
571-
) -> None:
567+
def fetch_contributors(conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str) -> None:
572568
"""Fetch contributors for a repo."""
573-
contribs = gh_api_simple(
574-
f"/repos/{org}/{name}/contributors?per_page=100", paginate=True
575-
)
569+
contribs = gh_api_simple(f"/repos/{org}/{name}/contributors?per_page=100", paginate=True)
576570
if not contribs or not isinstance(contribs, list):
577571
return
578572
for c in contribs:
@@ -639,9 +633,7 @@ def fetch_prs(
639633
since: str | None = None,
640634
) -> None:
641635
"""Fetch pull requests for a repo."""
642-
endpoint = (
643-
f"/repos/{org}/{name}/pulls?per_page=100&state=all&sort=updated&direction=desc"
644-
)
636+
endpoint = f"/repos/{org}/{name}/pulls?per_page=100&state=all&sort=updated&direction=desc"
645637
prs = gh_api_simple(endpoint, paginate=True)
646638
if not prs or not isinstance(prs, list):
647639
return
@@ -711,9 +703,7 @@ def fetch_prs(
711703
print(f" {fetched} PRs")
712704

713705

714-
def fetch_pr_reviews(
715-
conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str
716-
) -> None:
706+
def fetch_pr_reviews(conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str) -> None:
717707
"""Fetch reviews for all PRs in a repo that don't have reviews yet."""
718708
# Get PRs that have no reviews stored
719709
prs = conn.execute(
@@ -726,9 +716,7 @@ def fetch_pr_reviews(
726716

727717
review_count = 0
728718
for pr in prs:
729-
reviews = gh_api_simple(
730-
f"/repos/{org}/{name}/pulls/{pr['number']}/reviews?per_page=100"
731-
)
719+
reviews = gh_api_simple(f"/repos/{org}/{name}/pulls/{pr['number']}/reviews?per_page=100")
732720
if not reviews or not isinstance(reviews, list):
733721
continue
734722
for rv in reviews:
@@ -758,9 +746,7 @@ def fetch_issues(
758746
since: str | None = None,
759747
) -> None:
760748
"""Fetch issues (excluding PRs) for a repo."""
761-
endpoint = (
762-
f"/repos/{org}/{name}/issues?per_page=100&state=all&sort=updated&direction=desc"
763-
)
749+
endpoint = f"/repos/{org}/{name}/issues?per_page=100&state=all&sort=updated&direction=desc"
764750
if since:
765751
endpoint += f"&since={since}"
766752

@@ -868,9 +854,7 @@ def fetch_releases(conn: sqlite3.Connection, repo_id: int, name: str, org: str,
868854
print(f" {len(releases)} releases")
869855

870856

871-
def fetch_code_frequency(
872-
conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str
873-
) -> None:
857+
def fetch_code_frequency(conn: sqlite3.Connection, repo_id: int, name: str, org: str, now: str) -> None:
874858
"""Fetch weekly code frequency stats for a repo."""
875859
for attempt in range(5):
876860
data = gh_api_simple(f"/repos/{org}/{name}/stats/code_frequency")
@@ -917,9 +901,7 @@ def process_repo(
917901
# Determine incremental since for this repo
918902
repo_since = since
919903
if not full and not since:
920-
row = conn.execute(
921-
"SELECT value FROM _meta WHERE key = ?", (f"last_fetch_{name}",)
922-
).fetchone()
904+
row = conn.execute("SELECT value FROM _meta WHERE key = ?", (f"last_fetch_{name}",)).fetchone()
923905
if row:
924906
repo_since = row[0]
925907
print(f" Incremental since {repo_since}")
@@ -963,9 +945,7 @@ def main() -> None:
963945
parser = argparse.ArgumentParser(description="Fetch GitHub org data into github.db")
964946
parser.add_argument("--repo", help="Fetch a single repo by name")
965947
parser.add_argument("--since", help="Fetch from date (ISO 8601, e.g. 2026-03-01)")
966-
parser.add_argument(
967-
"--full", action="store_true", help="Ignore _meta, fetch all history"
968-
)
948+
parser.add_argument("--full", action="store_true", help="Ignore _meta, fetch all history")
969949
parser.add_argument(
970950
"--skip-commits",
971951
action="store_true",
@@ -994,19 +974,15 @@ def main() -> None:
994974
break
995975
if not target:
996976
target = repo_data
997-
skipped = process_repo(
998-
conn, target, args.org, now, args.since, args.skip_commits, args.full
999-
)
977+
skipped = process_repo(conn, target, args.org, now, args.since, args.skip_commits, args.full)
1000978
all_skipped.extend(skipped)
1001979
else:
1002980
# Fetch all repos
1003981
repos = fetch_repos(conn, args.org, now)
1004982
conn.commit()
1005983
for repo in repos:
1006984
try:
1007-
skipped = process_repo(
1008-
conn, repo, args.org, now, args.since, args.skip_commits, args.full
1009-
)
985+
skipped = process_repo(conn, repo, args.org, now, args.since, args.skip_commits, args.full)
1010986
all_skipped.extend(skipped)
1011987
except KeyboardInterrupt:
1012988
print("\nInterrupted — committing pending data...")

scripts/fetch_pricing.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,7 @@ def _extract_ondemand_prices(terms: dict, sku: str) -> list[dict]:
239239
"""Extract OnDemand price dimensions for a given SKU."""
240240
results = []
241241
on_demand = terms.get("OnDemand", {}).get(sku, {})
242-
for _term_key, term_details in (
243-
on_demand.items() if isinstance(on_demand, dict) else []
244-
):
242+
for _term_key, term_details in on_demand.items() if isinstance(on_demand, dict) else []:
245243
for _dim_key, dim in term_details.get("priceDimensions", {}).items():
246244
price_str = dim.get("pricePerUnit", {}).get("USD", "0")
247245
try:
@@ -286,9 +284,7 @@ def fetch_aws_pricing(regions: list[str], now: str) -> list[dict]:
286284
try:
287285
# Download to temp file to handle large files (EC2 ~150MB/region)
288286
with tempfile.NamedTemporaryFile(suffix=".json", delete=True) as tmp:
289-
with httpx.stream(
290-
"GET", url, timeout=300, follow_redirects=True
291-
) as resp:
287+
with httpx.stream("GET", url, timeout=300, follow_redirects=True) as resp:
292288
resp.raise_for_status()
293289
total = 0
294290
for chunk in resp.iter_bytes(chunk_size=1024 * 1024):
@@ -321,9 +317,7 @@ def fetch_aws_pricing(regions: list[str], now: str) -> list[dict]:
321317
continue
322318

323319
product_fields = parse_product(product)
324-
product_desc = (
325-
attrs.get("usagetype", "") + " " + attrs.get("operation", "")
326-
).strip()
320+
product_desc = (attrs.get("usagetype", "") + " " + attrs.get("operation", "")).strip()
327321

328322
for dim in _extract_ondemand_prices(terms, sku):
329323
row = {
@@ -495,9 +489,7 @@ def fetch_rosa_instances(now: str) -> list[dict]:
495489
for node in nodes_data.get("items", []):
496490
labels = node.get("metadata", {}).get("labels", {})
497491
node_name = node.get("metadata", {}).get("name", "")
498-
instance_type = labels.get(
499-
"node.kubernetes.io/instance-type", "unknown"
500-
)
492+
instance_type = labels.get("node.kubernetes.io/instance-type", "unknown")
501493
az = labels.get("topology.kubernetes.io/zone", "")
502494

503495
role = "worker"
@@ -603,12 +595,8 @@ def upsert_rosa_instances(conn: sqlite3.Connection, rows: list[dict]) -> int:
603595

604596
def main() -> None:
605597
parser = argparse.ArgumentParser(description="Fetch cloud pricing into pricing.db")
606-
parser.add_argument(
607-
"--aws-only", action="store_true", help="Fetch AWS pricing only"
608-
)
609-
parser.add_argument(
610-
"--claude-only", action="store_true", help="Fetch Claude pricing only"
611-
)
598+
parser.add_argument("--aws-only", action="store_true", help="Fetch AWS pricing only")
599+
parser.add_argument("--claude-only", action="store_true", help="Fetch Claude pricing only")
612600
parser.add_argument("--rosa-only", action="store_true", help="ROSA discovery only")
613601
parser.add_argument("--skip-rosa", action="store_true", help="Skip ROSA discovery")
614602
parser.add_argument(

0 commit comments

Comments
 (0)