diff --git a/interrogate_badge.svg b/interrogate_badge.svg index f3f8d64..bc91d28 100644 --- a/interrogate_badge.svg +++ b/interrogate_badge.svg @@ -1,5 +1,5 @@ - interrogate: 99.7% + interrogate: 100% @@ -12,8 +12,8 @@ interrogate interrogate - 99.7% - 99.7% + 100% + 100% diff --git a/src/sw_metadata_bot/publish.py b/src/sw_metadata_bot/publish.py index 66f6835..46939ac 100644 --- a/src/sw_metadata_bot/publish.py +++ b/src/sw_metadata_bot/publish.py @@ -164,6 +164,17 @@ def _issue_url_for_publish(record: dict[str, object]) -> str | None: return None +def _issue_is_closed(issue_data: dict[str, object] | None) -> bool: + """Return True when issue data indicates the issue is already closed.""" + if not isinstance(issue_data, dict): + return False + state_value = issue_data.get("state") + return isinstance(state_value, str) and state_value.strip().lower() in { + "closed", + "close", + } + + def _write_per_repo_report( analysis_root: Path, record: dict[str, object], @@ -319,6 +330,16 @@ def issue_client_for_platform(platform: str): ) continue + issue_data = issue_client.get_issue(issue_url) + if action == constants.ACTION_UPDATED_BY_COMMENT and _issue_is_closed( + issue_data + ): + record["action"] = constants.ACTION_SIMULATED_CREATED + record["reason_code"] = "changed_and_issue_closed" + record["previous_issue_url"] = issue_url + record.pop("issue_url", None) + action = constants.ACTION_SIMULATED_CREATED + if action == constants.ACTION_SIMULATED_CREATED: body = _load_publish_body(analysis_root, repo_url) title = "Automated Metadata Quality Report from CodeMetaSoft" diff --git a/tests/test_publish.py b/tests/test_publish.py index cdfd679..908ae7e 100644 --- a/tests/test_publish.py +++ b/tests/test_publish.py @@ -160,6 +160,49 @@ def test_publish_updated_by_comment_posts_comment(tmp_path, monkeypatch): assert record.get("dry_run") is False +def test_publish_closed_issue_opens_new_issue_instead_of_comment(tmp_path, monkeypatch): + """publish creates a new issue when the previous issue is already closed.""" + snapshot_dir = tmp_path / "snapshot" + snapshot_dir.mkdir() + repo_url = "https://github.com/example/repo" + issue_url = f"{repo_url}/issues/5" + + _write_run_report( + snapshot_dir, + records=[ + { + "repo_url": repo_url, + "action": "updated_by_comment", + "platform": "github", + "issue_url": issue_url, + "dry_run": True, + "issue_persistence": "simulated", + } + ], + ) + _write_issue_report(snapshot_dir, repo_url) + + class _ClosedIssueClient(_FakeIssueClient): + def get_issue(self, issue_url: str) -> dict: + return {"state": "closed"} + + fake = _ClosedIssueClient() + _patch_clients(monkeypatch, fake) + + runner = CliRunner() + result = runner.invoke(publish_command, ["--analysis-root", str(snapshot_dir)]) + + assert result.exit_code == 0, result.output + assert len(fake.created) == 1 + assert not fake.commented + + report = json.loads((snapshot_dir / "run_report.json").read_text()) + record = report["records"][0] + assert record["action"] == "created" + assert record["issue_persistence"] == "posted" + assert record.get("dry_run") is False + + def test_publish_closed_closes_issue(tmp_path, monkeypatch): """publish closes the issue for closed records.""" snapshot_dir = tmp_path / "snapshot"