Skip to content

Commit 94a6520

Browse files
authored
Doug/fix pr comment issues (#15)
* Fixed logic for ignoring alerts, diff logic, and consolidation of alerts * New version build * Additional fix for commenting logic
1 parent fa4797b commit 94a6520

File tree

6 files changed

+111
-37
lines changed

6 files changed

+111
-37
lines changed

socketsecurity/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
__author__ = 'socket.dev'
2-
__version__ = '1.0.1'
2+
__version__ = '1.0.3'

socketsecurity/core/__init__.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,13 @@ def compare_sboms(new_scan: list, head_scan: list) -> Diff:
548548
head_packages = Core.create_sbom_dict(head_scan)
549549
new_scan_alerts = {}
550550
head_scan_alerts = {}
551-
551+
consolidated = []
552552
for package_id in new_packages:
553553
purl, package = Core.create_purl(package_id, new_packages)
554-
if package_id not in head_packages and package.direct:
554+
base_purl = f"{purl.ecosystem}/{purl.name}@{purl.version}"
555+
if package_id not in head_packages and package.direct and base_purl not in consolidated:
555556
diff.new_packages.append(purl)
557+
consolidated.append(base_purl)
556558
new_scan_alerts = Core.create_issue_alerts(package, new_scan_alerts, new_packages)
557559
for package_id in head_packages:
558560
purl, package = Core.create_purl(package_id, head_packages)
@@ -633,18 +635,27 @@ def compare_issue_alerts(new_scan_alerts: dict, head_scan_alerts: dict, alerts:
633635
:param alerts: List of new alerts that are only in the new Full Scan
634636
:return:
635637
"""
638+
consolidated_alerts = []
636639
for alert_key in new_scan_alerts:
637640
if alert_key not in head_scan_alerts:
638641
new_alerts = new_scan_alerts[alert_key]
639642
for alert in new_alerts:
643+
alert: Issue
644+
alert_str = f"{alert.purl},{alert.manifests},{alert.type}"
640645
if alert.error or alert.warn:
641-
alerts.append(alert)
646+
if alert_str not in consolidated_alerts:
647+
alerts.append(alert)
648+
consolidated_alerts.append(alert_str)
642649
else:
643650
new_alerts = new_scan_alerts[alert_key]
644651
head_alerts = head_scan_alerts[alert_key]
645652
for alert in new_alerts:
646-
if alert not in head_alerts and (alert.error or alert.warn):
647-
alerts.append(alert)
653+
alert: Issue
654+
alert_str = f"{alert.purl},{alert.manifests},{alert.type}"
655+
if alert not in head_alerts and alert_str not in consolidated_alerts:
656+
if alert.error or alert.warn:
657+
alerts.append(alert)
658+
consolidated_alerts.append(alert_str)
648659
return alerts
649660

650661
@staticmethod

socketsecurity/core/github.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,40 @@ def remove_comment_alerts(comments: dict):
207207
if security_alert is not None:
208208
security_alert: Comment
209209
new_body = Comments.process_security_comment(security_alert, comments)
210+
Github.handle_ignore_reactions(comments)
210211
Github.update_comment(new_body, str(security_alert.id))
212+
213+
@staticmethod
214+
def handle_ignore_reactions(comments: dict) -> None:
215+
for comment in comments["ignore"]:
216+
comment: Comment
217+
if "SocketSecurity ignore" in comment.body:
218+
if not Github.comment_reaction_exists(comment.id):
219+
Github.post_reaction(comment.id)
220+
221+
@staticmethod
222+
def post_reaction(comment_id: int) -> None:
223+
repo = github_repository.rsplit("/", 1)[1]
224+
path = f"repos/{github_repository_owner}/{repo}/issues/comments/{comment_id}/reactions"
225+
payload = {
226+
"content": "+1"
227+
}
228+
payload = json.dumps(payload)
229+
do_request(path, payload=payload, method="POST", headers=headers, base_url=github_api_url)
230+
231+
@staticmethod
232+
def comment_reaction_exists(comment_id: int) -> bool:
233+
repo = github_repository.rsplit("/", 1)[1]
234+
path = f"repos/{github_repository_owner}/{repo}/issues/comments/{comment_id}/reactions"
235+
response = do_request(path, headers=headers, base_url=github_api_url)
236+
exists = False
237+
try:
238+
data = response.json()
239+
for reaction in data:
240+
content = reaction.get("content")
241+
if content is not None and content == ":thumbsup:":
242+
exists = True
243+
except Exception as error:
244+
log.error(f"Unable to get reaction for {comment_id} for PR {pr_number}")
245+
log.error(error)
246+
return exists

socketsecurity/core/messages.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def create_security_alert_table(diff: Diff, md: MdUtils) -> (MdUtils, list, dict
148148
ignore = f"`SocketSecurity ignore {alert.purl}`"
149149
if ignore not in ignore_commands:
150150
ignore_commands.append(ignore)
151-
manifest_str, sources = Messages.create_sources(alert, "console")
151+
manifest_str, source_str = Messages.create_sources(alert)
152152
purl_url = f"[{alert.purl}]({alert.url})"
153153
if alert.error:
154154
emoji = ':no_entry_sign:'
@@ -157,7 +157,7 @@ def create_security_alert_table(diff: Diff, md: MdUtils) -> (MdUtils, list, dict
157157
row = [
158158
alert.title,
159159
purl_url,
160-
", ".join(sources),
160+
source_str,
161161
manifest_str,
162162
emoji
163163
]
@@ -269,14 +269,15 @@ def create_console_security_alert_table(diff: Diff) -> PrettyTable:
269269
[
270270
"Alert",
271271
"Package",
272+
"url",
272273
"Introduced by",
273274
"Manifest File",
274275
"CI Status"
275276
]
276277
)
277278
for alert in diff.new_alerts:
278279
alert: Issue
279-
manifest_str, sources = Messages.create_sources(alert, "console")
280+
manifest_str, source_str = Messages.create_sources(alert, "console")
280281
if alert.error:
281282
state = "block"
282283
elif alert.warn:
@@ -287,27 +288,38 @@ def create_console_security_alert_table(diff: Diff) -> PrettyTable:
287288
state = "ignore"
288289
row = [
289290
alert.title,
291+
alert.purl,
290292
alert.url,
291-
", ".join(sources),
293+
source_str,
292294
manifest_str,
293295
state
294296
]
295297
alert_table.add_row(row)
296298
return alert_table
297299

298300
@staticmethod
299-
def create_sources(alert: Issue, style="md") -> [str, list]:
301+
def create_sources(alert: Issue, style="md") -> [str, str]:
300302
sources = []
301303
manifests = []
302304
for source, manifest in alert.introduced_by:
303-
sources.append(source)
304305
if style == "md":
305-
manifests.append(f"<li>{manifest}</li>")
306+
add_str = f"<li>{manifest}</li>"
307+
source_str = f"<li>{source}</li>"
306308
else:
307-
manifests.append(manifest)
309+
add_str = f"{manifest};"
310+
source_str = f"{source};"
311+
if source_str not in sources:
312+
sources.append(source_str)
313+
if add_str not in manifests:
314+
manifests.append(add_str)
308315
manifest_list = "".join(manifests)
316+
source_list = "".join(sources)
317+
source_list = source_list.rstrip(";")
318+
manifest_list = manifest_list.rstrip(";")
309319
if style == "md":
310320
manifest_str = f"<ul>{manifest_list}</ul>"
321+
sources_str = f"<ul>{source_list}</ul>"
311322
else:
312323
manifest_str = manifest_list
313-
return manifest_str, sources
324+
sources_str = source_list
325+
return manifest_str, sources_str

socketsecurity/core/scm_comments.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ def remove_alerts(comments: dict, new_alerts: list) -> list:
3131
if ignore_all:
3232
break
3333
else:
34-
purl = f"{alert.pkg_name}, {alert.pkg_version}"
35-
purl_star = f"{alert.pkg_name}, *"
34+
full_name = f"{alert.pkg_type}/{alert.pkg_name}"
35+
purl = (full_name, alert.pkg_version)
36+
purl_star = (full_name, "*")
3637
if purl in ignore_commands or purl_star in ignore_commands:
37-
print(f"Alerts for {alert.pkg_name}@{alert.pkg_version} ignored")
38+
log.info(f"Alerts for {alert.pkg_name}@{alert.pkg_version} ignored")
3839
else:
39-
print(f"Adding alert {alert.type} for {alert.pkg_name}@{alert.pkg_version}")
40+
log.info(f"Adding alert {alert.type} for {alert.pkg_name}@{alert.pkg_version}")
4041
alerts.append(alert)
4142
return alerts
4243

@@ -49,16 +50,20 @@ def get_ignore_options(comments: dict) -> [bool, list]:
4950
comment: Comment
5051
first_line = comment.body_list[0]
5152
if not ignore_all and "SocketSecurity ignore" in first_line:
52-
first_line = first_line.lstrip("@")
53-
_, command = first_line.split("SocketSecurity ")
54-
command = command.strip()
55-
if command == "ignore-all":
56-
ignore_all = True
57-
else:
58-
command = command.lstrip("ignore").strip()
59-
name, version = command.split("@")
60-
data = f"{name}, {version}"
61-
ignore_commands.append(data)
53+
try:
54+
first_line = first_line.lstrip("@")
55+
_, command = first_line.split("SocketSecurity ")
56+
command = command.strip()
57+
if command == "ignore-all":
58+
ignore_all = True
59+
else:
60+
command = command.lstrip("ignore").strip()
61+
name, version = command.split("@")
62+
data = (name, version)
63+
ignore_commands.append(data)
64+
except Exception as error:
65+
log.error(f"Unable to process ignore command for {comment}")
66+
log.error(error)
6267
return ignore_all, ignore_commands
6368

6469
@staticmethod
@@ -71,7 +76,7 @@ def is_ignore(pkg_name: str, pkg_version: str, name: str, version: str) -> bool:
7176
@staticmethod
7277
def is_heading_line(line) -> bool:
7378
is_heading_line = True
74-
if line != "|Alert|Package|Introduced by|Manifest File|" and ":---" not in line:
79+
if line != "|Alert|Package|Introduced by|Manifest File|CI|" and ":---" not in line:
7580
is_heading_line = False
7681
return is_heading_line
7782

@@ -86,10 +91,12 @@ def process_security_comment(comment: Comment, comments) -> str:
8691
start = True
8792
lines.append(line)
8893
elif start and "end-socket-alerts-table" not in line and not Comments.is_heading_line(line) and line != '':
89-
title, package, introduced_by, manifest = line.lstrip("|").rstrip("|").split("|")
94+
title, package, introduced_by, manifest, ci = line.lstrip("|").rstrip("|").split("|")
9095
details, _ = package.split("](")
9196
ecosystem, details = details.split("/", 1)
97+
ecosystem = ecosystem.lstrip("[")
9298
pkg_name, pkg_version = details.split("@")
99+
pkg_name = f"{ecosystem}/{pkg_name}"
93100
ignore = False
94101
for name, version in ignore_commands:
95102
if ignore_all or Comments.is_ignore(pkg_name, pkg_version, name, version):
@@ -114,7 +121,7 @@ def check_for_socket_comments(comments: dict):
114121
socket_comments["security"] = comment
115122
elif "socket-overview-comment-actions" in comment.body:
116123
socket_comments["overview"] = comment
117-
elif "SocketSecurity ignore" in comment.body:
124+
elif "SocketSecurity ignore".lower() in comment.body_list[0].lower():
118125
if "ignore" not in socket_comments:
119126
socket_comments["ignore"] = []
120127
socket_comments["ignore"].append(comment)

socketsecurity/socketcli.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from socketsecurity.core.messages import Messages
66
from socketsecurity.core.scm_comments import Comments
77
from socketsecurity.core.git_interface import Git
8-
from git import InvalidGitRepositoryError
8+
from git import InvalidGitRepositoryError, NoSuchPathError
99
import os
1010
import sys
1111
import logging
@@ -245,6 +245,8 @@ def main_code():
245245
except InvalidGitRepositoryError:
246246
is_repo = False
247247
pass
248+
except NoSuchPathError:
249+
raise Exception(f"Unable to find path {target_path}")
248250
# git_repo = None
249251
if repo is None:
250252
log.info("Repo name needs to be set")
@@ -306,11 +308,17 @@ def main_code():
306308
new_security_comment = True
307309
new_overview_comment = True
308310
if len(diff.new_alerts) == 0 or disable_security_issue:
309-
new_security_comment = False
310-
log.debug("No new alerts or security issue comment disabled")
311+
if security_comment is None or security_comment == "":
312+
new_security_comment = False
313+
log.debug("No new alerts or security issue comment disabled")
314+
else:
315+
log.debug("Updated security comment with no new alerts")
311316
if (len(diff.new_packages) == 0 and len(diff.removed_packages) == 0) or disable_overview:
312-
new_overview_comment = False
313-
log.debug("No new/removed packages or Dependency Overview comment disabled")
317+
if overview_comment is None or overview_comment == "":
318+
new_overview_comment = False
319+
log.debug("No new/removed packages or Dependency Overview comment disabled")
320+
else:
321+
log.debug("Updated overview comment with no dependencies")
314322
log.debug(f"Adding comments for {scm_type}")
315323
scm.add_socket_comments(
316324
security_comment,

0 commit comments

Comments
 (0)