This is an automated email from the ASF dual-hosted git repository.

narro pushed a commit to branch feat-8763
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git

commit 6254adba780e8d68f5614ae222b5c18f815275bc
Author: narro wizard <[email protected]>
AuthorDate: Fri Mar 13 03:18:50 2026 +0000

    feat(qa): add is_invalid field to qa_test_case_executions
    
    Add is_invalid boolean field to the domain layer qa_test_case_executions
    table to allow QA teams to flag test executions as invalid due to
    environmental issues, flaky tests, false positives, or false negatives.
    
    Changes:
    - Add IsInvalid field to QaTestCaseExecution domain model
    - Create migration script 
(20260313_add_is_invalid_to_qa_test_case_executions)
    - Register migration in migrationscripts/register.go
    - Update customize service to set default value for is_invalid
    - Update E2E test data to include new column
    
    Resolves #8763
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../domainlayer/qa/qa_test_case_execution.go       |  1 +
 ...13_add_is_invalid_to_qa_test_case_executions.go | 52 ++++++++++++++++++++++
 backend/core/models/migrationscripts/register.go   |  1 +
 .../e2e/import_test_case_execution_test.go         |  2 +
 .../qa_test_case_executions_output.csv             |  8 ++--
 .../qa_test_case_executions_output_incremental.csv | 10 ++---
 backend/plugins/customize/service/service.go       |  4 ++
 7 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/backend/core/models/domainlayer/qa/qa_test_case_execution.go 
b/backend/core/models/domainlayer/qa/qa_test_case_execution.go
index cfab89b6d..178194d9b 100644
--- a/backend/core/models/domainlayer/qa/qa_test_case_execution.go
+++ b/backend/core/models/domainlayer/qa/qa_test_case_execution.go
@@ -33,6 +33,7 @@ type QaTestCaseExecution struct {
        FinishTime   time.Time `gorm:"comment:Test finish time"`
        CreatorId    string    `gorm:"type:varchar(255);comment:Executor ID"`
        Status       string    `gorm:"type:varchar(255);comment:Test execution 
status | PENDING | IN_PROGRESS | SUCCESS | FAILED"` // enum, using string
+       IsInvalid    bool      `gorm:"type:tinyint(1);comment:Flag indicating 
if the test execution result is invalid"`
 }
 
 func (QaTestCaseExecution) TableName() string {
diff --git 
a/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go
 
b/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go
new file mode 100644
index 000000000..ce7656e1e
--- /dev/null
+++ 
b/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go
@@ -0,0 +1,52 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package migrationscripts
+
+import (
+       "github.com/apache/incubator-devlake/core/context"
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/plugin"
+)
+
+var _ plugin.MigrationScript = (*addIsInvalidToQaTestCaseExecution)(nil)
+
+type qaTestCaseExecution20260313 struct {
+       IsInvalid bool
+}
+
+func (qaTestCaseExecution20260313) TableName() string {
+       return "qa_test_case_executions"
+}
+
+type addIsInvalidToQaTestCaseExecution struct{}
+
+func (*addIsInvalidToQaTestCaseExecution) Up(basicRes context.BasicRes) 
errors.Error {
+       db := basicRes.GetDal()
+       if err := db.AutoMigrate(&qaTestCaseExecution20260313{}); err != nil {
+               return err
+       }
+       return nil
+}
+
+func (*addIsInvalidToQaTestCaseExecution) Version() uint64 {
+       return 20260313100000
+}
+
+func (*addIsInvalidToQaTestCaseExecution) Name() string {
+       return "add is_invalid to qa_test_case_executions"
+}
diff --git a/backend/core/models/migrationscripts/register.go 
b/backend/core/models/migrationscripts/register.go
index 5b682b662..9372d8fbd 100644
--- a/backend/core/models/migrationscripts/register.go
+++ b/backend/core/models/migrationscripts/register.go
@@ -136,6 +136,7 @@ func All() []plugin.MigrationScript {
                new(addCqIssueImpacts),
                new(addDueDateToIssues),
                new(createQaTables),
+               new(addIsInvalidToQaTestCaseExecution),
                new(increaseCqIssueComponentLength),
                new(extendFieldSizeForCq),
                new(addIssueFixVerion),
diff --git a/backend/plugins/customize/e2e/import_test_case_execution_test.go 
b/backend/plugins/customize/e2e/import_test_case_execution_test.go
index 92d5750b8..577cf48c5 100644
--- a/backend/plugins/customize/e2e/import_test_case_execution_test.go
+++ b/backend/plugins/customize/e2e/import_test_case_execution_test.go
@@ -71,6 +71,7 @@ func TestImportQaTestCaseExecutionsDataFlow(t *testing.T) {
                        "start_time",
                        "finish_time",
                        "creator_id",
+                       "is_invalid",
                        "status",
                })
        dataflowTester.VerifyTableWithRawData(
@@ -104,6 +105,7 @@ func TestImportQaTestCaseExecutionsDataFlow(t *testing.T) {
                        "start_time",
                        "finish_time",
                        "creator_id",
+                       "is_invalid",
                        "status",
                })
 
diff --git 
a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv
 
b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv
index 1d51d4a0d..cd78e9ec5 100644
--- 
a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv
+++ 
b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv
@@ -1,4 +1,4 @@
-id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
-exec-1,test-qa-project-id,tc-1,2023-03-01T10:00:00.000+00:00,2023-03-01T10:01:00.000+00:00,2023-03-01T10:05:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,,
-exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,FAILED,test-qa-project-id,,,
-exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,,
+id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,is_invalid,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+exec-1,test-qa-project-id,tc-1,2023-03-01T10:00:00.000+00:00,2023-03-01T10:01:00.000+00:00,2023-03-01T10:05:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,,
+exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,0,FAILED,test-qa-project-id,,,
+exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,,
diff --git 
a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv
 
b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv
index e214d734b..90e496a27 100644
--- 
a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv
+++ 
b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv
@@ -1,5 +1,5 @@
-id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
-exec-1,test-qa-project-id,tc-1,2023-03-04T10:00:00.000+00:00,2023-03-04T10:01:00.000+00:00,2023-03-04T10:06:00.000+00:00,csv:CsvAccount:0:user-a,FAILED,test-qa-project-id,,,
-exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,FAILED,test-qa-project-id,,,
-exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,,
-exec-4,test-qa-project-id,tc-3,2023-03-03T10:00:00.000+00:00,2023-03-03T10:01:00.000+00:00,2023-03-03T10:05:00.000+00:00,csv:CsvAccount:0:user-c,SUCCESS,test-qa-project-id,,,
+id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,is_invalid,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark
+exec-1,test-qa-project-id,tc-1,2023-03-04T10:00:00.000+00:00,2023-03-04T10:01:00.000+00:00,2023-03-04T10:06:00.000+00:00,csv:CsvAccount:0:user-a,0,FAILED,test-qa-project-id,,,
+exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,0,FAILED,test-qa-project-id,,,
+exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,,
+exec-4,test-qa-project-id,tc-3,2023-03-03T10:00:00.000+00:00,2023-03-03T10:01:00.000+00:00,2023-03-03T10:05:00.000+00:00,csv:CsvAccount:0:user-c,0,SUCCESS,test-qa-project-id,,,
diff --git a/backend/plugins/customize/service/service.go 
b/backend/plugins/customize/service/service.go
index 89e8833cf..410f35f9f 100644
--- a/backend/plugins/customize/service/service.go
+++ b/backend/plugins/customize/service/service.go
@@ -541,6 +541,10 @@ func (s *Service) qaTestCaseExecutionHandler(qaProjectId 
string) func(record map
                }
                delete(record, "creator_name")
                record["qa_project_id"] = qaProjectId
+               // Set default value for is_invalid if not present in the CSV
+               if _, exists := record["is_invalid"]; !exists {
+                       record["is_invalid"] = false
+               }
                return s.dal.CreateWithMap(&qa.QaTestCaseExecution{}, record)
        }
 }

Reply via email to