diff --git a/backend/kernelCI/settings.py b/backend/kernelCI/settings.py index 2067d7d..675dc70 100644 --- a/backend/kernelCI/settings.py +++ b/backend/kernelCI/settings.py @@ -146,3 +146,14 @@ def get_json_env_var(name, default): # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + + +class DisableMigrations: + def __contains__(self, item): + return True + + def __getitem__(self, item): + return None + + +MIGRATION_MODULES = DisableMigrations() diff --git a/backend/kernelCI/urls.py b/backend/kernelCI/urls.py index 42ec78e..0a586bd 100644 --- a/backend/kernelCI/urls.py +++ b/backend/kernelCI/urls.py @@ -16,8 +16,9 @@ """ from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), + path('api/', include('kernelCI_app.urls')), ] diff --git a/backend/kernelCI_app/serializers.py b/backend/kernelCI_app/serializers.py new file mode 100644 index 0000000..3d8f327 --- /dev/null +++ b/backend/kernelCI_app/serializers.py @@ -0,0 +1,54 @@ +from rest_framework import serializers +from kernelCI_app.models import Checkouts +from kernelCI_app.utils import get_visible_record_config + + +class CheckoutsSerializer(serializers.ModelSerializer): + class Meta: + model = Checkouts + fields = [ + 'field_timestamp', 'id', 'origin', 'tree_name', + 'git_repository_url', 'git_commit_hash', 'git_commit_name', + 'git_repository_branch', 'patchset_files', 'patchset_hash', + 'message_id', 'comment', 'start_time', 'contacts', + 'log_url', 'log_excerpt', 'valid', 'misc' + ] + + +class TreeSerializer(CheckoutsSerializer): + build_status = serializers.SerializerMethodField(method_name="get_build_status") + test_status = serializers.SerializerMethodField(method_name="get_test_status") + tree_name = serializers.SerializerMethodField(method_name="get_tree_name") + + class Meta(CheckoutsSerializer.Meta): + fields = CheckoutsSerializer.Meta.fields + ['build_status', 'test_status'] + + def get_config(self, obj): + return get_visible_record_config('checkouts', obj.id) + + def get_field_from_config(self, obj, field): + config = self.get_config(obj) + return config.get(field) + + def get_tree_name(self, obj): + return self.get_field_from_config(obj, 'tree_name') + + def get_build_status(self, obj): + return { + "valid": obj.valid_builds, + "invalid": obj.invalid_builds, + "null": obj.null_builds, + "total": obj.total_builds + } + + def get_test_status(self, obj): + return { + "fail": obj.fail_tests, + "error": obj.error_tests, + "miss": obj.miss_tests, + "pass": obj.pass_tests, + "done": obj.done_tests, + "skip": obj.skip_tests, + "null": obj.null_tests, + "total": obj.total_tests + } diff --git a/backend/kernelCI_app/urls.py b/backend/kernelCI_app/urls.py new file mode 100644 index 0000000..7084c79 --- /dev/null +++ b/backend/kernelCI_app/urls.py @@ -0,0 +1,7 @@ +from django.urls import path +from kernelCI_app import views + + +urlpatterns = [ + path('tree/', views.TreeView.as_view(), name='tree') +] diff --git a/backend/kernelCI_app/utils.py b/backend/kernelCI_app/utils.py new file mode 100644 index 0000000..74327cf --- /dev/null +++ b/backend/kernelCI_app/utils.py @@ -0,0 +1,46 @@ +def get_visible_records(table_name): + return visible_records.get(table_name, {}) + + +def get_visible_record_ids(table_name): + return list(get_visible_records(table_name).keys()) + + +def get_visible_record_config(table_name, id): + return get_visible_records(table_name).get(id) + + +visible_records = { + "checkouts": { + "broonie:7592653346c84691a16ccd1c115df05c": { + "tree_name": "mainline", + "build_status": {"finished": 160, "total": 182}, + "test_status": {"finished": 182, "total": 182}, + }, + "broonie:170e93ec1178448293bb3b1163b1a4ee": { + "tree_name": "stable", + "build_status": {"finished": 182, "total": 182}, + "test_status": {"finished": 820, "total": 820}, + }, + "broonie:88964264010d43159ffa28bb524be058": { + "tree_name": "stable", + "build_status": {"finished": 160, "total": 182}, + "test_status": {"finished": 642, "total": 820} + }, + "broonie:12f55b2668fb4eca9254bfadad4ee871": { + "tree_name": "stable", + "build_status": {"finished": 182, "total": 182}, + "test_status": {"finished": 820, "total": 820} + }, + "broonie:c4ea3368208f4909b5af51c6a148047d": { + "tree_name": "stable", + "build_status": {"finished": 182, "total": 182}, + "test_status": {"finished": 820, "total": 820} + }, + "broonie:1b17e613a3e94254af6fef1167572d35": { + "tree_name": "stable", + "build_status": {"finished": 182, "total": 182}, + "test_status": {"finished": 820, "total": 820} + }, + } +} diff --git a/backend/kernelCI_app/views.py b/backend/kernelCI_app/views.py index fd0e044..9d80d09 100644 --- a/backend/kernelCI_app/views.py +++ b/backend/kernelCI_app/views.py @@ -1,3 +1,51 @@ -# from django.shortcuts import render +from django.http import JsonResponse +from django.views import View -# Create your views here. +from kernelCI_app.models import Checkouts +from kernelCI_app.serializers import TreeSerializer +from kernelCI_app.utils import get_visible_record_ids + + +class TreeView(View): + + def get(self, _): + checkout_ids = get_visible_record_ids('checkouts') + placeholders = ','.join(['%s'] * len(checkout_ids)) + + checkouts = Checkouts.objects.raw(f""" + SELECT + checkouts.*, + COUNT(CASE WHEN builds.valid = true THEN 1 END) AS valid_builds, + COUNT(CASE WHEN builds.valid = false THEN 1 END) AS invalid_builds, + SUM(CASE WHEN builds.valid IS NULL AND builds.id IS NOT NULL THEN 1 ELSE 0 END) + AS null_builds, + COUNT(builds.id) AS total_builds, + COUNT(CASE WHEN tests.status = 'FAIL' THEN 1 END) AS fail_tests, + COUNT(CASE WHEN tests.status = 'ERROR' THEN 1 END) AS error_tests, + COUNT(CASE WHEN tests.status = 'MISS' THEN 1 END) AS miss_tests, + COUNT(CASE WHEN tests.status = 'PASS' THEN 1 END) AS pass_tests, + COUNT(CASE WHEN tests.status = 'DONE' THEN 1 END) AS done_tests, + COUNT(CASE WHEN tests.status = 'SKIP' THEN 1 END) AS skip_tests, + SUM(CASE WHEN tests.status IS NULL AND tests.id IS NOT NULL THEN 1 ELSE 0 END) + AS null_tests, + COUNT(tests.id) AS total_tests + FROM + checkouts + LEFT JOIN + builds ON builds.checkout_id = checkouts.id + LEFT JOIN + tests ON tests.build_id = builds.id + WHERE + checkouts.id IN ({placeholders}) + GROUP BY + checkouts.id; + """, + checkout_ids + ) + + for c in checkouts: + print('checkout:', c.id, c.valid_builds, c.pass_tests) + + serializer = TreeSerializer(checkouts, many=True) + resp = JsonResponse(serializer.data, safe=False) + return resp