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
14 changes: 14 additions & 0 deletions src/psrt_ghsa_bot/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import csv
import datetime
import os
import re
import typing

import urllib3
Expand Down Expand Up @@ -101,6 +102,19 @@ def apply_to_repo(

print(f" 📋 Processing {ghsa_id} (state: {state})")

# If the summary contains '[CLOSE]', '[CLOSED]', '[COMPLETE]',
# or '[COMPLETED]' then we can close the ticket.
summary = security_advisory.get("summary", "")
if re.search(r"\[(?:CLOSED?|COMPLETED?)\]", summary.upper()) is not None:
github.rest.security_advisories.update_repository_advisory(
owner=owner,
repo=repo,
ghsa_id=ghsa_id,
data={"state": "closed"},
)
print(f" 📋 Closed {ghsa_id}")
continue

# Maintain a dictionary of updates to make and then submit them all at once.
patch_data = {}

Expand Down
32 changes: 31 additions & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ def cve_reserve_response(cve_id, year):
}


def _create_advisory_dict(state, cve_id, collaborating_teams):
def _create_advisory_dict(state, cve_id, collaborating_teams, summary=""):
"""Helper to create a security advisory dictionary."""
return {
"ghsa_id": "GHSA-xxxx-xxxx-xxxx",
"state": state,
"summary": summary,
"cve_id": cve_id,
"collaborating_teams": [{"slug": team} for team in collaborating_teams],
"collaborating_users": [{"login": "octocat", "id": 1, "type": "User"}],
Expand Down Expand Up @@ -177,6 +178,35 @@ def test_update_collaborating_users() -> None:
)


@pytest.mark.parametrize(
"summary",
[
"[CLOSE] perl is better than Python",
"[CLOSED] 0.1 + 0.2 is broken?!?!?!?!?!",
"[COMPLETE] some boring security thing",
"fix soemthing in datetime module [COMPLETED]",
"blah blah [closed] lowercase blah",
],
)
def test_closes_advisory_with_close_or_complete_tag(summary) -> None:
security_advisory = _create_advisory_dict("triage", None, [], summary=summary)

github = mock.Mock()
cve_api = mock.Mock()

with mock.patch("psrt_ghsa_bot.app.get_repository_advisories") as get_repo_advs:
get_repo_advs.return_value = [security_advisory]

app.apply_to_repo(github, "owner", "repo", cve_api)

github.rest.security_advisories.update_repository_advisory.assert_called_once_with(
owner="owner",
repo="repo",
ghsa_id="GHSA-xxxx-xxxx-xxxx",
data={"state": "closed"},
)


def test_load_psrt_members_from_devguide() -> None:
with mock.patch("psrt_ghsa_bot.app.urllib3.request") as urllib3_request:
resp = mock.Mock()
Expand Down
Loading