From e04ee2a173c873c0517b8cc2ade50c1118e9c172 Mon Sep 17 00:00:00 2001 From: Murilo Geraldini Date: Wed, 5 Mar 2025 16:29:03 -0300 Subject: [PATCH] feat(build-details-page): add status support Part of #1022 --- backend/kernelCI_app/helpers/build.py | 7 +++++++ backend/kernelCI_app/models.py | 1 + backend/kernelCI_app/typeModels/commonDetails.py | 4 +++- backend/kernelCI_app/typeModels/databases.py | 1 + backend/kernelCI_app/views/buildDetailsView.py | 3 ++- .../src/components/BuildDetails/BuildDetails.tsx | 11 ++++++++--- dashboard/src/types/tree/BuildDetails.tsx | 3 +++ dashboard/src/types/tree/TreeDetails.tsx | 2 +- dashboard/src/utils/status.ts | 4 ++-- dashboard/src/utils/utils.ts | 11 ++++++++--- 10 files changed, 36 insertions(+), 11 deletions(-) diff --git a/backend/kernelCI_app/helpers/build.py b/backend/kernelCI_app/helpers/build.py index b00971c82..917bce07b 100644 --- a/backend/kernelCI_app/helpers/build.py +++ b/backend/kernelCI_app/helpers/build.py @@ -1 +1,8 @@ +import os + build_status_map = {True: "valid", False: "invalid", None: "null"} + + +def map_valid_status_field(field: str) -> str: + is_new_schema = os.getenv("SCHEMA_VERSION", "4") == "5" + return "status" if is_new_schema else "valid" diff --git a/backend/kernelCI_app/models.py b/backend/kernelCI_app/models.py index 6ad501051..cda7c4452 100644 --- a/backend/kernelCI_app/models.py +++ b/backend/kernelCI_app/models.py @@ -70,6 +70,7 @@ class Builds(models.Model): log_url = models.TextField(blank=True, null=True) log_excerpt = models.CharField(max_length=16384, blank=True, null=True) valid = models.BooleanField(blank=True, null=True) + status = models.TextField(blank=True, null=True) misc = models.JSONField(blank=True, null=True) class Meta: diff --git a/backend/kernelCI_app/typeModels/commonDetails.py b/backend/kernelCI_app/typeModels/commonDetails.py index 5341627ac..8e2d8d239 100644 --- a/backend/kernelCI_app/typeModels/commonDetails.py +++ b/backend/kernelCI_app/typeModels/commonDetails.py @@ -15,6 +15,7 @@ Build__ConfigUrl, Build__Compiler, Build__Valid, + Build__Status, Build__LogUrl, Build__StartTime, Build__Duration, @@ -69,7 +70,8 @@ class BuildHistoryItem(BaseModel): misc: Build__Misc config_url: Build__ConfigUrl compiler: Build__Compiler - valid: Build__Valid + valid: Build__Valid = None + status: Build__Status = None duration: Build__Duration log_url: Build__LogUrl start_time: Build__StartTime diff --git a/backend/kernelCI_app/typeModels/databases.py b/backend/kernelCI_app/typeModels/databases.py index 4a9a6bf4a..611e061ce 100644 --- a/backend/kernelCI_app/typeModels/databases.py +++ b/backend/kernelCI_app/typeModels/databases.py @@ -39,6 +39,7 @@ class EnvironmentMisc(BaseModel): type Build__ConfigName = Optional[str] type Build__ConfigUrl = Optional[str] type Build__Valid = Optional[bool] +type Build__Status = Optional[DatabaseStatusValues] type Build__StartTime = Optional[datetime] type Build__Duration = Optional[float] type Build__Compiler = Optional[str] diff --git a/backend/kernelCI_app/views/buildDetailsView.py b/backend/kernelCI_app/views/buildDetailsView.py index 9b1507d20..1f10e1f92 100644 --- a/backend/kernelCI_app/views/buildDetailsView.py +++ b/backend/kernelCI_app/views/buildDetailsView.py @@ -6,6 +6,7 @@ from rest_framework.views import APIView from rest_framework.response import Response from pydantic import ValidationError +from kernelCI_app.helpers.build import map_valid_status_field class BuildDetails(APIView): @@ -26,7 +27,7 @@ def get(self, request, build_id: str) -> Response: "config_name", "config_url", "log_url", - "valid", + map_valid_status_field("valid"), "misc", "input_files", "output_files", diff --git a/dashboard/src/components/BuildDetails/BuildDetails.tsx b/dashboard/src/components/BuildDetails/BuildDetails.tsx index 9f9a55bfa..cf50a634a 100644 --- a/dashboard/src/components/BuildDetails/BuildDetails.tsx +++ b/dashboard/src/components/BuildDetails/BuildDetails.tsx @@ -123,7 +123,7 @@ const BuildDetails = ({ { title: buildDetailsTitle, subtitle: , - leftIcon: , + leftIcon: , eyebrow: formatMessage({ id: 'buildDetails.buildDetails' }), subsections: [ { @@ -173,8 +173,13 @@ const BuildDetails = ({ }, { title: 'global.status', - linkText: getBuildStatus(data.valid).toUpperCase(), - icon: , + linkText: getBuildStatus(data.valid, data.status).toUpperCase(), + icon: ( + + ), }, { title: 'global.architecture', diff --git a/dashboard/src/types/tree/BuildDetails.tsx b/dashboard/src/types/tree/BuildDetails.tsx index 6b02798f8..48e148506 100644 --- a/dashboard/src/types/tree/BuildDetails.tsx +++ b/dashboard/src/types/tree/BuildDetails.tsx @@ -1,3 +1,5 @@ +import type { Status } from '@/types/database'; + export type TBuildDetails = { timestamp: string; id: string; @@ -7,6 +9,7 @@ export type TBuildDetails = { comment?: string; config_name?: string; valid?: boolean; + status?: Status; start_time?: string; duration?: string; compiler?: string; diff --git a/dashboard/src/types/tree/TreeDetails.tsx b/dashboard/src/types/tree/TreeDetails.tsx index f25b34fea..d382a8773 100644 --- a/dashboard/src/types/tree/TreeDetails.tsx +++ b/dashboard/src/types/tree/TreeDetails.tsx @@ -20,7 +20,7 @@ export type AccordionItemBuilds = { date?: string; buildErrors?: number; buildTime?: string | ReactNode; - status: 'pass' | 'fail' | 'null'; + status: Status; kernelImage?: string; buildLogs?: string; kernelConfig?: string; diff --git a/dashboard/src/utils/status.ts b/dashboard/src/utils/status.ts index 7e6e3a8c1..d6b5f7788 100644 --- a/dashboard/src/utils/status.ts +++ b/dashboard/src/utils/status.ts @@ -41,9 +41,9 @@ export const getBuildStatusGroup = ( buildStatus: AccordionItemBuilds['status'], ): StatusGroups => { switch (buildStatus) { - case 'pass': + case 'PASS': return 'success'; - case 'fail': + case 'FAIL': return 'failed'; default: return 'inconclusive'; diff --git a/dashboard/src/utils/utils.ts b/dashboard/src/utils/utils.ts index d81df804f..b3f0e2c06 100644 --- a/dashboard/src/utils/utils.ts +++ b/dashboard/src/utils/utils.ts @@ -13,6 +13,7 @@ import type { StatusCount, } from '@/types/general'; import type { ISummaryItem } from '@/components/Tabs/Summary'; +import type { Status } from '@/types/database'; import { valueOrEmpty } from '@/lib/string'; @@ -132,14 +133,18 @@ const isBuildError = (build_valid: boolean | null): number => { export const getBuildStatus = ( build_valid?: boolean | null, + build_status?: Status, ): AccordionItemBuilds['status'] => { + if (build_status !== undefined && build_status !== null) { + return build_status; + } if (build_valid === true) { - return 'pass'; + return 'PASS'; } if (build_valid === false) { - return 'fail'; + return 'FAIL'; } - return 'null'; + return 'NULL'; }; export const sanitizeBuilds = (