Skip to content

Commit

Permalink
Keep the InputSource objects when using reset on Projects #1536 (#1549)
Browse files Browse the repository at this point in the history
* Keep the InputSource objects when using ``reset`` on Projects #1536

Signed-off-by: tdruez <[email protected]>

* Remove connectivity requirement for a unit test

Signed-off-by: tdruez <[email protected]>

---------

Signed-off-by: tdruez <[email protected]>
  • Loading branch information
tdruez authored Jan 20, 2025
1 parent ce227cd commit 54e63b6
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 59 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ v34.9.4 (unreleased)
sheets with a dedicated VULNERABILITIES sheet.
https://github.com/aboutcode-org/scancode.io/issues/1519

- Keep the InputSource objects when using ``reset`` on Projects.
https://github.com/aboutcode-org/scancode.io/issues/1536

- Add a ``report`` management command that allows to generate XLSX reports for
multiple projects at once using labels and searching by project name.
https://github.com/aboutcode-org/scancode.io/issues/1524
Expand Down
10 changes: 6 additions & 4 deletions scanpipe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,14 +640,14 @@ def archive(self, remove_input=False, remove_codebase=False, remove_output=False
self.is_archived = True
self.save(update_fields=["is_archived"])

def delete_related_objects(self):
def delete_related_objects(self, keep_input=False):
"""
Delete all related object instances using the private `_raw_delete` model API.
This bypass the objects collection, cascade deletions, and signals.
It results in a much faster objects deletion, but it needs to be applied in the
correct models order as the cascading event will not be triggered.
Note that this approach is used in Django's `fast_deletes` but the scanpipe
models are cannot be fast-deleted as they have cascades and relations.
models cannot be fast-deleted as they have cascades and relations.
"""
# Use default `delete()` on the DiscoveredPackage model, as the
# `codebase_resources (ManyToManyField)` records need to collected and
Expand All @@ -667,9 +667,11 @@ def delete_related_objects(self):
self.discovereddependencies,
self.codebaseresources,
self.runs,
self.inputsources,
]

if not keep_input:
relationships.append(self.inputsources)

for qs in relationships:
count = qs.all()._raw_delete(qs.db)
deleted_counter[qs.model._meta.label] = count
Expand All @@ -695,7 +697,7 @@ def reset(self, keep_input=True):
"""
self._raise_if_run_in_progress()

self.delete_related_objects()
self.delete_related_objects(keep_input=keep_input)

work_directories = [
self.codebase_path,
Expand Down
34 changes: 24 additions & 10 deletions scanpipe/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from scanpipe.models import DiscoveredDependency
from scanpipe.models import DiscoveredPackage
from scanpipe.models import Project
from scanpipe.models import ProjectMessage
from scanpipe.tests.pipelines.do_nothing import DoNothing
from scanpipe.tests.pipelines.download_inputs import DownloadInput
from scanpipe.tests.pipelines.profile_step import ProfileStep
Expand All @@ -47,12 +48,12 @@
mocked_now = mock.Mock(now=lambda: datetime(2010, 10, 10, 10, 10, 10))


def make_project(name=None, **extra):
def make_project(name=None, **data):
name = name or str(uuid.uuid4())[:8]
return Project.objects.create(name=name, **extra)
return Project.objects.create(name=name, **data)


def make_resource_file(project, path, **extra):
def make_resource_file(project, path, **data):
return CodebaseResource.objects.create(
project=project,
path=path,
Expand All @@ -61,30 +62,43 @@ def make_resource_file(project, path, **extra):
type=CodebaseResource.Type.FILE,
is_text=True,
tag=path.split("/")[0],
**extra,
**data,
)


def make_resource_directory(project, path, **extra):
def make_resource_directory(project, path, **data):
return CodebaseResource.objects.create(
project=project,
path=path,
name=path.split("/")[-1],
type=CodebaseResource.Type.DIRECTORY,
tag=path.split("/")[0],
**extra,
**data,
)


def make_package(project, package_url, **extra):
package = DiscoveredPackage(project=project, **extra)
def make_package(project, package_url, **data):
package = DiscoveredPackage(project=project, **data)
package.set_package_url(package_url)
package.save()
return package


def make_dependency(project, **extra):
return DiscoveredDependency.objects.create(project=project, **extra)
def make_dependency(project, **data):
return DiscoveredDependency.objects.create(project=project, **data)


def make_message(project, **data):
if "model" not in data:
data["model"] = str(uuid.uuid4())[:8]

if "severity" not in data:
data["severity"] = ProjectMessage.Severity.ERROR

return ProjectMessage.objects.create(
project=project,
**data,
)


resource_data1 = {
Expand Down
10 changes: 2 additions & 8 deletions scanpipe/tests/pipes/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
from scanpipe import pipes
from scanpipe.models import CodebaseResource
from scanpipe.models import Project
from scanpipe.models import ProjectMessage
from scanpipe.pipes import flag
from scanpipe.pipes import output
from scanpipe.tests import FIXTURES_REGEN
from scanpipe.tests import make_dependency
from scanpipe.tests import make_message
from scanpipe.tests import make_package
from scanpipe.tests import make_resource_file
from scanpipe.tests import mocked_now
Expand Down Expand Up @@ -206,13 +206,7 @@ def test_scanpipe_pipes_outputs_to_xlsx(self):
call_command("loaddata", fixtures, **{"verbosity": 0})

project = Project.objects.get(name="asgiref")
ProjectMessage.objects.create(
project=project,
severity=ProjectMessage.Severity.ERROR,
description="Error",
model="Model",
details={},
)
make_message(project, description="Error")
make_resource_file(
project=project, path="path/file1.ext", status=flag.REQUIRES_REVIEW
)
Expand Down
10 changes: 2 additions & 8 deletions scanpipe/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
from scanpipe.pipes.input import copy_input
from scanpipe.pipes.output import JSONResultsGenerator
from scanpipe.tests import dependency_data1
from scanpipe.tests import make_message
from scanpipe.tests import make_package
from scanpipe.tests import make_project
from scanpipe.tests import make_resource_file
Expand Down Expand Up @@ -795,13 +796,7 @@ def test_scanpipe_api_project_action_relations_filterset(self):

def test_scanpipe_api_project_action_messages(self):
url = reverse("project-messages", args=[self.project1.uuid])
ProjectMessage.objects.create(
project=self.project1,
severity=ProjectMessage.Severity.ERROR,
description="Error",
model="ModelName",
details={},
)
make_message(self.project1, description="Error")

response = self.csrf_client.get(url)
self.assertEqual(1, response.data["count"])
Expand All @@ -812,7 +807,6 @@ def test_scanpipe_api_project_action_messages(self):
message = response.data["results"][0]
self.assertEqual("error", message["severity"])
self.assertEqual("Error", message["description"])
self.assertEqual("ModelName", message["model"])
self.assertEqual({}, message["details"])

def test_scanpipe_api_project_action_file_content(self):
Expand Down
Loading

0 comments on commit 54e63b6

Please sign in to comment.