Skip to content

Commit

Permalink
Add support for new Webhook model in API #1325
Browse files Browse the repository at this point in the history
Signed-off-by: tdruez <[email protected]>
  • Loading branch information
tdruez committed Jul 24, 2024
1 parent b086be9 commit ac0550a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
25 changes: 22 additions & 3 deletions scanpipe/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from scanpipe.models import InputSource
from scanpipe.models import Project
from scanpipe.models import ProjectMessage
from scanpipe.models import WebhookSubscription
from scanpipe.models import Run
from scanpipe.pipes import count_group_by

Expand Down Expand Up @@ -143,6 +144,18 @@ class Meta:
]


class WebhookSubscriptionSerializer(serializers.ModelSerializer):
class Meta:
model = WebhookSubscription
fields = [
"target_url",
"trigger_on_each_run",
"include_summary",
"include_results",
"is_active",
]


class ProjectSerializer(
ExcludeFromListViewMixin,
SerializerExcludeFieldsMixin,
Expand All @@ -167,6 +180,7 @@ class ProjectSerializer(
style={"base_template": "textarea.html"},
)
webhook_url = serializers.CharField(write_only=True, required=False)
webhooks = WebhookSubscriptionSerializer(many=True, write_only=True)
next_run = serializers.CharField(source="get_next_run", read_only=True)
runs = RunSerializer(many=True, read_only=True)
input_sources = InputSourceSerializer(
Expand All @@ -192,6 +206,7 @@ class Meta:
"upload_file_tag",
"input_urls",
"webhook_url",
"webhooks",
"created_date",
"is_archived",
"notes",
Expand Down Expand Up @@ -289,6 +304,7 @@ def create(self, validated_data):
pipeline = validated_data.pop("pipeline", [])
execute_now = validated_data.pop("execute_now", False)
webhook_url = validated_data.pop("webhook_url", None)
webhooks = validated_data.pop("webhooks", [])

project = super().create(validated_data)

Expand All @@ -298,12 +314,15 @@ def create(self, validated_data):
for url in input_urls:
project.add_input_source(download_url=url)

if webhook_url:
project.add_webhook_subscription(webhook_url)

for pipeline_name in pipeline:
project.add_pipeline(pipeline_name, execute_now)

if webhook_url:
project.add_webhook_subscription(target_url=webhook_url)

for webhook_data in webhooks:
project.add_webhook_subscription(**webhook_data)

return project


Expand Down
29 changes: 18 additions & 11 deletions scanpipe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,35 +699,33 @@ def clone(
execute_now=False,
):
"""Clone this project using the provided ``clone_name`` as new project name."""
cloned_project = Project.objects.create(
new_project = Project.objects.create(
name=clone_name,
settings=self.settings if copy_settings else {},
)

if labels := self.labels.names():
cloned_project.labels.add(*labels)
new_project.labels.add(*labels)

if copy_inputs:
# Clone the InputSource instances
for input_source in self.inputsources.all():
input_source.pk = None
input_source.project = cloned_project
input_source.save()
input_source.clone(to_project=new_project)
# Copy the files from the input work directory
for input_location in self.inputs():
cloned_project.copy_input_from(input_location)
new_project.copy_input_from(input_location)

if copy_pipelines:
for run in self.runs.all():
cloned_project.add_pipeline(
new_project.add_pipeline(
run.pipeline_name, execute_now, selected_groups=run.selected_groups
)

if copy_subscriptions:
for subscription in self.webhooksubscriptions.all():
cloned_project.add_webhook_subscription(subscription.target_url)
subscription.clone(to_project=new_project)

return cloned_project
return new_project

def _raise_if_run_in_progress(self):
"""
Expand Down Expand Up @@ -1184,12 +1182,12 @@ def add_pipeline(self, pipeline_name, execute_now=False, selected_groups=None):

return run

def add_webhook_subscription(self, target_url):
def add_webhook_subscription(self, **kwargs):
"""
Create a new WebhookSubscription instance with the provided `target_url` for
the current project.
"""
return WebhookSubscription.objects.create(project=self, target_url=target_url)
return WebhookSubscription.objects.create(project=self, **kwargs)

@cached_property
def can_start_pipelines(self):
Expand Down Expand Up @@ -1497,6 +1495,15 @@ class Meta:
def model_fields(cls):
return [field.name for field in cls._meta.get_fields()]

def clone(self, to_project):
"""Clone this instance as a new instance of the provided ``to_project``."""
if to_project == self.project:
raise ValueError("Cannot clone instance into the same project.")

self.pk = None
self.project = to_project
self.save()


class ProjectMessage(UUIDPKModel, ProjectRelatedModel):
"""Stores messages such as errors and exceptions raised during a pipeline run."""
Expand Down
11 changes: 6 additions & 5 deletions scanpipe/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ def test_scanpipe_project_model_clone(self):
new_file_path1.touch()
run1 = self.project1.add_pipeline("analyze_docker_image", selected_groups=["g"])
run2 = self.project1.add_pipeline("find_vulnerabilities")
subscription1 = self.project1.add_webhook_subscription("http://domain.url")
subscription1 = self.project1.add_webhook_subscription(target_url="http://domain.url")

cloned_project = self.project1.clone("cloned project")
self.assertIsInstance(cloned_project, Project)
Expand Down Expand Up @@ -535,7 +535,7 @@ def test_scanpipe_project_model_add_uploads(self):

def test_scanpipe_project_model_add_webhook_subscription(self):
self.assertEqual(0, self.project1.webhooksubscriptions.count())
self.project1.add_webhook_subscription("https://localhost")
self.project1.add_webhook_subscription(target_url="https://localhost")
self.assertEqual(1, self.project1.webhooksubscriptions.count())

def test_scanpipe_project_model_get_next_run(self):
Expand Down Expand Up @@ -1199,7 +1199,7 @@ def test_scanpipe_run_model_append_to_log(self):

@mock.patch("scanpipe.models.WebhookSubscription.deliver")
def test_scanpipe_run_model_deliver_project_subscriptions(self, mock_deliver):
self.project1.add_webhook_subscription("https://localhost")
self.project1.add_webhook_subscription(target_url="https://localhost")
run1 = self.create_run()
run1.deliver_project_subscriptions()
mock_deliver.assert_called_once_with(pipeline_run=run1)
Expand Down Expand Up @@ -1912,7 +1912,8 @@ def test_scanpipe_codebase_resource_model_walk_method_problematic_filenames(self

@mock.patch("requests.post")
def test_scanpipe_webhook_subscription_model_deliver_method(self, mock_post):
webhook = self.project1.add_webhook_subscription("https://localhost")
webhook = self.project1.add_webhook_subscription(target_url="https://localhost")

self.assertFalse(webhook.delivered)
run1 = self.create_run()

Expand All @@ -1939,7 +1940,7 @@ def test_scanpipe_webhook_subscription_model_deliver_method(self, mock_post):
self.assertEqual("text", webhook.response_text)

def test_scanpipe_webhook_subscription_model_get_payload(self):
webhook = self.project1.add_webhook_subscription("https://localhost")
webhook = self.project1.add_webhook_subscription(target_url="https://localhost")
run1 = self.create_run()
payload = webhook.get_payload(run1)

Expand Down

0 comments on commit ac0550a

Please sign in to comment.