Initial curated RepoPulse source from 2524ccc3c1c27739996dccb2b7992989f88cd26d
This commit is contained in:
commit
0adf8ef5d9
90 files changed
+14315
No files matched your search
@@ -0,0 +1,161 @@
|
||||
import json
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
import app.store as store_module
|
||||
from app.scanner import scan_repository
|
||||
from app.store import ScanStore
|
||||
|
||||
|
||||
def test_scan_history_comparison_and_trend(tmp_path: Path) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
(repository / ".gitignore").write_text("*.db\n", encoding="utf-8")
|
||||
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
first = store.save(scan_repository(str(repository)))
|
||||
|
||||
(repository / "app.py").write_text("print('hello')\n", encoding="utf-8")
|
||||
(repository / "tests").mkdir()
|
||||
(repository / "tests" / "test_app.py").write_text("def test_ok():\n assert True\n", encoding="utf-8")
|
||||
second = store.save(scan_repository(str(repository)))
|
||||
|
||||
assert store.get(second.id) == second
|
||||
assert store.recent(1) == [second]
|
||||
assert store.previous_for_repository(second.repository_path, second.id) == first
|
||||
|
||||
comparison = store.compare(second)
|
||||
assert comparison.previous_scan_id == first.id
|
||||
assert comparison.health_score_delta == second.health_score - first.health_score
|
||||
assert comparison.metric_deltas["source_files"] == 2
|
||||
|
||||
trend = store.trend(second.repository_path)
|
||||
assert [item.scan_id for item in trend] == [first.id, second.id]
|
||||
assert trend[-1].health_score == second.health_score
|
||||
|
||||
|
||||
def test_comparison_uses_the_scan_before_the_selected_scan(tmp_path: Path) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
(repository / ".gitignore").write_text("*.db\n", encoding="utf-8")
|
||||
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
first = store.save(scan_repository(str(repository)))
|
||||
second = store.save(scan_repository(str(repository)))
|
||||
third = store.save(scan_repository(str(repository)))
|
||||
|
||||
assert store.previous_for_repository(second.repository_path, second.id) == first
|
||||
assert store.previous_for_repository(third.repository_path, third.id) == second
|
||||
|
||||
|
||||
def test_repository_summary_exposes_compact_remediation_context(tmp_path: Path) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
(repository / ".gitignore").write_text(".env\n", encoding="utf-8")
|
||||
(repository / ".env").write_text("TOKEN=actual-secret-value-123456\n", encoding="utf-8")
|
||||
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
store.save(scan_repository(str(repository)))
|
||||
|
||||
(repository / ".env").unlink()
|
||||
(repository / "app.py").write_text("api_key = 'actual-secret-value-123456'\n", encoding="utf-8")
|
||||
store.save(scan_repository(str(repository)))
|
||||
|
||||
summary = store.list_repositories()[0]
|
||||
|
||||
assert summary.last_scan_blockers == 1
|
||||
assert summary.last_scan_primary_signal is not None
|
||||
assert summary.last_scan_primary_signal.code == "security.secret-assignment"
|
||||
assert summary.last_scan_primary_signal.count == 1
|
||||
assert summary.last_scan_added_findings >= 1
|
||||
assert summary.last_scan_resolved_findings == 1
|
||||
|
||||
|
||||
def test_corrupt_database_is_quarantined_and_recreated(tmp_path: Path) -> None:
|
||||
database = tmp_path / "repopulse.db"
|
||||
database.write_bytes(b"not a sqlite database")
|
||||
|
||||
store = ScanStore(str(database))
|
||||
|
||||
assert store.recent() == []
|
||||
assert list(tmp_path.glob("repopulse.db.corrupt-*"))
|
||||
assert store.database_recovery_status()["status"] == "degraded_recovered"
|
||||
|
||||
|
||||
def test_schema_migration_records_the_durable_backup_artifact(tmp_path: Path) -> None:
|
||||
database = tmp_path / "repopulse.db"
|
||||
initial_store = ScanStore(str(database))
|
||||
with initial_store._connection() as db:
|
||||
db.execute("PRAGMA user_version = 3")
|
||||
|
||||
migrated_store = ScanStore(str(database))
|
||||
|
||||
recorded = migrated_store.get_state("last_schema_migration_backup")
|
||||
assert recorded is not None
|
||||
metadata = json.loads(recorded)
|
||||
assert metadata["from_version"] == 3
|
||||
assert metadata["to_version"] == store_module.SCHEMA_VERSION
|
||||
assert (tmp_path / metadata["backup_file"]).is_file()
|
||||
assert migrated_store.storage_stats()["last_schema_migration_backup"] == recorded
|
||||
|
||||
|
||||
def test_history_is_bounded_per_repository(tmp_path: Path, monkeypatch) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
|
||||
monkeypatch.setattr(store_module, "MAX_HISTORY_PER_REPOSITORY", 2)
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
first = store.save(scan_repository(str(repository)))
|
||||
second = store.save(scan_repository(str(repository)))
|
||||
third = store.save(scan_repository(str(repository)))
|
||||
|
||||
assert [item.id for item in store.recent_for_repository(third.repository_path)] == [third.id, second.id]
|
||||
assert store.get(first.id) is None
|
||||
|
||||
|
||||
def test_retention_compacts_old_detailed_payloads_and_expires_old_snapshots(tmp_path: Path, monkeypatch) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
(repository / ".gitignore").write_text("*.db\n", encoding="utf-8")
|
||||
monkeypatch.setenv("REPOPULSE_FULL_REPORTS_PER_REPOSITORY", "1")
|
||||
monkeypatch.setenv("REPOPULSE_REPORT_RETENTION_DAYS", "30")
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
|
||||
first = store.save(scan_repository(str(repository)))
|
||||
second = store.save(scan_repository(str(repository)))
|
||||
compacted = store.get(first.id)
|
||||
|
||||
assert compacted is not None and compacted.compacted is True
|
||||
assert compacted.findings == []
|
||||
assert store.get(second.id) is not None
|
||||
|
||||
expired = second.model_copy(
|
||||
update={"id": "expired-scan", "scanned_at": datetime.now(UTC) - timedelta(days=31)}
|
||||
)
|
||||
store.save(expired)
|
||||
assert store.get("expired-scan") is None
|
||||
|
||||
|
||||
def test_catalog_summary_uses_denormalized_fields_without_report_json_parsing(tmp_path: Path, monkeypatch) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
repository.mkdir()
|
||||
(repository / "README.md").write_text("# Demo\n", encoding="utf-8")
|
||||
(repository / ".gitignore").write_text("*.db\n", encoding="utf-8")
|
||||
store = ScanStore(str(tmp_path / "repopulse.db"))
|
||||
store.save(scan_repository(str(repository)))
|
||||
|
||||
def fail_if_called(_row):
|
||||
raise AssertionError("catalog list must not parse report_json")
|
||||
|
||||
monkeypatch.setattr(store, "_report_from_row", fail_if_called)
|
||||
summary = store.list_repositories()[0]
|
||||
assert summary.last_scan_id
|
||||
storage = store.storage_stats()
|
||||
assert storage["scan_count"] == 1
|
||||
assert storage["mirror_count"] >= 0
|
||||
assert storage["worktree_count"] >= 0
|
||||
Reference in new issue
Block a user