Skip to content
Merged
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
6 changes: 3 additions & 3 deletions coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions interrogate_badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ test = [
"coverage-badge",
"pytest",
"pytest-cov",
"setuptools<82.0.0",
]
docs = [
"furo>=2025.12.19",
Expand Down
5 changes: 5 additions & 0 deletions src/sw_metadata_bot/analysis_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ def is_previous_issue_open(previous_record: dict[str, object]) -> bool:
if state in {"closed", "close"}:
return False

# If the previous analysis already closed the issue, treat it as closed
# regardless of whether previous_issue_state was persisted.
if previous_record.get("action") == "closed":
return False

issue_url = previous_record.get("issue_url") or previous_record.get(
"previous_issue_url"
)
Expand Down
1 change: 1 addition & 0 deletions src/sw_metadata_bot/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def publish_analysis(analysis_root: Path) -> None:
issue_client.close_issue(issue_url)

record["issue_url"] = issue_url
record["previous_issue_state"] = "closed"
record["dry_run"] = False
record["issue_persistence"] = "posted"
record.pop("simulated_issue_url", None)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_incremental.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,17 @@ def test_no_findings_closes_open_issue():
)
assert decision.action == "close"
assert decision.reason == "no_findings_close_open_issue"


def test_no_findings_already_closed_issue_stops():
"""Stop without repeat action when issue was already closed in previous analysis."""
decision = incremental.evaluate(
previous_exists=True,
unsubscribed=False,
repo_updated=True,
has_findings=False,
identical_findings=True,
previous_issue_open=False,
)
assert decision.action == "stop"
assert decision.reason == "no_findings"
45 changes: 45 additions & 0 deletions tests/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,51 @@
from sw_metadata_bot import analysis_runtime, commit_lookup, pipeline
from sw_metadata_bot import publish as publish_module

# ---------------------------------------------------------------------------
# is_previous_issue_open
# ---------------------------------------------------------------------------


def test_is_previous_issue_open_false_when_action_closed():
"""Return False when the previous record action is closed, regardless of issue_url."""
record = {
"action": "closed",
"issue_url": "https://github.com/example/repo/issues/1",
"issue_persistence": "posted",
}
assert analysis_runtime.is_previous_issue_open(record) is False


def test_is_previous_issue_open_false_when_previous_issue_state_closed():
"""Return False when previous_issue_state is explicitly closed."""
record = {
"action": "closed",
"issue_url": "https://github.com/example/repo/issues/1",
"issue_persistence": "posted",
"previous_issue_state": "closed",
}
assert analysis_runtime.is_previous_issue_open(record) is False


def test_is_previous_issue_open_true_for_posted_open_issue():
"""Return True when an issue was posted and no closing signal exists."""
record = {
"action": "created",
"issue_url": "https://github.com/example/repo/issues/2",
"issue_persistence": "posted",
}
assert analysis_runtime.is_previous_issue_open(record) is True


def test_is_previous_issue_open_false_for_simulated_issue():
"""Return False for simulated (dry-run) issues that were never posted."""
record = {
"action": "simulated_created",
"issue_url": "https://github.com/example/repo/issues/3",
"issue_persistence": "simulated",
}
assert analysis_runtime.is_previous_issue_open(record) is False


def _write_config(tmp_path, **overrides):
"""Write a minimal config and return its path."""
Expand Down
Loading
Loading