From 8dc98601496654567c04412e8d640021967c02af Mon Sep 17 00:00:00 2001 From: lfjnascimento <luiz.nascimento@profusion.mobi> Date: Thu, 18 Jul 2024 13:49:38 -0300 Subject: [PATCH 1/3] chore: add django-query-builder dependencie --- backend/poetry.lock | 69 +++++++++++++++++++++++++++++++++++++++++- backend/pyproject.toml | 1 + 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index d1d0a53..e2503f6 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -103,6 +103,22 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "django-query-builder" +version = "3.2.0" +description = "Build complex nested queries" +optional = false +python-versions = "*" +files = [ + {file = "django-query-builder-3.2.0.tar.gz", hash = "sha256:e22228cb66305a08b2763a46c028b14c6627e7b31d536c7dd8a1c37c1a1c8c70"}, + {file = "django_query_builder-3.2.0-py2.py3-none-any.whl", hash = "sha256:560ee939533b9e2cdd707a13a9cb79e34599d8455405934d27233532889c8abf"}, +] + +[package.dependencies] +Django = ">=3.2" +fleming = ">=0.6.0" +pytz = ">=2015.6" + [[package]] name = "djangorestframework" version = "3.15.2" @@ -133,6 +149,21 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.12.0,<2.13.0" pyflakes = ">=3.2.0,<3.3.0" +[[package]] +name = "fleming" +version = "0.7.0" +description = "Python helpers for manipulating datetime objects relative to time zones" +optional = false +python-versions = "*" +files = [ + {file = "fleming-0.7.0-py2.py3-none-any.whl", hash = "sha256:9bdd83f8497c19be4e316726b8419be45ab5000c6398876e6aea456676345613"}, + {file = "fleming-0.7.0.tar.gz", hash = "sha256:dd93f95f17f220d8ec3cedc2090b3703d7499e6c723bc9f45eb5f7bda8d75a63"}, +] + +[package.dependencies] +python-dateutil = ">=2.2" +pytz = ">=2013.9" + [[package]] name = "gunicorn" version = "22.0.0" @@ -305,6 +336,42 @@ files = [ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sqlparse" version = "0.5.0" @@ -345,4 +412,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "6bccc453c42238e3cf955bbec77a7e023271de8f9eea93b8df215863476a7a82" +content-hash = "fe5323a273b28a06ad10a51fbfc0a4b214e449b0f61d40e72cb4a9c7753008fa" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 5e4afd9..791f729 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -12,6 +12,7 @@ django = "^5.0.6" djangorestframework = "^3.15.2" gunicorn = "^22.0.0" psycopg = "^3.1.19" +django-query-builder = "^3.2.0" [tool.poetry.group.dev.dependencies] From 4df9528eaaded50d5e3addc5197d374628c4ff1a Mon Sep 17 00:00:00 2001 From: lfjnascimento <luiz.nascimento@profusion.mobi> Date: Thu, 18 Jul 2024 13:50:31 -0300 Subject: [PATCH 2/3] fix: set start_time as DateTimeField --- backend/kernelCI_app/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/kernelCI_app/serializers.py b/backend/kernelCI_app/serializers.py index 334fa57..401c885 100644 --- a/backend/kernelCI_app/serializers.py +++ b/backend/kernelCI_app/serializers.py @@ -74,7 +74,7 @@ class TreeDetailsSerializer(serializers.Serializer): architecture = serializers.CharField() config_name = serializers.CharField() valid = serializers.BooleanField() - start_time = serializers.CharField() + start_time = serializers.DateTimeField() duration = serializers.CharField() compiler = serializers.CharField() config_url = serializers.CharField() From 3835f48d4019066b7128b0cf6cdfc2d831107ec6 Mon Sep 17 00:00:00 2001 From: lfjnascimento <luiz.nascimento@profusion.mobi> Date: Thu, 18 Jul 2024 13:58:57 -0300 Subject: [PATCH 3/3] feat: add filter capabilities to the treeDetails endpoint - now we can use ?filter_<field_name>=<value> to filter the response --- backend/kernelCI_app/views.py | 53 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/backend/kernelCI_app/views.py b/backend/kernelCI_app/views.py index 9816083..841b35f 100644 --- a/backend/kernelCI_app/views.py +++ b/backend/kernelCI_app/views.py @@ -1,8 +1,8 @@ from django.http import JsonResponse from django.views import View - +from querybuilder.query import Query from kernelCI_app.models import Checkouts, Builds -from kernelCI_app.serializers import TreeSerializer, TreeDetailsSerializer +from kernelCI_app.serializers import TreeSerializer from kernelCI_app.utils import get_visible_record_identifiers @@ -108,25 +108,30 @@ def get_test_staus(self, build_id): return {k: getattr(builds[0], k) for k in status_keys} def get(self, request, commit_hash): - builds = Builds.objects.raw( - """ - SELECT - builds.id, builds.architecture, builds.config_name, builds.misc, - builds.config_url, builds.compiler, builds.valid, - builds.start_time, builds.duration, builds.log_url - FROM - builds - INNER JOIN - checkouts ON checkouts.id = builds.checkout_id - WHERE checkouts.git_commit_hash = %s; - """, - [commit_hash] - ) - - for build in builds: - build.test_status = self.get_test_staus(build.id) - - data = TreeDetailsSerializer(builds, many=True).data - summary = self.create_summary(data) - resp = {"builds": data, "summary": summary} - return JsonResponse(resp, safe=False) + build_fields = [ + 'id', 'architecture', 'config_name', 'misc', 'config_url', + 'compiler', 'valid', 'duration', 'log_url', 'start_time'] + checkout_fields = [ + 'git_repository_branch', 'git_repository_url', 'git_repository_branch'] + + query = Query().from_table(Builds, build_fields).join( + 'checkouts', + condition='checkouts.id = builds.checkout_id', + fields=checkout_fields + ).where(git_commit_hash__eq=commit_hash) + + for k in request.GET.keys(): + if k.startswith('filter_'): + field = k[7:] + if field in build_fields or field in checkout_fields: + filter_list = request.GET.getlist(k) + query.where({field: filter_list}) + + records = query.select() + for r in records: + status = self.get_test_staus(r.get('id')) + r['status'] = status + + summary = self.create_summary(records) + + return JsonResponse({"builds": records, "summary": summary}, safe=False)