Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@
## 2026-07-09 - Avoid N+1 API blocking in SBOM aggregator
**Learning:** The `collect_inventories` function in `scripts/ci/sbom_inventory_aggregator.py` was fetching SBOMs from the GitHub dependency graph synchronously for every repository in the organization. For large organizations (up to 500 repos), this N+1 network/CLI bottleneck significantly stalled the aggregation workflow.
**Action:** Use `concurrent.futures.ThreadPoolExecutor` to fetch SBOMs concurrently when multiple repositories are provided, bounded by a `max_workers` limit (e.g., 10) to avoid overwhelming the CLI/API, while preserving the fast serial path for single-item inputs.

## 2024-05-18 - [Optimize redact_sensitive_log O(N^2) bottlenecks]
**Learning:** `_consume_sensitive_assignment` inside `redact_sensitive_log.py` had a severe performance issue because when it checked for sensitive words, it skipped non-matching characters very slowly (only incrementing `cursor` by 1 on failure to find an exact start). Using standard logic to quickly skip sequences and avoid copying slices significantly improves parsing speed on large log texts.
**Action:** Replace `_consume_sensitive_assignment` with a more efficient scanning implementation.
56 changes: 32 additions & 24 deletions scripts/ci/redact_sensitive_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,41 +44,42 @@ def _redact_json(value: Any) -> Any:
return value


def _consume_sensitive_assignment(text: str, start: int) -> tuple[str, int] | None:
"""Return a redacted key/value assignment parsed in linear time."""
def _consume_sensitive_assignment(text: str, start: int) -> tuple[str, int] | int:
"""Return a redacted assignment, or the next index to scan if no match."""
cursor = start
key_quote = ""
if cursor < len(text) and text[cursor] in "\"'":
length = len(text)
if cursor < length and text[cursor] in "\"'":
key_quote = text[cursor]
cursor += 1
key_start = cursor
if cursor >= len(text) or text[cursor] not in KEY_CHARS or text[cursor].isdigit():
return None
while cursor < len(text) and text[cursor] in KEY_CHARS:
if cursor >= length or text[cursor] not in KEY_CHARS or text[cursor].isdigit():
return start + 1
while cursor < length and text[cursor] in KEY_CHARS:
cursor += 1
key = text[key_start:cursor]
if key_quote:
if cursor >= len(text) or text[cursor] != key_quote:
return None
if cursor >= length or text[cursor] != key_quote:
return start + 1
cursor += 1
if not SENSITIVE_KEY_RE.search(key):
return None
while cursor < len(text) and text[cursor].isspace():
return cursor
while cursor < length and text[cursor].isspace():
cursor += 1
if cursor >= len(text) or text[cursor] not in ":=":
return None
if cursor >= length or text[cursor] not in ":=":
return cursor
cursor += 1
while cursor < len(text) and text[cursor].isspace():
while cursor < length and text[cursor].isspace():
cursor += 1
if cursor >= len(text):
return None
if cursor >= length:
return cursor

value_start = cursor
if text[cursor] in "\"'":
value_quote = text[cursor]
cursor += 1
escaped = False
while cursor < len(text):
while cursor < length:
char = text[cursor]
cursor += 1
if escaped:
Expand All @@ -88,25 +89,32 @@ def _consume_sensitive_assignment(text: str, start: int) -> tuple[str, int] | No
elif char == value_quote:
break
else:
while cursor < len(text) and not text[cursor].isspace() and text[cursor] not in ",}":
while cursor < length and not text[cursor].isspace() and text[cursor] not in ",}":
cursor += 1
if cursor == value_start:
return None
return cursor
return text[start:value_start] + REDACTED, cursor


def _redact_assignments(text: str) -> str:
"""Redact sensitive key/value assignments without backtracking regexes."""
output: list[str] = []
cursor = 0
while cursor < len(text):
match = _consume_sensitive_assignment(text, cursor)
if match is None:
output.append(text[cursor])
cursor += 1
last_append = 0
length = len(text)
while cursor < length:
result = _consume_sensitive_assignment(text, cursor)
if isinstance(result, int):
cursor = result
continue
replacement, cursor = match
replacement, next_cursor = result
if cursor > last_append:
output.append(text[last_append:cursor])
output.append(replacement)
cursor = next_cursor
last_append = cursor
if last_append < length:
output.append(text[last_append:])
return "".join(output)


Expand Down
Loading