Skip to content

Commit 3d33285

Browse files
authored
Refine pipeline choices in the "Add pipeline" modal #1071 (#1072)
Signed-off-by: tdruez <tdruez@nexb.com>
1 parent 6e35324 commit 3d33285

File tree

5 files changed

+72
-9
lines changed

5 files changed

+72
-9
lines changed

CHANGELOG.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
Changelog
22
=========
33

4+
v33.2.0 (unreleased)
5+
--------------------
6+
7+
- Refine pipeline choices in the "Add pipeline" modal based on the project context.
8+
* When there is at least one existing pipeline in the project, the modal now includes
9+
all addon pipelines along with the existing pipeline for selection.
10+
* In cases where no pipelines are assigned to the project, the modal displays all
11+
base (non-addon) pipelines for user selection.
12+
13+
https://github.com/nexB/scancode.io/issues/
14+
415
v33.1.0 (2024-02-02)
516
--------------------
617

scanpipe/forms.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,32 @@ def save(self, project):
158158

159159
class AddPipelineForm(PipelineBaseForm):
160160
pipeline = forms.ChoiceField(
161-
choices=[
162-
(name, pipeline_class.get_summary())
163-
for name, pipeline_class in scanpipe_app.pipelines.items()
164-
],
165161
widget=forms.RadioSelect(),
166162
required=True,
167163
)
168164

165+
def __init__(self, project_runs=None, *args, **kwargs):
166+
super().__init__(*args, **kwargs)
167+
168+
# The pipeline choices are determined based on the project context:
169+
# 1. If no pipelines are assigned to the project:
170+
# Include all base (non-addon) pipelines.
171+
# 2. If at least one pipeline already exists on the project:
172+
# Include all addon pipelines and the existing pipeline (useful for
173+
# potential re-runs in debug mode).
174+
project_run_names = {run.pipeline_name for run in project_runs or []}
175+
176+
pipeline_choices = [
177+
(name, pipeline_class.get_summary())
178+
for name, pipeline_class in scanpipe_app.pipelines.items()
179+
# no pipelines are assigned to the project
180+
if (not project_runs and not pipeline_class.is_addon)
181+
# at least one pipeline already exists on the project
182+
or (project_runs and (name in project_run_names or pipeline_class.is_addon))
183+
]
184+
185+
self.fields["pipeline"].choices = pipeline_choices
186+
169187
def save(self, project):
170188
self.handle_pipeline(project)
171189
return project

scanpipe/templates/scanpipe/modals/add_pipeline_modal.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@
88
<button class="delete" type="button" aria-label="close"></button>
99
</header>
1010
<section class="modal-card-body">
11+
{% if pipeline_runs %}
12+
<div class="message is-info">
13+
<div class="message-body">
14+
<span class="icon width-1 height-1 mr-1">
15+
<i class="fa-solid fa-info-circle"></i>
16+
</span>
17+
<span>
18+
Pipeline selection is <strong>limited to add-ons</strong> as pipelines
19+
have already been assigned to this project.
20+
</span>
21+
</div>
22+
</div>
23+
{% endif %}
1124
<div class="field">
1225
<div class="control">
1326
{% for label, summary in add_pipeline_form.pipeline.field.choices %}

scanpipe/tests/test_forms.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import requests
2929

30+
from scanpipe.forms import AddPipelineForm
3031
from scanpipe.forms import EditInputSourceTagForm
3132
from scanpipe.forms import InputsBaseForm
3233
from scanpipe.forms import ProjectForm
@@ -83,13 +84,33 @@ def test_scanpipe_forms_project_form_name(self):
8384

8485
def test_scanpipe_forms_project_form_pipeline_choices(self):
8586
blank_entry = ("", "---------")
86-
main_pipline = ("scan_codebase", "scan_codebase")
87-
addon_pipline = ("find_vulnerabilities", "find_vulnerabilities")
87+
main_pipeline = ("scan_codebase", "scan_codebase")
88+
addon_pipeline = ("find_vulnerabilities", "find_vulnerabilities")
8889

8990
choices = ProjectForm().fields["pipeline"].choices
9091
self.assertIn(blank_entry, choices)
91-
self.assertIn(main_pipline, choices)
92-
self.assertNotIn(addon_pipline, choices)
92+
self.assertIn(main_pipeline, choices)
93+
self.assertNotIn(addon_pipeline, choices)
94+
95+
def test_scanpipe_forms_add_pipeline_form_pipeline_choices(self):
96+
main_pipeline1 = "scan_codebase"
97+
main_pipeline2 = "scan_single_package"
98+
addon_pipeline = "find_vulnerabilities"
99+
100+
form = AddPipelineForm()
101+
choices = form.fields["pipeline"].choices
102+
pipeline_choices = [choice[0] for choice in choices]
103+
self.assertIn(main_pipeline1, pipeline_choices)
104+
self.assertIn(main_pipeline2, pipeline_choices)
105+
self.assertNotIn(addon_pipeline, pipeline_choices)
106+
107+
self.project1.add_pipeline(pipeline_name=main_pipeline1)
108+
form = AddPipelineForm(project_runs=self.project1.runs.all())
109+
choices = form.fields["pipeline"].choices
110+
pipeline_choices = [choice[0] for choice in choices]
111+
self.assertIn(main_pipeline1, pipeline_choices)
112+
self.assertNotIn(main_pipeline2, pipeline_choices)
113+
self.assertIn(addon_pipeline, pipeline_choices)
93114

94115
def test_scanpipe_forms_project_settings_form_update_name_and_notes(self):
95116
data = {

scanpipe/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ def get_context_data(self, **kwargs):
693693
{
694694
"input_sources": project.get_inputs_with_source(),
695695
"labels": list(project.labels.all()),
696-
"add_pipeline_form": AddPipelineForm(),
696+
"add_pipeline_form": AddPipelineForm(project_runs=pipeline_runs),
697697
"add_inputs_form": AddInputsForm(),
698698
"add_labels_form": AddLabelsForm(),
699699
"edit_input_tag_from": EditInputSourceTagForm(),

0 commit comments

Comments
 (0)