Skip to content

Commit 881b9b9

Browse files
committed
Add a "Refresh Scan" button action in Scan list and Scan tab
Signed-off-by: tdruez <[email protected]>
1 parent 8e62f70 commit 881b9b9

File tree

6 files changed

+58
-5
lines changed

6 files changed

+58
-5
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ Release notes
33

44
### Version 5.5.0-dev
55

6+
- Add UI to refresh a package scan.
7+
https://github.com/aboutcode-org/dejacode/issues/423
8+
69
- Update ProductPackage "unknown" license during "Scan all Packages".
710
Only "unknown" licenses are updated.
811
Products with a is_locked configuration status are excluded.

component_catalog/templates/component_catalog/includes/scan_actions_list.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,11 @@
2020
</a>
2121
</li>
2222
{% endif %}
23+
{% if scan.refresh_url %}
24+
<li class="list-inline-item"{% if not show_btn_label %} data-bs-toggle="tooltip"{% endif %} data-bs-title="Refresh Scan">
25+
<a class="btn btn-outline-dark btn-sm" href="{{ scan.refresh_url }}">
26+
<i class="fa-solid fa-rotate-right"></i>{% if show_btn_label %} Refresh Scan{% endif %}
27+
</a>
28+
</li>
29+
{% endif %}
2330
</ul>
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<strong class="ms-1">{{ scan.runs.0.status|title }}</strong>
22
{% include 'component_catalog/includes/scan_status.html' with status=scan.runs.0.status only %}
33
<div class="text-center mt-2">
4-
{% include 'component_catalog/includes/scan_actions_list.html' with scan=scan only %}
4+
{% if scan.runs.0.status != "running" %}
5+
{% include 'component_catalog/includes/scan_actions_list.html' with scan=scan only %}
6+
{% endif %}
57
</div>

component_catalog/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from component_catalog.views import get_scan_progress_htmx_view
2727
from component_catalog.views import package_create_ajax_view
2828
from component_catalog.views import package_scan_view
29+
from component_catalog.views import refresh_scan_view
2930
from component_catalog.views import send_scan_data_as_file_view
3031
from dje.views import DataspacedDeleteView
3132
from dje.views import ExportCycloneDXBOMView
@@ -147,6 +148,11 @@
147148
delete_scan_view,
148149
name="scan_delete",
149150
),
151+
path(
152+
"scans/<uuid:project_uuid>/refresh/",
153+
refresh_scan_view,
154+
name="scan_refresh",
155+
),
150156
path(
151157
"scans/",
152158
ScanListView.as_view(),

component_catalog/views.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,25 @@ def delete_scan_view(request, project_uuid):
16701670
return redirect("component_catalog:scan_list")
16711671

16721672

1673+
@login_required
1674+
def refresh_scan_view(request, project_uuid):
1675+
user = request.user
1676+
dataspace = user.dataspace
1677+
if not dataspace.enable_package_scanning:
1678+
raise Http404
1679+
1680+
scancodeio = ScanCodeIO(dataspace)
1681+
response = scancodeio.refresh_scan(str(project_uuid))
1682+
1683+
if response.status_code != 200:
1684+
raise Http404("Scan could not be refreshed.")
1685+
1686+
messages.success(request, "Refresh Scan started.")
1687+
if referer := request.META.get("HTTP_REFERER"):
1688+
return redirect(referer)
1689+
return redirect("component_catalog:scan_list")
1690+
1691+
16731692
class ScanListView(
16741693
LoginRequiredMixin,
16751694
AddPackagePermissionMixin,
@@ -1719,13 +1738,15 @@ def get_context_data(self, **kwargs):
17191738

17201739
scans = []
17211740
for scan in context_data["object_list"]:
1741+
scan_uuid = scan.get("uuid")
17221742
package_download_url = get_package_download_url(scan)
17231743
package = packages_by_url.get(package_download_url)
17241744
scan["package"] = package
1745+
scan["created_date"] = parse_datetime(scan.get("created_date"))
17251746
scan["view_url"] = f"{package.details_url}#scan" if package else None
17261747
scan["download_result_url"] = get_scan_results_as_file_url(scan)
1727-
scan["created_date"] = parse_datetime(scan.get("created_date"))
1728-
scan["delete_url"] = reverse("component_catalog:scan_delete", args=[scan.get("uuid")])
1748+
scan["delete_url"] = reverse("component_catalog:scan_delete", args=[scan_uuid])
1749+
scan["refresh_url"] = reverse("component_catalog:scan_refresh", args=[scan_uuid])
17291750
scans.append(scan)
17301751

17311752
context_data.update(
@@ -2360,6 +2381,7 @@ def scan_status_fields(self, scan):
23602381
scan_status_fields = []
23612382
scan_run = scan.get("runs", [{}])[-1]
23622383
status = scan_run.get("status")
2384+
scan_uuid = scan.get("uuid")
23632385
issue_statuses = ["failure", "stale", "stopped"]
23642386
completed_statuses = ["success", *issue_statuses]
23652387

@@ -2404,17 +2426,20 @@ def scan_status_fields(self, scan):
24042426
filename = package.filename or package.package_url_filename
24052427
download_result_url = reverse(
24062428
"component_catalog:scan_data_as_file",
2407-
args=[scan.get("uuid"), quote_plus(filename)],
2429+
args=[scan_uuid, quote_plus(filename)],
24082430
)
24092431

24102432
delete_url = None
2433+
refresh_url = None
24112434
if status in completed_statuses:
2412-
delete_url = reverse("component_catalog:scan_delete", args=[scan.get("uuid")])
2435+
delete_url = reverse("component_catalog:scan_delete", args=[scan_uuid])
2436+
refresh_url = reverse("component_catalog:scan_refresh", args=[scan_uuid])
24132437

24142438
field_context = {
24152439
"scan": {
24162440
"download_result_url": download_result_url,
24172441
"delete_url": delete_url,
2442+
"refresh_url": refresh_url,
24182443
}
24192444
}
24202445
scan_status_fields.append(

dejacode_toolkit/scancodeio.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ def delete_scan(self, detail_url):
160160
logger.debug(f"{self.label} [Exception] {exception}")
161161
return False
162162

163+
def refresh_scan(self, project_uuid):
164+
reset_url = self.get_scan_action_url(project_uuid, "reset")
165+
logger.debug(f"{self.label}: refresh scan reset_url={reset_url}")
166+
data = {
167+
"keep_input": True,
168+
"restore_pipelines": True,
169+
"execute_now": True,
170+
}
171+
return self.session.post(url=reset_url, json=data, timeout=self.default_timeout)
172+
163173
@staticmethod
164174
def get_status_from_scan_results(scan_results):
165175
status = ""

0 commit comments

Comments
 (0)