Skip to content

Add ability to filter by run status #413 #490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ v31.0.0 (next)
- Creation date displayed under the project name
- Add ability to sort by date and name
- Add ability to filter by pipeline type
- Add ability to filter by run status

https://github.com/nexB/scancode.io/issues/413

Expand Down
16 changes: 9 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ PYTHON_EXE?=python3
MANAGE=bin/python manage.py
ACTIVATE?=. bin/activate;
VIRTUALENV_PYZ=etc/thirdparty/virtualenv.pyz
BLACK_ARGS=--exclude="migrations|data|lib|bin|var" .
BLACK_ARGS=--exclude="migrations|data|lib|bin|var"
PYCODESTYLE_ARGS=--max-line-length=88 \
--exclude=lib,thirdparty,docs,bin,migrations,settings.py,data,pipelines,var
# Do not depend on Python to generate the SECRET_KEY
GET_SECRET_KEY=`base64 /dev/urandom | head -c50`
# Customize with `$ make envfile ENV_FILE=/etc/scancodeio/.env`
Expand Down Expand Up @@ -64,11 +66,11 @@ envfile:

isort:
@echo "-> Apply isort changes to ensure proper imports ordering"
bin/isort .
@${ACTIVATE} isort .

black:
@echo "-> Apply black code formatter"
bin/black ${BLACK_ARGS}
@${ACTIVATE} black ${BLACK_ARGS} .

doc8:
@echo "-> Run doc8 validation"
Expand All @@ -78,11 +80,11 @@ valid: isort black doc8

check: doc8
@echo "-> Run pycodestyle (PEP8) validation"
@${ACTIVATE} pycodestyle --max-line-length=88 --exclude=lib,thirdparty,docs,bin,migrations,settings.py,data,pipelines,var .
@${ACTIVATE} pycodestyle ${PYCODESTYLE_ARGS} .
@echo "-> Run isort imports ordering validation"
@${ACTIVATE} isort --check-only .
@echo "-> Run black validation"
@${ACTIVATE} black --check ${BLACK_ARGS}
@${ACTIVATE} black --check ${BLACK_ARGS} .

clean:
@echo "-> Clean the Python env"
Expand Down Expand Up @@ -111,7 +113,7 @@ sqlitedb:
@$(MAKE) migrate

run:
${MANAGE} runserver 8001 --noreload --insecure
${MANAGE} runserver 8001 --insecure --noreload

test:
@echo "-> Run the test suite"
Expand All @@ -122,7 +124,7 @@ worker:

bump:
@echo "-> Bump the version"
bin/bumpver update --no-fetch --patch
@${ACTIVATE} bumpver update --no-fetch --patch

docs:
rm -rf docs/_build/
Expand Down
21 changes: 21 additions & 0 deletions scanpipe/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from scanpipe.models import DiscoveredPackage
from scanpipe.models import Project
from scanpipe.models import ProjectError
from scanpipe.models import Run

scanpipe_app = apps.get_app_config("scanpipe")

Expand Down Expand Up @@ -153,6 +154,18 @@ class ProjectFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
choices=scanpipe_app.get_pipeline_choices(include_blank=False),
widget=BulmaDropdownWidget,
)
status = django_filters.ChoiceFilter(
label="Status",
method="filter_run_status",
choices=[
("not_started", "Not started"),
("queued", "Queued"),
("running", "Running"),
("succeed", "Success"),
("failed", "Failure"),
],
widget=BulmaDropdownWidget,
)

class Meta:
model = Project
Expand All @@ -177,6 +190,14 @@ def __init__(self, data=None, *args, **kwargs):
]
)

def filter_run_status(self, queryset, name, value):
"""
Filter by Run status using the `RunQuerySet` methods.
"""
run_queryset_method = value
run_queryset = getattr(Run.objects, run_queryset_method)()
return queryset.filter(runs__in=run_queryset)


class JSONContainsFilter(django_filters.CharFilter):
"""
Expand Down
10 changes: 8 additions & 2 deletions scanpipe/templates/scanpipe/project_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
<div>
{% include 'scanpipe/includes/breadcrumb.html' %}
{{ filter.form.is_archived }}
{% if filter.is_active %}
<a class="is-grey-link" href="{% url 'project_list' %}">
<i class="fas fa-times"></i> Clear search and filters
</a>
{% endif %}
</div>
<a href="{% url 'project_add' %}" class="button is-link">New Project</a>
</div>
Expand All @@ -31,6 +36,7 @@
</div>
<div>
{% include 'scanpipe/includes/filter_dropdown.html' with filter_form_field=filter.form.pipeline only %}
{% include 'scanpipe/includes/filter_dropdown.html' with filter_form_field=filter.form.status only %}
{% include 'scanpipe/includes/filter_dropdown.html' with filter_form_field=filter.form.sort only %}
</div>
</div>
Expand All @@ -41,8 +47,8 @@
<div class="tile is-ancestor">
<div class="tile is-parent">
<article class="tile is-child box has-text-centered border-dashed">
{% if filter.form.search.value %}
No Projects found. <a href="{% url 'project_list' %}">Clear the search</a>
{% if filter.is_active %}
No Projects found. <a href="{% url 'project_list' %}">Clear search and filters</a>
{% else %}
<a href="{% url 'project_add' %}">New Project</a>
{% endif %}
Expand Down
40 changes: 40 additions & 0 deletions scanpipe/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,57 @@
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
# Visit https://github.com/nexB/scancode.io for support and download.

import uuid

from django.test import TestCase
from django.utils import timezone

from scanpipe.filters import ProjectFilterSet
from scanpipe.filters import ResourceFilterSet
from scanpipe.models import CodebaseResource
from scanpipe.models import Project
from scanpipe.models import Run


class ScanPipeFiltersTest(TestCase):
def setUp(self):
self.project1 = Project.objects.create(name="Analysis")

def test_scanpipe_filters_project_filterset_status(self):
now = timezone.now()
not_started = Project.objects.create(name="not_started")
Run.objects.create(project=not_started)
queued = Project.objects.create(name="queued")
Run.objects.create(project=queued, task_id=uuid.uuid4())
running = Project.objects.create(name="running")
Run.objects.create(project=running, task_start_date=now, task_id=uuid.uuid4())
succeed = Project.objects.create(name="succeed")
Run.objects.create(
project=succeed, task_start_date=now, task_end_date=now, task_exitcode=0
)
failed = Project.objects.create(name="failed")
Run.objects.create(
project=failed, task_start_date=now, task_end_date=now, task_exitcode=1
)

filterset = ProjectFilterSet(data={"status": ""})
self.assertEqual(6, len(filterset.qs))

filterset = ProjectFilterSet(data={"status": "not_started"})
self.assertEqual([not_started], list(filterset.qs))

filterset = ProjectFilterSet(data={"status": "queued"})
self.assertEqual([queued], list(filterset.qs))

filterset = ProjectFilterSet(data={"status": "running"})
self.assertEqual([running], list(filterset.qs))

filterset = ProjectFilterSet(data={"status": "succeed"})
self.assertEqual([succeed], list(filterset.qs))

filterset = ProjectFilterSet(data={"status": "failed"})
self.assertEqual([failed], list(filterset.qs))

def test_scanpipe_filters_filter_queryset_empty_values(self):
resource1 = CodebaseResource.objects.create(
project=self.project1,
Expand Down