Skip to content

Commit 0245acc

Browse files
committed
Move tasks from dje module into product_portfolio module #303
Signed-off-by: tdruez <tdruez@nexb.com>
1 parent 821c955 commit 0245acc

6 files changed

Lines changed: 240 additions & 237 deletions

File tree

dje/tasks.py

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
from django.core import management
1717
from django.core.exceptions import ObjectDoesNotExist
1818
from django.core.mail import send_mail
19-
from django.db import transaction
20-
from django.template.defaultfilters import pluralize
2119

2220
from django_rq import job
2321

@@ -118,122 +116,6 @@ def scancodeio_submit_scan(uris, user_uuid, dataspace_uuid):
118116
logger.info(f'uri="{uri}" is not reachable.')
119117

120118

121-
@job
122-
def scancodeio_submit_project(scancodeproject_uuid, user_uuid, pipeline_name):
123-
"""Submit the provided SBOM file to ScanCode.io as an asynchronous task."""
124-
logger.info(
125-
f"Entering scancodeio_submit_project task with "
126-
f"scancodeproject_uuid={scancodeproject_uuid} user_uuid={user_uuid} "
127-
f"pipeline_name={pipeline_name}"
128-
)
129-
130-
DejacodeUser = apps.get_model("dje", "DejacodeUser")
131-
ScanCodeProject = apps.get_model("product_portfolio", "scancodeproject")
132-
scancode_project = ScanCodeProject.objects.get(uuid=scancodeproject_uuid)
133-
134-
try:
135-
user = DejacodeUser.objects.get(uuid=user_uuid)
136-
except ObjectDoesNotExist:
137-
logger.error(f"[scancodeio_submit_project]: User uuid={user_uuid} does not exists.")
138-
return
139-
140-
scancodeio = ScanCodeIO(user.dataspace)
141-
142-
# Create a Project instance on ScanCode.io without immediate execution of the
143-
# pipeline. This allows to get instant feedback from ScanCode.io about the Project
144-
# creation status and its related data, even in SYNC mode.
145-
response = scancodeio.submit_project(
146-
project_name=scancodeproject_uuid,
147-
pipeline_name=pipeline_name,
148-
file_location=scancode_project.input_file.path,
149-
user_uuid=user_uuid,
150-
execute_now=False,
151-
)
152-
153-
if not response:
154-
logger.info("Error submitting the file to ScanCode.io server")
155-
scancode_project.status = ScanCodeProject.Status.FAILURE
156-
msg = "- Error: File could not be submitted to ScanCode.io"
157-
scancode_project.append_to_log(msg, save=True)
158-
return
159-
160-
logger.info("Update the ScanCodeProject instance")
161-
scancode_project.status = ScanCodeProject.Status.SUBMITTED
162-
scancode_project.project_uuid = response.get("uuid")
163-
msg = "- File submitted to ScanCode.io for inspection"
164-
scancode_project.append_to_log(msg, save=True)
165-
166-
# Delay the execution of the pipeline after the ScancodeProject instance was
167-
# properly saved and committed in order to avoid any race conditions.
168-
if runs := response.get("runs"):
169-
logger.info("Start the pipeline run")
170-
transaction.on_commit(lambda: scancodeio.start_pipeline(run_url=runs[0]["url"]))
171-
172-
173-
@job("default", timeout=1200)
174-
def pull_project_data_from_scancodeio(scancodeproject_uuid):
175-
"""
176-
Pull Project data from ScanCode.io as an asynchronous task for the provided
177-
`scancodeproject_uuid`.
178-
"""
179-
logger.info(
180-
f"Entering pull_project_data_from_scancodeio task with "
181-
f"scancodeproject_uuid={scancodeproject_uuid}"
182-
)
183-
184-
ScanCodeProject = apps.get_model("product_portfolio", "scancodeproject")
185-
scancode_project = ScanCodeProject.objects.get(uuid=scancodeproject_uuid)
186-
187-
# Make sure the import is not already in progress,
188-
# or that the import has not completed yet.
189-
if not scancode_project.can_start_import:
190-
logger.error("Cannot start import")
191-
return
192-
193-
# Update the status to prevent from starting the task again
194-
ScanCodeProject.objects.filter(uuid=scancode_project.uuid).update(
195-
status=ScanCodeProject.Status.IMPORT_STARTED
196-
)
197-
198-
if scancode_project.type == scancode_project.ProjectType.LOAD_SBOMS:
199-
notification_verb = "Import SBOM"
200-
else:
201-
notification_verb = "Import packages from ScanCode.io"
202-
203-
try:
204-
created, existing, errors = scancode_project.import_data_from_scancodeio()
205-
except Exception as e:
206-
scancode_project.status = ScanCodeProject.Status.FAILURE
207-
scancode_project.append_to_log(message=str(e), save=True)
208-
scancode_project.notify(verb=notification_verb, description="Import failed.")
209-
return
210-
211-
scancode_project.status = ScanCodeProject.Status.SUCCESS
212-
213-
for object_type, values in created.items():
214-
object_type_plural = f"{object_type}{pluralize(values)}"
215-
object_type_plural = object_type_plural.replace("dependencys", "dependencies")
216-
msg = f"- Imported {len(values)} {object_type_plural}."
217-
scancode_project.append_to_log(msg)
218-
219-
for object_type, values in existing.items():
220-
object_type_plural = f"{object_type}{pluralize(values)}"
221-
object_type_plural = object_type_plural.replace("dependencys", "dependencies")
222-
reason = "already available in the dataspace"
223-
if object_type == "dependency":
224-
reason = "already defined on the product"
225-
msg = f"- {len(values)} {object_type_plural} skipped: {reason}."
226-
scancode_project.append_to_log(msg)
227-
228-
for object_type, values in errors.items():
229-
msg = f"- {len(values)} {object_type} error{pluralize(values)} occurred during import."
230-
scancode_project.append_to_log(msg)
231-
232-
scancode_project.save()
233-
description = "\n".join(scancode_project.import_log)
234-
scancode_project.notify(verb=notification_verb, description=description)
235-
236-
237119
@job("default", timeout="3h")
238120
def update_vulnerabilities():
239121
"""Fetch vulnerabilities for all Dataspaces that enable vulnerablecodedb access."""

product_portfolio/forms.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from component_catalog.models import Component
3535
from component_catalog.programming_languages import PROGRAMMING_LANGUAGES
3636
from dejacode_toolkit.scancodeio import ScanCodeIO
37-
from dje import tasks
3837
from dje.fields import SmartFileField
3938
from dje.forms import ColorCodeFormMixin
4039
from dje.forms import DataspacedAdminForm
@@ -56,6 +55,8 @@
5655
from product_portfolio.models import ProductComponent
5756
from product_portfolio.models import ProductPackage
5857
from product_portfolio.models import ScanCodeProject
58+
from product_portfolio.tasks import pull_project_data_from_scancodeio_task
59+
from product_portfolio.tasks import scancodeio_submit_project_task
5960

6061

6162
class NameVersionValidationFormMixin:
@@ -669,7 +670,7 @@ def submit(self, product, user):
669670
)
670671

671672
transaction.on_commit(
672-
lambda: tasks.scancodeio_submit_project.delay(
673+
lambda: scancodeio_submit_project_task.delay(
673674
scancodeproject_uuid=scancode_project.uuid,
674675
user_uuid=user.uuid,
675676
pipeline_name=self.pipeline_name,
@@ -999,7 +1000,7 @@ def submit(self, product, user):
9991000
)
10001001

10011002
transaction.on_commit(
1002-
lambda: tasks.pull_project_data_from_scancodeio.delay(
1003+
lambda: pull_project_data_from_scancodeio_task.delay(
10031004
scancodeproject_uuid=scancode_project.uuid,
10041005
)
10051006
)

product_portfolio/tasks.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,133 @@
1010

1111
from django.apps import apps
1212
from django.core.exceptions import ObjectDoesNotExist
13+
from django.db import transaction
14+
from django.template.defaultfilters import pluralize
1315

1416
from django_rq import job
1517
from guardian.shortcuts import get_perms as guardian_get_perms
1618

19+
from dejacode_toolkit.scancodeio import ScanCodeIO
20+
1721
logger = logging.getLogger(__name__)
1822

1923

24+
@job
25+
def scancodeio_submit_project_task(scancodeproject_uuid, user_uuid, pipeline_name):
26+
"""Submit the provided SBOM file to ScanCode.io as an asynchronous task."""
27+
logger.info(
28+
f"Entering scancodeio_submit_project task with "
29+
f"scancodeproject_uuid={scancodeproject_uuid} user_uuid={user_uuid} "
30+
f"pipeline_name={pipeline_name}"
31+
)
32+
33+
DejacodeUser = apps.get_model("dje", "DejacodeUser")
34+
ScanCodeProject = apps.get_model("product_portfolio", "scancodeproject")
35+
scancode_project = ScanCodeProject.objects.get(uuid=scancodeproject_uuid)
36+
37+
try:
38+
user = DejacodeUser.objects.get(uuid=user_uuid)
39+
except ObjectDoesNotExist:
40+
logger.error(f"[scancodeio_submit_project]: User uuid={user_uuid} does not exists.")
41+
return
42+
43+
scancodeio = ScanCodeIO(user.dataspace)
44+
45+
# Create a Project instance on ScanCode.io without immediate execution of the
46+
# pipeline. This allows to get instant feedback from ScanCode.io about the Project
47+
# creation status and its related data, even in SYNC mode.
48+
response = scancodeio.submit_project(
49+
project_name=scancodeproject_uuid,
50+
pipeline_name=pipeline_name,
51+
file_location=scancode_project.input_file.path,
52+
user_uuid=user_uuid,
53+
execute_now=False,
54+
)
55+
56+
if not response:
57+
logger.info("Error submitting the file to ScanCode.io server")
58+
scancode_project.status = ScanCodeProject.Status.FAILURE
59+
msg = "- Error: File could not be submitted to ScanCode.io"
60+
scancode_project.append_to_log(msg, save=True)
61+
return
62+
63+
logger.info("Update the ScanCodeProject instance")
64+
scancode_project.status = ScanCodeProject.Status.SUBMITTED
65+
scancode_project.project_uuid = response.get("uuid")
66+
msg = "- File submitted to ScanCode.io for inspection"
67+
scancode_project.append_to_log(msg, save=True)
68+
69+
# Delay the execution of the pipeline after the ScancodeProject instance was
70+
# properly saved and committed in order to avoid any race conditions.
71+
if runs := response.get("runs"):
72+
logger.info("Start the pipeline run")
73+
transaction.on_commit(lambda: scancodeio.start_pipeline(run_url=runs[0]["url"]))
74+
75+
76+
@job("default", timeout=1200)
77+
def pull_project_data_from_scancodeio_task(scancodeproject_uuid):
78+
"""
79+
Pull Project data from ScanCode.io as an asynchronous task for the provided
80+
`scancodeproject_uuid`.
81+
"""
82+
logger.info(
83+
f"Entering pull_project_data_from_scancodeio task with "
84+
f"scancodeproject_uuid={scancodeproject_uuid}"
85+
)
86+
87+
ScanCodeProject = apps.get_model("product_portfolio", "scancodeproject")
88+
scancode_project = ScanCodeProject.objects.get(uuid=scancodeproject_uuid)
89+
90+
# Make sure the import is not already in progress,
91+
# or that the import has not completed yet.
92+
if not scancode_project.can_start_import:
93+
logger.error("Cannot start import")
94+
return
95+
96+
# Update the status to prevent from starting the task again
97+
ScanCodeProject.objects.filter(uuid=scancode_project.uuid).update(
98+
status=ScanCodeProject.Status.IMPORT_STARTED
99+
)
100+
101+
if scancode_project.type == scancode_project.ProjectType.LOAD_SBOMS:
102+
notification_verb = "Import SBOM"
103+
else:
104+
notification_verb = "Import packages from ScanCode.io"
105+
106+
try:
107+
created, existing, errors = scancode_project.import_data_from_scancodeio()
108+
except Exception as e:
109+
scancode_project.status = ScanCodeProject.Status.FAILURE
110+
scancode_project.append_to_log(message=str(e), save=True)
111+
scancode_project.notify(verb=notification_verb, description="Import failed.")
112+
return
113+
114+
scancode_project.status = ScanCodeProject.Status.SUCCESS
115+
116+
for object_type, values in created.items():
117+
object_type_plural = f"{object_type}{pluralize(values)}"
118+
object_type_plural = object_type_plural.replace("dependencys", "dependencies")
119+
msg = f"- Imported {len(values)} {object_type_plural}."
120+
scancode_project.append_to_log(msg)
121+
122+
for object_type, values in existing.items():
123+
object_type_plural = f"{object_type}{pluralize(values)}"
124+
object_type_plural = object_type_plural.replace("dependencys", "dependencies")
125+
reason = "already available in the dataspace"
126+
if object_type == "dependency":
127+
reason = "already defined on the product"
128+
msg = f"- {len(values)} {object_type_plural} skipped: {reason}."
129+
scancode_project.append_to_log(msg)
130+
131+
for object_type, values in errors.items():
132+
msg = f"- {len(values)} {object_type} error{pluralize(values)} occurred during import."
133+
scancode_project.append_to_log(msg)
134+
135+
scancode_project.save()
136+
description = "\n".join(scancode_project.import_log)
137+
scancode_project.notify(verb=notification_verb, description=description)
138+
139+
20140
@job("default", timeout=1200)
21141
def improve_packages_from_purldb_task(product_uuid, user_uuid):
22142
logger.info(

0 commit comments

Comments
 (0)