deploy
This commit is contained in:
67
tests/test_analysis.py
Normal file
67
tests/test_analysis.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from agent import RepoFile, _analyze_repository, _redact_secrets
|
||||
from a2a_pack.context import LLMCreds
|
||||
|
||||
|
||||
def test_analysis_detects_security_dependency_tests_docs_and_scores():
|
||||
files = [
|
||||
RepoFile(
|
||||
path="app.py",
|
||||
size=80,
|
||||
sha="a",
|
||||
category="source",
|
||||
text="DEBUG = True\nAPI_KEY='abcdef1234567890'\n# TODO fix auth\n",
|
||||
lines=["DEBUG = True", "API_KEY='abcdef1234567890'", "# TODO fix auth", ""],
|
||||
),
|
||||
RepoFile(
|
||||
path="requirements.txt",
|
||||
size=30,
|
||||
sha="b",
|
||||
category="package/dependency",
|
||||
text="fastapi\nuvicorn==0.30.0\n",
|
||||
lines=["fastapi", "uvicorn==0.30.0", ""],
|
||||
),
|
||||
RepoFile(
|
||||
path="Dockerfile",
|
||||
size=30,
|
||||
sha="c",
|
||||
category="Docker/container",
|
||||
text="FROM python\n",
|
||||
lines=["FROM python", ""],
|
||||
),
|
||||
]
|
||||
tree_entries = [
|
||||
{"path": "app.py", "type": "blob"},
|
||||
{"path": "requirements.txt", "type": "blob"},
|
||||
{"path": "Dockerfile", "type": "blob"},
|
||||
]
|
||||
classified = {
|
||||
"counts_by_category": {"source": 1, "package/dependency": 1, "Docker/container": 1, "tests": 0, "docs": 0, "CI/CD": 0},
|
||||
"tree": [],
|
||||
"categories": {},
|
||||
"total_entries": 3,
|
||||
"total_files": 3,
|
||||
}
|
||||
report = _analyze_repository(
|
||||
repo_meta={"owner": {"login": "octo"}, "name": "demo", "full_name": "octo/demo", "default_branch": "main"},
|
||||
ref="main",
|
||||
branches=[],
|
||||
tree_entries=tree_entries,
|
||||
classified=classified,
|
||||
files=files,
|
||||
skipped=[],
|
||||
limits={"max_files": 100, "max_bytes": 1000, "max_file_bytes": 1000},
|
||||
llm_creds=LLMCreds(base_url="", api_key="", model="", source="platform"),
|
||||
)
|
||||
categories = {f["category"] for f in report["findings"]}
|
||||
assert "security/config" in categories
|
||||
assert "dependency" in categories
|
||||
assert "tests" in categories
|
||||
assert "docs" in categories
|
||||
assert report["scorecard"]["total"] < 90
|
||||
assert any(c["path"] == "app.py" and "REDACTED" in c["snippet"] for f in report["findings"] for c in f["citations"])
|
||||
|
||||
|
||||
def test_redacts_secret_like_values():
|
||||
text = "API_KEY=sk_test_1234567890abcdef"
|
||||
assert "sk_test_1234567890abcdef" not in _redact_secrets(text)
|
||||
assert "<REDACTED>" in _redact_secrets(text)
|
||||
72
tests/test_inspector.py
Normal file
72
tests/test_inspector.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from agent import (
|
||||
RepoFile,
|
||||
_citation,
|
||||
_recommendation,
|
||||
_redact_secrets,
|
||||
_score,
|
||||
classify_path,
|
||||
)
|
||||
|
||||
|
||||
def test_file_classification_core_categories():
|
||||
assert classify_path("src/app.py") == "source"
|
||||
assert classify_path(".github/workflows/ci.yml") == "CI/CD"
|
||||
assert classify_path("Dockerfile") == "Docker/container"
|
||||
assert classify_path("tests/test_app.py") == "tests"
|
||||
assert classify_path("README.md") == "docs"
|
||||
assert classify_path("package-lock.json") == "package/dependency"
|
||||
assert classify_path("infra/main.tf") == "infra/IaC"
|
||||
assert classify_path("scripts/deploy.sh") == "scripts"
|
||||
assert classify_path(".env.example") == "hidden/dotfiles"
|
||||
|
||||
|
||||
def test_citation_extracts_line_range_and_redacts_secret():
|
||||
f = RepoFile(
|
||||
path="config.py",
|
||||
sha="abc",
|
||||
size=50,
|
||||
category="source",
|
||||
text="SAFE=1\nAPI_KEY='supersecretvalue12345'\nEND=1",
|
||||
lines=["SAFE=1", "API_KEY='supersecretvalue12345'", "END=1"],
|
||||
)
|
||||
c = _citation(f, 2)
|
||||
assert c["path"] == "config.py"
|
||||
assert c["line_start"] == 2
|
||||
assert "supersecretvalue12345" not in c["snippet"]
|
||||
assert "<REDACTED>" in c["snippet"]
|
||||
|
||||
|
||||
def test_redact_secret_patterns():
|
||||
text = "token = ghp_abcdefghijklmnopqrstuvwxyz1234567890 and password=abc123456789xyz"
|
||||
redacted = _redact_secrets(text)
|
||||
assert "ghp_abcdefghijklmnopqrstuvwxyz" not in redacted
|
||||
assert "abc123456789xyz" not in redacted
|
||||
assert "<REDACTED>" in redacted
|
||||
|
||||
|
||||
def test_scoring_penalizes_missing_repo_capabilities():
|
||||
score = _score(
|
||||
findings=[{"severity": "high", "category": "security/config"}],
|
||||
file_paths={"src/app.py", "package.json"},
|
||||
categories={"tests": 0, "docs": 0, "CI/CD": 0},
|
||||
skipped=[],
|
||||
)
|
||||
assert 0 <= score["total"] <= 100
|
||||
assert score["sub_scores"]["security"] < 100
|
||||
assert score["sub_scores"]["testing"] < 100
|
||||
assert score["sub_scores"]["docs"] < 100
|
||||
|
||||
|
||||
def test_issue_payload_generation_contains_citations():
|
||||
rec = _recommendation(
|
||||
"medium",
|
||||
"Add .dockerignore",
|
||||
"Prevent unwanted files from entering Docker build context.",
|
||||
[{"path": ".dockerignore", "line_start": None, "line_end": None, "snippet": "No .dockerignore found."}],
|
||||
"low",
|
||||
"medium",
|
||||
["docker", "security"],
|
||||
)
|
||||
assert rec["issue_payload"]["title"] == "Add .dockerignore"
|
||||
assert "No .dockerignore found" in rec["issue_payload"]["body"]
|
||||
assert "docker" in rec["issue_payload"]["labels"]
|
||||
Reference in New Issue
Block a user