Skip to content

Commit 5de8cbe

Browse files
authored
Refactor the Webhook.get_payload to use Serializers #1325 (#1326)
Signed-off-by: tdruez <tdruez@nexb.com>
1 parent f5e7810 commit 5de8cbe

File tree

6 files changed

+108
-25
lines changed

6 files changed

+108
-25
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ v34.7.1 (unreleased)
1818
The `package_uid` is now included in each BOM Component as a property.
1919
https://github.com/nexB/scancode.io/issues/1316
2020

21+
- Add ``results_url`` and ``summary_url`` on the API ProjectSerializer.
22+
https://github.com/nexB/scancode.io/issues/1325
23+
2124
v34.7.0 (2024-07-02)
2225
--------------------
2326

scanpipe/api/serializers.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from django.apps import apps
2424

2525
from rest_framework import serializers
26+
from rest_framework.reverse import reverse
2627
from taggit.serializers import TaggitSerializer
2728
from taggit.serializers import TagListSerializerField
2829

@@ -144,6 +145,7 @@ class Meta:
144145

145146
class ProjectSerializer(
146147
ExcludeFromListViewMixin,
148+
SerializerExcludeFieldsMixin,
147149
PipelineChoicesMixin,
148150
TaggitSerializer,
149151
serializers.ModelSerializer,
@@ -177,6 +179,8 @@ class ProjectSerializer(
177179
discovered_dependencies_summary = serializers.SerializerMethodField()
178180
codebase_relations_summary = serializers.SerializerMethodField()
179181
labels = TagListSerializerField(required=False)
182+
results_url = serializers.SerializerMethodField()
183+
summary_url = serializers.SerializerMethodField()
180184

181185
class Meta:
182186
model = Project
@@ -210,8 +214,9 @@ class Meta:
210214
"discovered_packages_summary",
211215
"discovered_dependencies_summary",
212216
"codebase_relations_summary",
217+
"results_url",
218+
"summary_url",
213219
)
214-
215220
exclude_from_list_view = [
216221
"settings",
217222
"input_root",
@@ -258,6 +263,16 @@ def validate_input_urls(self, value):
258263
"""Add support for providing multiple URLs in a single string."""
259264
return [url for entry in value for url in entry.split()]
260265

266+
def get_action_url(self, obj, action_name):
267+
request = self.context.get("request")
268+
return reverse(f"project-{action_name}", kwargs={"pk": obj.pk}, request=request)
269+
270+
def get_results_url(self, obj):
271+
return self.get_action_url(obj, "results")
272+
273+
def get_summary_url(self, obj):
274+
return self.get_action_url(obj, "summary")
275+
261276
def create(self, validated_data):
262277
"""
263278
Create a new `project` with `upload_file` and `pipeline` as optional.

scanpipe/models.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,20 +3807,25 @@ def __str__(self):
38073807
return str(self.uuid)
38083808

38093809
def get_payload(self, pipeline_run):
3810-
return {
3811-
"project": {
3812-
"uuid": self.project.uuid,
3813-
"name": self.project.name,
3814-
"input_sources": self.project.get_inputs_with_source(),
3815-
},
3816-
"run": {
3817-
"uuid": pipeline_run.uuid,
3818-
"pipeline_name": pipeline_run.pipeline_name,
3819-
"status": pipeline_run.status,
3820-
"scancodeio_version": pipeline_run.scancodeio_version,
3821-
},
3810+
"""Return the Webhook payload generated from project and pipeline_run data."""
3811+
from scanpipe.api.serializers import ProjectSerializer
3812+
from scanpipe.api.serializers import RunSerializer
3813+
3814+
project_serializer = ProjectSerializer(
3815+
instance=self.project,
3816+
exclude_fields=("url", "runs"),
3817+
)
3818+
run_serializer = RunSerializer(
3819+
instance=pipeline_run,
3820+
exclude_fields=("url", "project"),
3821+
)
3822+
payload = {
3823+
"project": project_serializer.data,
3824+
"run": run_serializer.data,
38223825
}
38233826

3827+
return payload
3828+
38243829
def deliver(self, pipeline_run):
38253830
"""Deliver this Webhook by sending a POST request to the `target_url`."""
38263831
payload = self.get_payload(pipeline_run)

scanpipe/tests/pipes/test_scancode.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,8 @@ def test_scanpipe_pipes_scancode_extract_archive_vmimage_qcow2(self):
143143
self.assertEqual(sorted(expected), sorted(results))
144144

145145
else:
146-
expected = {
147-
str(input_location): [
148-
"Unable to read kernel at: /boot/vmlinuz-6.5.0-1022-azure.\n"
149-
"libguestfs requires the kernel executable to be readable.\n"
150-
"This is the case by default on most Linux distributions except on "
151-
"Ubuntu.\nPlease follow the ExtractCode installation instructions "
152-
"in the README.rst at:\n"
153-
"https://github.com/nexB/extractcode/blob/main/README.rst '\n"
154-
]
155-
}
156-
self.assertEqual(expected, errors)
146+
expected = "libguestfs requires the kernel executable to be readable"
147+
self.assertIn(expected, errors[str(input_location)][0])
157148

158149
def test_scanpipe_pipes_scancode_get_resource_info(self):
159150
input_location = str(self.data / "aboutcode" / "notice.NOTICE")

scanpipe/tests/test_api.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ def test_scanpipe_api_project_detail(self):
186186
self.assertEqual(1, response.data["package_count"])
187187
self.assertEqual(1, response.data["dependency_count"])
188188
self.assertEqual(1, response.data["relation_count"])
189+
self.assertEqual(
190+
f"http://testserver/api/projects/{self.project1.uuid}/results/",
191+
response.data["results_url"],
192+
)
193+
self.assertEqual(
194+
f"http://testserver/api/projects/{self.project1.uuid}/summary/",
195+
response.data["summary_url"],
196+
)
189197

190198
expected = {"": 1}
191199
self.assertEqual(expected, response.data["codebase_resources_summary"])

scanpipe/tests/test_models.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,7 +1895,7 @@ def test_scanpipe_codebase_resource_model_walk_method_problematic_filenames(self
18951895
self.assertEqual(expected_paths, result)
18961896

18971897
@mock.patch("requests.post")
1898-
def test_scanpipe_webhook_subscription_deliver_method(self, mock_post):
1898+
def test_scanpipe_webhook_subscription_model_deliver_method(self, mock_post):
18991899
webhook = self.project1.add_webhook_subscription("https://localhost")
19001900
self.assertFalse(webhook.delivered)
19011901
run1 = self.create_run()
@@ -1922,6 +1922,67 @@ def test_scanpipe_webhook_subscription_deliver_method(self, mock_post):
19221922
self.assertTrue(webhook.success)
19231923
self.assertEqual("text", webhook.response_text)
19241924

1925+
def test_scanpipe_webhook_subscription_model_get_payload(self):
1926+
webhook = self.project1.add_webhook_subscription("https://localhost")
1927+
run1 = self.create_run()
1928+
payload = webhook.get_payload(run1)
1929+
1930+
expected = {
1931+
"project": {
1932+
"name": "Analysis",
1933+
"uuid": str(self.project1.uuid),
1934+
"is_archived": False,
1935+
"notes": "",
1936+
"labels": [],
1937+
"settings": {},
1938+
"input_sources": [],
1939+
"input_root": [],
1940+
"output_root": [],
1941+
"next_run": "pipeline",
1942+
"extra_data": {},
1943+
"message_count": 0,
1944+
"resource_count": 0,
1945+
"package_count": 0,
1946+
"dependency_count": 0,
1947+
"relation_count": 0,
1948+
"codebase_resources_summary": {},
1949+
"discovered_packages_summary": {
1950+
"total": 0,
1951+
"with_missing_resources": 0,
1952+
"with_modified_resources": 0,
1953+
},
1954+
"discovered_dependencies_summary": {
1955+
"total": 0,
1956+
"is_runtime": 0,
1957+
"is_optional": 0,
1958+
"is_resolved": 0,
1959+
},
1960+
"codebase_relations_summary": {},
1961+
"results_url": f"/api/projects/{self.project1.uuid}/results/",
1962+
"summary_url": f"/api/projects/{self.project1.uuid}/summary/",
1963+
},
1964+
"run": {
1965+
"pipeline_name": "pipeline",
1966+
"status": run1.status,
1967+
"description": "",
1968+
"selected_groups": None,
1969+
"selected_steps": None,
1970+
"uuid": str(run1.uuid),
1971+
"scancodeio_version": "",
1972+
"task_id": None,
1973+
"task_start_date": None,
1974+
"task_end_date": None,
1975+
"task_exitcode": None,
1976+
"task_output": "",
1977+
"log": "",
1978+
"execution_time": None,
1979+
},
1980+
}
1981+
1982+
del payload["project"]["created_date"]
1983+
del payload["run"]["created_date"]
1984+
self.assertDictEqual(expected, payload)
1985+
19251986
def test_scanpipe_discovered_package_model_extract_purl_data(self):
19261987
package_data = {}
19271988
expected = {

0 commit comments

Comments
 (0)