diff --git a/common/Scripts/worklog.py b/common/Scripts/worklog.py
index 4530b3dbfb0..a1ac03fd623 100755
--- a/common/Scripts/worklog.py
+++ b/common/Scripts/worklog.py
@@ -3,6 +3,7 @@
import html
import json
import os.path
+import re
import subprocess
import sys
import tempfile
@@ -108,6 +109,14 @@ def author(self) -> str:
return str(self._data['commit']['author']['name'])
+ @property
+ def message(self) -> str:
+ return str(self._data['commit']['message'])
+
+ @property
+ def cves(self) -> List[str]:
+ return re.findall(r'CVE-\d{4}-\d{4,7}', self.message)
+
@staticmethod
def __tempfile(ref: str) -> str:
dir = os.path.join(tempfile.gettempdir(), '_solus_worklog')
@@ -283,25 +292,49 @@ def v(self) -> str:
def _successful_builds(self) -> Iterable[Build]:
return [build for build in self.builds if build.status == "OK"]
+ @property
+ def cves(self) -> List[str]:
+ return [cve for build in self._successful_builds
+ for cve in build.commit().cves]
+
def to_tty(self) -> str:
authors = [TTY.url(f'@{build.commit().author}', build.tag_url)
for build in self._successful_builds]
+ cves = [TTY.url(cve, f'https://nvd.nist.gov/vuln/detail/{cve}')
+ for cve in self.cves]
- return (f'{TTY.Green}{self.package}{TTY.Reset} {self.v} ' +
+ line = (f'{TTY.Green}{self.package}{TTY.Reset} {self.v} ' +
f'{TTY.Blue}[{", ".join(authors)}]{TTY.Reset}')
+ if len(cves) > 0:
+ line += f' {TTY.Red}[{", ".join(cves)}]{TTY.Reset}'
+
+ return line
+
def to_md(self) -> str:
authors = [f'[@{build.commit().author}]({build.tag_url})'
for build in self._successful_builds]
+ cves = [f'[{cve}](https://nvd.nist.gov/vuln/detail/{cve})'
+ for cve in self.cves]
+ line = f'**{self.package}** was updated to **{self.v}** ({", ".join(authors)}).'
+
+ if len(cves) > 0:
+ line += f' Includes security fixes for {", ".join(cves)}.'
- return f'**{self.package}** was updated to **{self.v}** ({", ".join(authors)})'
+ return line
def to_html(self) -> str:
authors = [f'@{html.escape(build.commit().author)}'
for build in self._successful_builds]
+ cves = [f'{cve}'
+ for cve in self.cves]
+ line = (f'{html.escape(self.package)} was updated to {html.escape(self.v)} '
+ f'({", ".join(authors)}).')
- return (f'{html.escape(self.package)} was updated to {html.escape(self.v)} '
- f'({", ".join(authors)})')
+ if len(cves) > 0:
+ line += f' Includes security fixes for {", ".join(cves)}.'
+
+ return line
class Builds:
@@ -317,7 +350,7 @@ def all(self) -> List[Build]:
def packages(self) -> List[Build]:
return list({b.pkg: b for b in self.all}.values())
- def updates(self, start: datetime, end: datetime) -> List[Update]:
+ def updates(self, start: datetime, end: datetime, security: bool = False) -> List[Update]:
updates: Dict[str, Update] = {}
for build in self._filter(self.all, start, end):
@@ -326,6 +359,10 @@ def updates(self, start: datetime, end: datetime) -> List[Update]:
else:
updates[build.package] = Update(build)
+ if security:
+ updates = {pkg: update for pkg, update in updates.items()
+ if len(update.cves) > 0}
+
return list(updates.values())
def during(self, start: datetime, end: datetime) -> List[Build]:
@@ -454,6 +491,8 @@ def _items(self, kind: str) -> Sequence[Listable]:
return self.builds.during(self.start, self.end)
case 'updates':
return self.builds.updates(self.start, self.end)
+ case 'security-updates':
+ return self.builds.updates(self.start, self.end, security=True)
case 'commits':
return self.git.commits(self.start, self.end)
case _:
@@ -502,10 +541,11 @@ def _print_item(item: Listable, fmt: str) -> None:
./worklog.py commits '1 days ago'
'''
))
- parser.add_argument('command', type=str, choices=['builds', 'updates', 'commits'],
+ parser.add_argument('command', type=str, choices=['builds', 'updates', 'security-updates', 'commits'],
help='Type of output to show. '
'`builds` shows the builds as produced by the build server, '
'`updates` shows per-package updates based on the build server log and GitHub metadata, '
+ '`security-updates` shows updates with security fixes, '
'`commits` shows the commits from your local copy of the `packages` repository.')
parser.add_argument('after', type=str,
help='Show builds after this date. '