You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by ab...@apache.org on 2023/07/31 01:25:02 UTC

[incubator-devlake] branch main updated: fix: Github Action has been silently failing for a while (#5772)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 45e7ecc22 fix: Github Action has been silently failing for a while (#5772)
45e7ecc22 is described below

commit 45e7ecc22ab26fb3de26c738404b4ecf3e7591eb
Author: Klesh Wong <zh...@merico.dev>
AuthorDate: Mon Jul 31 09:24:57 2023 +0800

    fix: Github Action has been silently failing for a while (#5772)
    
    * fix: remove deprecated test case
    
    * fix: github action always passed
    
    * fix: force tz to utc for e2e-plugins-test
    
    * fix: e2e test
    
    * fix: zentao ci failed due to tz and github actions failure
    
    * test: server startup test with all plugins loaded
    
    * fix: replace spaces with tabs for the Makefile
    
    * fix: remote test cases
    
    * fix: pg is case sensitive
    
    * fix: double quote does not work for mysql
    
    ---------
    
    Co-authored-by: Keon Amini <ke...@merico.dev>
---
 backend/Makefile                                   | 40 +++++------
 backend/plugins/jira/api/scope_config.go           | 12 ++--
 backend/plugins/jira/e2e/development_penal_test.go |  2 +-
 backend/plugins/jira/e2e/epic_test.go              |  2 +-
 backend/plugins/jira/e2e/issue_repo_commit_test.go |  4 +-
 backend/plugins/jira/e2e/issue_test.go             |  8 +--
 backend/plugins/jira/e2e/remotelink_test.go        |  4 +-
 backend/plugins/jira/tasks/task_data_test.go       | 84 ----------------------
 .../snapshot_tables/_tool_zentao_departments.csv   | 13 ----
 .../e2e/snapshot_tables/_tool_zentao_products.csv  |  2 -
 .../zentao/e2e/snapshot_tables/boards_product.csv  |  2 -
 .../e2e/snapshot_tables/issue_changelogs.csv       | 10 +--
 .../plugins/zentao/e2e/snapshot_tables/teams.csv   | 13 ----
 backend/plugins/zentao/tasks/changelog_dbget.go    |  2 +-
 backend/server/api/shared/api_output.go            | 12 ++--
 backend/test/e2e/services/server_startup_test.go   | 60 +++++++++++++++-
 backend/test/helper/api.go                         |  8 ++-
 17 files changed, 109 insertions(+), 169 deletions(-)

diff --git a/backend/Makefile b/backend/Makefile
index 85f7ae35b..a0a6780d8 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -40,7 +40,7 @@ swag:
 	elif [ $(PLUGIN) = "none" ]; then \
 		swag init --parseDependency --parseInternal -o ./server/api/docs -g ./server/api/api.go;\
 	else \
-	  	plugins="";\
+		plugins="";\
 		for p in $$(echo $(PLUGIN) | tr "," "\n"); do \
 			plugins="$$plugins -g ./plugins/$$p/api/*.go"; \
 		done;\
@@ -50,24 +50,24 @@ swag:
 
 build-plugin:
 	if [ "$(PLUGIN)" = "none" ]; then \
-  		echo "Building plugins will be skipped"; \
+		echo "Building plugins will be skipped"; \
 	elif [ "$(DEBUG)" = "true" ]; then \
-  		PLUGIN=$(PLUGIN) sh scripts/compile-plugins.sh -gcflags='all=-N -l'; \
-  	else \
+		PLUGIN=$(PLUGIN) sh scripts/compile-plugins.sh -gcflags='all=-N -l'; \
+	else \
 		PLUGIN=$(PLUGIN) sh scripts/compile-plugins.sh; \
 	fi
 
 build-worker:
 	if [ "$(DEBUG)" = "true" ]; then \
-  		go build -gcflags='all=-N -l' -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake-worker ./worker/; \
-  	else \
+		go build -gcflags='all=-N -l' -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake-worker ./worker/; \
+	else \
 		go build -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake-worker ./worker/; \
 	fi
 
 build-server: swag
 	if [ "$(DEBUG)" = "true" ]; then \
-  		go build -gcflags='all=-N -l' -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake ./server/; \
-  	else \
+		go build -gcflags='all=-N -l' -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake ./server/; \
+	else \
 		go build -ldflags "-X 'github.com/apache/incubator-devlake/core/version.Version=$(VERSION)'" -o bin/lake ./server/; \
 	fi
 
@@ -110,10 +110,7 @@ unit-test: mock unit-test-only python-unit-test
 unit-test-only:
 	set -e;\
 	for m in $$(go list ./... | egrep -v 'test|models|e2e'); do \
-  		echo $$m; \
-			if ! go test -timeout 60s -v $$m; then \
-				exit $$?; \
-			fi \
+		echo $$m; go test -timeout 60s -v $$m || exit $$?; \
 	done; \
 
 build-pydevlake:
@@ -124,13 +121,11 @@ python-unit-test: build-pydevlake
 	sh ./python/run_tests.sh
 
 e2e-plugins-test:
+	export TZ=UTC;\
 	export ENV_PATH=$(shell readlink -f .env);\
 	set -e;\
 	for m in $$(go list ./plugins/... | egrep 'e2e'); do \
-		echo $$m; \
-		if !  go test -timeout 300s -gcflags=all=-l -v $$m; then \
-		  exit $$?; \
-		fi \
+		echo $$m; go test -timeout 300s -gcflags=all=-l -v $$m || exit $$?; \
 	done; \
 
 e2e-test-init:
@@ -139,11 +134,10 @@ e2e-test-init:
 	go run ./test/init.go || exit $$?;\
 
 e2e-test-run:
+	export ENV_PATH=$(shell readlink -f .env);\
+	set -e;\
 	for m in $$(go list ./test/e2e/... | grep -v manual); do \
-		echo $$m; \
-		if ! go test -p 1 -timeout 300s -v $$m ; then \
-		  exit $$?; \
-		fi; \
+		echo $$m; go test -failfast -timeout 120s -v $$m || exit $$?; \
 	done; \
 
 e2e-test: e2e-test-init e2e-test-run
@@ -152,11 +146,9 @@ integration-test:
 	export ENV_PATH=$(shell readlink -f .env);\
 	set -e;\
 	go run ./test/init.go || exit $$?;\
-	exit_code=0;\
 	for m in $$(go list ./test/integration/...); do \
-		echo $$m; go test -p 1 -timeout 300s -v $$m || exit_code=$$?; \
-    done; \
-	exit $$exit_code
+		echo $$m; go test -timeout 300s -v $$m || exit $$?; \
+	done; \
 
 lint:
 	golangci-lint run
diff --git a/backend/plugins/jira/api/scope_config.go b/backend/plugins/jira/api/scope_config.go
index 89d725f78..015f1ea2f 100644
--- a/backend/plugins/jira/api/scope_config.go
+++ b/backend/plugins/jira/api/scope_config.go
@@ -57,8 +57,8 @@ type repo struct {
 // @Tags plugins/jira
 // @Accept application/json
 // @Param connectionId path int true "connectionId"
-// @Param scopeConfig body tasks.JiraScopeConfig true "scope config"
-// @Success 200  {object} tasks.JiraScopeConfig
+// @Param scopeConfig body models.JiraScopeConfig true "scope config"
+// @Success 200  {object} models.JiraScopeConfig
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jira/connections/{connectionId}/scope-configs [POST]
@@ -73,8 +73,8 @@ func CreateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutpu
 // @Accept application/json
 // @Param id path int true "id"
 // @Param connectionId path int true "connectionId"
-// @Param scopeConfig body tasks.JiraScopeConfig true "scope config"
-// @Success 200  {object} tasks.JiraScopeConfig
+// @Param scopeConfig body models.JiraScopeConfig true "scope config"
+// @Success 200  {object} models.JiraScopeConfig
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jira/connections/{connectionId}/scope-configs/{id} [PATCH]
@@ -88,7 +88,7 @@ func UpdateScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutpu
 // @Tags plugins/jira
 // @Param id path int true "id"
 // @Param connectionId path int true "connectionId"
-// @Success 200  {object} tasks.JiraScopeConfig
+// @Success 200  {object} models.JiraScopeConfig
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jira/connections/{connectionId}/scope-configs/{id} [GET]
@@ -103,7 +103,7 @@ func GetScopeConfig(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput,
 // @Param connectionId path int true "connectionId"
 // @Param pageSize query int false "page size, default 50"
 // @Param page query int false "page size, default 1"
-// @Success 200  {object} []tasks.JiraScopeConfig
+// @Success 200  {object} []models.JiraScopeConfig
 // @Failure 400  {object} shared.ApiBody "Bad Request"
 // @Failure 500  {object} shared.ApiBody "Internal Error"
 // @Router /plugins/jira/connections/{connectionId}/scope-configs [GET]
diff --git a/backend/plugins/jira/e2e/development_penal_test.go b/backend/plugins/jira/e2e/development_penal_test.go
index 0cb39bf25..fd779a19f 100644
--- a/backend/plugins/jira/e2e/development_penal_test.go
+++ b/backend/plugins/jira/e2e/development_penal_test.go
@@ -34,7 +34,7 @@ func TestDevelopmentPanelDataFlow(t *testing.T) {
 		Options: &tasks.JiraOptions{
 			ConnectionId: 1,
 			BoardId:      68,
-			ScopeConfig: &tasks.JiraScopeConfig{
+			ScopeConfig: &models.JiraScopeConfig{
 				ApplicationType: "GitLab",
 			},
 		},
diff --git a/backend/plugins/jira/e2e/epic_test.go b/backend/plugins/jira/e2e/epic_test.go
index f9c631ec1..b2f9714e2 100644
--- a/backend/plugins/jira/e2e/epic_test.go
+++ b/backend/plugins/jira/e2e/epic_test.go
@@ -36,7 +36,7 @@ func TestEpicDataflow(t *testing.T) {
 		Options: &tasks.JiraOptions{
 			ConnectionId: 1,
 			BoardId:      93,
-			ScopeConfig:  &tasks.JiraScopeConfig{StoryPointField: "customfield_10024"},
+			ScopeConfig:  &models.JiraScopeConfig{StoryPointField: "customfield_10024"},
 		},
 	}
 
diff --git a/backend/plugins/jira/e2e/issue_repo_commit_test.go b/backend/plugins/jira/e2e/issue_repo_commit_test.go
index c060fcf12..7b959b13e 100644
--- a/backend/plugins/jira/e2e/issue_repo_commit_test.go
+++ b/backend/plugins/jira/e2e/issue_repo_commit_test.go
@@ -35,9 +35,9 @@ func TestConvertIssueRepoCommitsDataFlow(t *testing.T) {
 		Options: &tasks.JiraOptions{
 			ConnectionId: 2,
 			BoardId:      8,
-			ScopeConfig: &tasks.JiraScopeConfig{
+			ScopeConfig: &models.JiraScopeConfig{
 				RemotelinkCommitShaPattern: `.*/commit/(.*)`,
-				RemotelinkRepoPattern: []tasks.CommitUrlPattern{
+				RemotelinkRepoPattern: []models.CommitUrlPattern{
 					{"", `https://bitbucket.org/(?P<namespace>[^/]+)/(?P<repo_name>[^/]+)/commits/(?P<commit_sha>\w{40})`},
 					{"", `https://gitlab.com/(?P<namespace>\S+)/(?P<repo_name>\S+)/-/commit/(?P<commit_sha>\w{40})`},
 					{"", `https://github.com/(?P<namespace>[^/]+)/(?P<repo_name>[^/]+)/commit/(?P<commit_sha>\w{40})`},
diff --git a/backend/plugins/jira/e2e/issue_test.go b/backend/plugins/jira/e2e/issue_test.go
index 6dfd8546e..324361d49 100644
--- a/backend/plugins/jira/e2e/issue_test.go
+++ b/backend/plugins/jira/e2e/issue_test.go
@@ -36,19 +36,19 @@ func TestIssueDataFlow(t *testing.T) {
 		Options: &tasks.JiraOptions{
 			ConnectionId: 2,
 			BoardId:      8,
-			ScopeConfig: &tasks.JiraScopeConfig{
+			ScopeConfig: &models.JiraScopeConfig{
 				StoryPointField: "customfield_10024",
-				TypeMappings: map[string]tasks.TypeMapping{
+				TypeMappings: map[string]models.TypeMapping{
 					"子任务": {
 						StandardType: "Sub-task",
-						StatusMappings: map[string]tasks.StatusMapping{
+						StatusMappings: map[string]models.StatusMapping{
 							"done": {StandardStatus: "你好世界"},
 							"new":  {StandardStatus: "\u6069\u5E95\u6EF4\u68AF\u6B38\u592B\u5178\u4EA2\u59C6"},
 						},
 					},
 					"任务": {
 						StandardType: "Task",
-						StatusMappings: map[string]tasks.StatusMapping{
+						StatusMappings: map[string]models.StatusMapping{
 							"done": {StandardStatus: "hello world"},
 							"new":  {StandardStatus: "110 100 100 116 102 46 99 111 109"},
 						},
diff --git a/backend/plugins/jira/e2e/remotelink_test.go b/backend/plugins/jira/e2e/remotelink_test.go
index ee773f74f..49df1b421 100644
--- a/backend/plugins/jira/e2e/remotelink_test.go
+++ b/backend/plugins/jira/e2e/remotelink_test.go
@@ -34,9 +34,9 @@ func TestRemotelinkDataFlow(t *testing.T) {
 		Options: &tasks.JiraOptions{
 			ConnectionId: 2,
 			BoardId:      8,
-			ScopeConfig: &tasks.JiraScopeConfig{
+			ScopeConfig: &models.JiraScopeConfig{
 				RemotelinkCommitShaPattern: ".*/commit/(.*)",
-				RemotelinkRepoPattern: []tasks.CommitUrlPattern{
+				RemotelinkRepoPattern: []models.CommitUrlPattern{
 					{
 						Pattern: "",
 						Regex:   `https://example.com/(?P<namespace>\S+)/(?P<repo_name>\S+)/-/commits/(?P<commit_sha>\w{40})`,
diff --git a/backend/plugins/jira/tasks/task_data_test.go b/backend/plugins/jira/tasks/task_data_test.go
deleted file mode 100644
index 3e546f566..000000000
--- a/backend/plugins/jira/tasks/task_data_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-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 tasks
-
-import (
-	"reflect"
-	"testing"
-
-	"github.com/apache/incubator-devlake/core/errors"
-	"github.com/apache/incubator-devlake/plugins/jira/models"
-)
-
-func TestMakeScopeConfigs(t *testing.T) {
-	type args struct {
-		rule models.JiraScopeConfig
-	}
-	tests := []struct {
-		name  string
-		args  args
-		want  *JiraScopeConfig
-		want1 errors.Error
-	}{
-		{"non-null RemotelinkRepoPattern",
-			args{rule: models.JiraScopeConfig{
-				Name:                       "name",
-				EpicKeyField:               "epic",
-				StoryPointField:            "story",
-				RemotelinkCommitShaPattern: "commit sha pattern",
-				RemotelinkRepoPattern:      []byte(`[{"pattern":"","regex":"abc"},{"pattern":"","regex":"efg"}]`),
-				TypeMappings:               []byte(`{"10040":{"standardType":"Incident","statusMappings":null}}`),
-			}},
-			&JiraScopeConfig{
-				Name:                       "name",
-				EpicKeyField:               "epic",
-				StoryPointField:            "story",
-				RemotelinkCommitShaPattern: "commit sha pattern",
-				RemotelinkRepoPattern:      []CommitUrlPattern{{"", "abc"}, {"", "efg"}},
-				TypeMappings: map[string]TypeMapping{"10040": {
-					StandardType:   "Incident",
-					StatusMappings: nil,
-				}},
-			},
-			nil,
-		},
-
-		{"null RemotelinkRepoPattern",
-			args{rule: models.JiraScopeConfig{
-				RemotelinkRepoPattern: nil,
-				TypeMappings:          nil,
-			}},
-			&JiraScopeConfig{
-				RemotelinkRepoPattern: nil,
-				TypeMappings:          nil,
-			},
-			nil,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got, got1 := MakeScopeConfig(tt.args.rule)
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("MakeScopeConfig() got = %v, want %v", got, tt.want)
-			}
-			if !reflect.DeepEqual(got1, tt.want1) {
-				t.Errorf("MakeScopeConfig() got1 = %v, want %v", got1, tt.want1)
-			}
-		})
-	}
-}
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_departments.csv b/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_departments.csv
deleted file mode 100644
index fcb121d37..000000000
--- a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_departments.csv
+++ /dev/null
@@ -1,13 +0,0 @@
-connection_id,id,name,parent,path,grade,order_in,position,dept_function,manager,manager_name
-1,1,,0,,0,0,,,,
-1,2,,0,,0,0,,,,
-1,3,,0,,0,0,,,,
-1,4,,0,,0,0,,,,
-1,5,,0,,0,0,,,,
-1,6,,0,,0,0,,,,
-1,7,,0,,0,0,,,,
-1,8,,0,,0,0,,,,
-1,9,,0,,0,0,,,,
-1,10,,0,,0,0,,,,
-1,11,,0,,0,0,,,,
-1,12,,0,,0,0,,,,
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv b/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv
deleted file mode 100644
index da1c79109..000000000
--- a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-connection_id,id,program,name,code,bind,line,type,product_type,status,sub_status,description,po_id,qd_id,rd_id,acl,reviewer,created_by_id,created_date,created_version,order_in,deleted,plans,releases,builds,cases,projects,executions,bugs,docs,progress,case_review
-1,3,10,产品名称1,产品代号2,0,31,product,normal,normal,,"<span style=""background-color:#FFFFFF;"">产品描述1</span>",1,1,1,private,"devlake,dev1",1,2022-11-17T06:42:25.000+00:00,17.6,15,0,1,0,0,0,0,0,0,0,12.121,0
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv b/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv
deleted file mode 100644
index 0c3d53b5d..000000000
--- a/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-id,name,description,url,created_date,type
-zentao:ZentaoProduct:1:3,产品名称1,"<span style=""background-color:#FFFFFF;"">产品描述1</span>",/product-index-3.html,2022-11-17T06:42:25.000+00:00,product/normal
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/issue_changelogs.csv b/backend/plugins/zentao/e2e/snapshot_tables/issue_changelogs.csv
index 4604b1eff..808a46b9d 100644
--- a/backend/plugins/zentao/e2e/snapshot_tables/issue_changelogs.csv
+++ b/backend/plugins/zentao/e2e/snapshot_tables/issue_changelogs.csv
@@ -1,6 +1,6 @@
 id,issue_id,author_id,author_name,field_id,field_name,original_from_value,original_to_value,from_value,to_value,created_date
-zentao:ZentaoChangelogDetail:1:114:75,zentao:ZentaoBug:1:1,"",admin,type,type,interface,codeerror,interface,codeerror,2021-04-28T03:09:08.000+00:00
-zentao:ZentaoChangelogDetail:1:114:76,zentao:ZentaoBug:1:1,"",admin,pri,pri,0,1,0,1,2021-04-28T03:09:08.000+00:00
-zentao:ZentaoChangelogDetail:1:115:77,zentao:ZentaoBug:1:2,"",admin,pri,pri,0,2,0,2,2021-04-28T03:09:08.000+00:00
-zentao:ZentaoChangelogDetail:1:116:78,zentao:ZentaoBug:1:3,"",admin,pri,pri,0,1,0,1,2021-04-28T03:09:08.000+00:00
-zentao:ZentaoChangelogDetail:1:117:79,zentao:ZentaoBug:1:4,"",admin,pri,pri,0,1,0,1,2021-04-28T03:09:08.000+00:00
+zentao:ZentaoChangelogDetail:1:114:75,zentao:ZentaoBug:1:1,,admin,type,type,interface,codeerror,interface,codeerror,2021-04-28T11:09:08.000+00:00
+zentao:ZentaoChangelogDetail:1:114:76,zentao:ZentaoBug:1:1,,admin,pri,pri,0,1,0,1,2021-04-28T11:09:08.000+00:00
+zentao:ZentaoChangelogDetail:1:115:77,zentao:ZentaoBug:1:2,,admin,pri,pri,0,2,0,2,2021-04-28T11:09:08.000+00:00
+zentao:ZentaoChangelogDetail:1:116:78,zentao:ZentaoBug:1:3,,admin,pri,pri,0,1,0,1,2021-04-28T11:09:08.000+00:00
+zentao:ZentaoChangelogDetail:1:117:79,zentao:ZentaoBug:1:4,,admin,pri,pri,0,1,0,1,2021-04-28T11:09:08.000+00:00
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/teams.csv b/backend/plugins/zentao/e2e/snapshot_tables/teams.csv
deleted file mode 100644
index c83d48031..000000000
--- a/backend/plugins/zentao/e2e/snapshot_tables/teams.csv
+++ /dev/null
@@ -1,13 +0,0 @@
-id,name,alias,parent_id,sorting_index
-zentao:ZentaoDepartment:1:1,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:10,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:11,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:12,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:2,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:3,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:4,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:5,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:6,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:7,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:8,,,zentao:ZentaoDepartment:1:0,0
-zentao:ZentaoDepartment:1:9,,,zentao:ZentaoDepartment:1:0,0
diff --git a/backend/plugins/zentao/tasks/changelog_dbget.go b/backend/plugins/zentao/tasks/changelog_dbget.go
index ed12eb9bb..aa181ef18 100644
--- a/backend/plugins/zentao/tasks/changelog_dbget.go
+++ b/backend/plugins/zentao/tasks/changelog_dbget.go
@@ -75,7 +75,7 @@ func (h actionHistoryHandler) collectActionHistory(rdb dal.Dal, connectionId uin
 		dal.Select("*,zt_action.id aid,zt_history.id hid "),
 		dal.From("zt_action"),
 		dal.Join("LEFT JOIN zt_history on zt_history.action = zt_action.id"),
-		dal.Where("zt_action.objectType IN ?", []string{"story", "task", "bug"}),
+		dal.Where("? IN ?", dal.ClauseColumn{Table: "zt_action", Name: "objectType"}, []string{"story", "task", "bug"}),
 	}
 	cursor, err := rdb.Cursor(clause...)
 	if err != nil {
diff --git a/backend/server/api/shared/api_output.go b/backend/server/api/shared/api_output.go
index 086aaab9a..fb8cace6f 100644
--- a/backend/server/api/shared/api_output.go
+++ b/backend/server/api/shared/api_output.go
@@ -30,13 +30,15 @@ import (
 
 const BadRequestBody = "bad request body format"
 
-type ApiBody struct {
-	Success bool        `json:"success"`
-	Message string      `json:"message"`
-	Causes  []string    `json:"causes"`
-	Data    interface{} `json:"data"`
+type TypedApiBody[T any] struct {
+	Success bool     `json:"success"`
+	Message string   `json:"message"`
+	Causes  []string `json:"causes"`
+	Data    T        `json:"data"`
 }
 
+type ApiBody TypedApiBody[interface{}]
+
 type ResponsePipelines struct {
 	Count     int64              `json:"count"`
 	Pipelines []*models.Pipeline `json:"pipelines"`
diff --git a/backend/test/e2e/services/server_startup_test.go b/backend/test/e2e/services/server_startup_test.go
index 524b21edb..1ca0ab215 100644
--- a/backend/test/e2e/services/server_startup_test.go
+++ b/backend/test/e2e/services/server_startup_test.go
@@ -18,13 +18,71 @@ limitations under the License.
 package services
 
 import (
+	"github.com/apache/incubator-devlake/core/plugin"
+	ae "github.com/apache/incubator-devlake/plugins/ae/impl"
+	bamboo "github.com/apache/incubator-devlake/plugins/bamboo/impl"
+	bitbucket "github.com/apache/incubator-devlake/plugins/bitbucket/impl"
+	customize "github.com/apache/incubator-devlake/plugins/customize/impl"
+	dbt "github.com/apache/incubator-devlake/plugins/dbt/impl"
+	dora "github.com/apache/incubator-devlake/plugins/dora/impl"
+	feishu "github.com/apache/incubator-devlake/plugins/feishu/impl"
+	gitee "github.com/apache/incubator-devlake/plugins/gitee/impl"
+	gitextractor "github.com/apache/incubator-devlake/plugins/gitextractor/impl"
+	github "github.com/apache/incubator-devlake/plugins/github/impl"
+	githubGraphql "github.com/apache/incubator-devlake/plugins/github_graphql/impl"
+	gitlab "github.com/apache/incubator-devlake/plugins/gitlab/impl"
+	icla "github.com/apache/incubator-devlake/plugins/icla/impl"
+	jenkins "github.com/apache/incubator-devlake/plugins/jenkins/impl"
+	jira "github.com/apache/incubator-devlake/plugins/jira/impl"
+	org "github.com/apache/incubator-devlake/plugins/org/impl"
+	pagerduty "github.com/apache/incubator-devlake/plugins/pagerduty/impl"
+	refdiff "github.com/apache/incubator-devlake/plugins/refdiff/impl"
+	slack "github.com/apache/incubator-devlake/plugins/slack/impl"
+	sonarqube "github.com/apache/incubator-devlake/plugins/sonarqube/impl"
+	starrocks "github.com/apache/incubator-devlake/plugins/starrocks/impl"
+	tapd "github.com/apache/incubator-devlake/plugins/tapd/impl"
+	teambition "github.com/apache/incubator-devlake/plugins/teambition/impl"
+	trello "github.com/apache/incubator-devlake/plugins/trello/impl"
+	webhook "github.com/apache/incubator-devlake/plugins/webhook/impl"
+	zentao "github.com/apache/incubator-devlake/plugins/zentao/impl"
 	"github.com/apache/incubator-devlake/test/helper"
 	"github.com/stretchr/testify/require"
 	"testing"
 )
 
 func TestStartup(t *testing.T) {
-	client := helper.StartDevLakeServer(t, nil)
+	client := helper.StartDevLakeServer(t, loadGoPlugins())
 	projects := client.ListProjects()
 	require.Equal(t, 0, int(projects.Count))
 }
+
+func loadGoPlugins() []plugin.PluginMeta {
+	return []plugin.PluginMeta{
+		ae.AE{},
+		bamboo.Bamboo{},
+		bitbucket.Bitbucket(""),
+		customize.Customize{},
+		dbt.Dbt{},
+		dora.Dora{},
+		feishu.Feishu{},
+		gitee.Gitee(""),
+		gitextractor.GitExtractor{},
+		github.Github{},
+		githubGraphql.GithubGraphql{},
+		gitlab.Gitlab(""),
+		icla.Icla{},
+		jenkins.Jenkins{},
+		jira.Jira{},
+		org.Org{},
+		pagerduty.PagerDuty{},
+		refdiff.RefDiff{},
+		slack.Slack{},
+		sonarqube.Sonarqube{},
+		starrocks.StarRocks(""),
+		tapd.Tapd{},
+		teambition.Teambition{},
+		trello.Trello{},
+		webhook.Webhook{},
+		zentao.Zentao{},
+	}
+}
diff --git a/backend/test/helper/api.go b/backend/test/helper/api.go
index e6bca602d..23423e074 100644
--- a/backend/test/helper/api.go
+++ b/backend/test/helper/api.go
@@ -19,16 +19,18 @@ package helper
 
 import (
 	"fmt"
-	"github.com/apache/incubator-devlake/helpers/pluginhelper/services"
 	"net/http"
 	"reflect"
 	"strings"
 
+	"github.com/apache/incubator-devlake/helpers/pluginhelper/services"
+
 	"github.com/apache/incubator-devlake/core/errors"
 	"github.com/apache/incubator-devlake/core/models"
 	"github.com/apache/incubator-devlake/core/plugin"
 	"github.com/apache/incubator-devlake/server/api/blueprints"
 	apiProject "github.com/apache/incubator-devlake/server/api/project"
+	"github.com/apache/incubator-devlake/server/api/shared"
 	"github.com/stretchr/testify/require"
 )
 
@@ -67,12 +69,12 @@ func (d *DevlakeClient) ListConnections(pluginName string) []*Connection {
 // DeleteConnection FIXME
 func (d *DevlakeClient) DeleteConnection(pluginName string, connectionId uint64) services.BlueprintProjectPairs {
 	d.testCtx.Helper()
-	refs := sendHttpRequest[services.BlueprintProjectPairs](d.testCtx, d.timeout, &testContext{
+	refs := sendHttpRequest[shared.TypedApiBody[services.BlueprintProjectPairs]](d.testCtx, d.timeout, &testContext{
 		client:       d,
 		printPayload: true,
 		inlineJson:   false,
 	}, http.MethodDelete, fmt.Sprintf("%s/plugins/%s/connections/%d", d.Endpoint, pluginName, connectionId), nil, nil)
-	return refs
+	return refs.Data
 }
 
 // CreateBasicBlueprintV2 FIXME