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
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@
## 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-07-26 - O(N) string processing bottleneck
**Learning:** In `scripts/ci/redact_sensitive_log.py`, processing character-by-character using `.append()` in a `while` loop was found to be incredibly slow for long inputs. Advancing the cursor inside a helper function on match-failure using single increments caused severe overhead.
**Action:** When scrubbing text for secrets, batch non-matching segments using string slicing (`text[last_append:cursor]`) rather than character-by-character appending. Furthermore, ensure the cursor-consuming helper returns its next index position on failure, skipping over irrelevant words entirely instead of stalling.
Comment on lines +46 to +48
11 changes: 9 additions & 2 deletions scripts/ci/redact_sensitive_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,21 @@ def _redact_assignments(text: str) -> str:
"""Redact sensitive key/value assignments without backtracking regexes."""
output: list[str] = []
cursor = 0
last_append = 0
while cursor < len(text):
match = _consume_sensitive_assignment(text, cursor)
if match is None:
output.append(text[cursor])
cursor += 1
continue
replacement, cursor = match
replacement, next_cursor = match
if cursor > last_append:
output.append(text[last_append:cursor])
output.append(replacement)
cursor = next_cursor
last_append = cursor

if last_append < len(text):
output.append(text[last_append:])
return "".join(output)


Expand Down
35 changes: 35 additions & 0 deletions tests/test_redact_sensitive_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest
from scripts.ci.redact_sensitive_log import _consume_sensitive_assignment, _redact_assignments, redact_text
Comment on lines +1 to +2

def test_consume_sensitive_assignment():
text = "api_key='123' token=secret"
res1, cursor = _consume_sensitive_assignment(text, 0)
assert res1 == "api_key=[REDACTED]"
assert cursor == 13

# Ensure it skips whitespace and correctly captures next
res2, cursor2 = _consume_sensitive_assignment(text, 14)
assert res2 == "token=[REDACTED]"

def test_redact_assignments():
text = "api_key='123' and something else token=secret"
res = _redact_assignments(text)
assert res == "api_key=[REDACTED] and something else token=[REDACTED]"

def test_consume_sensitive_assignment_no_match():
text = "not_sensitive='123'"
res = _consume_sensitive_assignment(text, 0)
assert res is None

def test_redact_text_integration():
text = 'some text api_key="secret_value" more text'
res = redact_text(text)
assert res == 'some text api_key=[REDACTED] more text'

def test_redact_main_coverage(monkeypatch, capsys):
import io
monkeypatch.setattr("sys.stdin", io.StringIO("api_key='123'"))
from scripts.ci.redact_sensitive_log import main
assert main() == 0
captured = capsys.readouterr()
assert captured.out == "api_key=[REDACTED]"
Loading