Skip to content

Commit 797154e

Browse files
Automatically close advisories that have [CLOSED] in the summary
Co-authored-by: Stan Ulbrych <stan@ulbrych.org> Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent f79794d commit 797154e

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

src/psrt_ghsa_bot/app.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import csv
55
import datetime
66
import os
7+
import re
78
import typing
89

910
import urllib3
@@ -101,6 +102,19 @@ def apply_to_repo(
101102

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

105+
# If the summary contains '[CLOSE]', '[CLOSED]', '[COMPLETE]',
106+
# or '[COMPLETED]' then we can close the ticket.
107+
summary = security_advisory.get("summary", "")
108+
if re.search(r"\[(?:CLOSED?|COMPLETED?)\]", summary.upper()) is not None:
109+
github.rest.security_advisories.update_repository_advisory(
110+
owner=owner,
111+
repo=repo,
112+
ghsa_id=ghsa_id,
113+
data={"state": "closed"},
114+
)
115+
print(f" 📋 Closed {ghsa_id}")
116+
continue
117+
104118
# Maintain a dictionary of updates to make and then submit them all at once.
105119
patch_data = {}
106120

tests/test_app.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ def cve_reserve_response(cve_id, year):
3434
}
3535

3636

37-
def _create_advisory_dict(state, cve_id, collaborating_teams):
37+
def _create_advisory_dict(state, cve_id, collaborating_teams, summary=""):
3838
"""Helper to create a security advisory dictionary."""
3939
return {
4040
"ghsa_id": "GHSA-xxxx-xxxx-xxxx",
4141
"state": state,
42+
"summary": summary,
4243
"cve_id": cve_id,
4344
"collaborating_teams": [{"slug": team} for team in collaborating_teams],
4445
"collaborating_users": [{"login": "octocat", "id": 1, "type": "User"}],
@@ -177,6 +178,35 @@ def test_update_collaborating_users() -> None:
177178
)
178179

179180

181+
@pytest.mark.parametrize(
182+
"summary",
183+
[
184+
"[CLOSE] perl is better than Python",
185+
"[CLOSED] 0.1 + 0.2 is broken?!?!?!?!?!",
186+
"[COMPLETE] some boring security thing",
187+
"fix soemthing in datetime module [COMPLETED]",
188+
"blah blah [closed] lowercase blah",
189+
],
190+
)
191+
def test_closes_advisory_with_close_or_complete_tag(summary) -> None:
192+
security_advisory = _create_advisory_dict("triage", None, [], summary=summary)
193+
194+
github = mock.Mock()
195+
cve_api = mock.Mock()
196+
197+
with mock.patch("psrt_ghsa_bot.app.get_repository_advisories") as get_repo_advs:
198+
get_repo_advs.return_value = [security_advisory]
199+
200+
app.apply_to_repo(github, "owner", "repo", cve_api)
201+
202+
github.rest.security_advisories.update_repository_advisory.assert_called_once_with(
203+
owner="owner",
204+
repo="repo",
205+
ghsa_id="GHSA-xxxx-xxxx-xxxx",
206+
data={"state": "closed"},
207+
)
208+
209+
180210
def test_load_psrt_members_from_devguide() -> None:
181211
with mock.patch("psrt_ghsa_bot.app.urllib3.request") as urllib3_request:
182212
resp = mock.Mock()

0 commit comments

Comments
 (0)