From bed7ab2558d8e33da187fdfa496335f4eb87383c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allen=20Zhang=20=28=E5=BC=A0=E6=B6=9B=29?= Date: Wed, 28 Feb 2024 19:16:27 +0800 Subject: [PATCH] feat: add config --- examples/config/coverage.json | 9 ++ packages/canyon-backend/package.json | 3 +- packages/canyon-backend/prisma/schema.prisma | 2 + packages/canyon-backend/schema.gql | 5 + .../models/update-project-response.model.ts | 0 .../src/project/project.model.ts | 6 + .../src/project/project.resolver.ts | 20 +++ .../project/services/get-projects.service.ts | 1 + .../src/project/services/project.service.ts | 56 ++++++- .../services/consumer-coverage.service.ts | 47 +++++- .../gql/mutations/UpdateProject.graphql | 5 + .../gql/queries/GetProjectByID.graphql | 2 + .../backend/gql/queries/GetProjects.graphql | 3 +- .../pages/index/projects/[id]/configure.tsx | 74 --------- .../[id]/configure/helper/BasicForms.tsx | 126 +++++++++++++++ .../helper/icons/SolarUserIdLinear.tsx | 6 + .../index/projects/[id]/configure/index.tsx | 144 ++++++++++++++++++ .../src/pages/index/projects/index.tsx | 26 +++- 18 files changed, 447 insertions(+), 88 deletions(-) create mode 100644 examples/config/coverage.json create mode 100644 packages/canyon-backend/src/project/models/update-project-response.model.ts create mode 100644 packages/canyon-platform/src/helpers/backend/gql/mutations/UpdateProject.graphql delete mode 100644 packages/canyon-platform/src/pages/index/projects/[id]/configure.tsx create mode 100644 packages/canyon-platform/src/pages/index/projects/[id]/configure/helper/BasicForms.tsx create mode 100644 packages/canyon-platform/src/pages/index/projects/[id]/configure/helper/icons/SolarUserIdLinear.tsx create mode 100644 packages/canyon-platform/src/pages/index/projects/[id]/configure/index.tsx diff --git a/examples/config/coverage.json b/examples/config/coverage.json new file mode 100644 index 00000000..2de386f4 --- /dev/null +++ b/examples/config/coverage.json @@ -0,0 +1,9 @@ +{ + "include": [ + "src/**/*.js" + ], + "exclude": [ + "**/*.spec.js" + ], + "extensions": [".js"] +} diff --git a/packages/canyon-backend/package.json b/packages/canyon-backend/package.json index faa931af..b025bf82 100755 --- a/packages/canyon-backend/package.json +++ b/packages/canyon-backend/package.json @@ -55,7 +55,8 @@ "passport-local": "^1.0.0", "prisma": "5.8.1", "reflect-metadata": "^0.1.14", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "test-exclude": "^6.0.0" }, "devDependencies": { "@nestjs/cli": "^10.3.0", diff --git a/packages/canyon-backend/prisma/schema.prisma b/packages/canyon-backend/prisma/schema.prisma index 6c8a0f8e..3c2c9101 100755 --- a/packages/canyon-backend/prisma/schema.prisma +++ b/packages/canyon-backend/prisma/schema.prisma @@ -49,6 +49,8 @@ model Project { pathWithNamespace String @map("path_with_namespace") description String bu String + tag String + coverage String createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(3) @@map("project") diff --git a/packages/canyon-backend/schema.gql b/packages/canyon-backend/schema.gql index af0231b4..28481379 100644 --- a/packages/canyon-backend/schema.gql +++ b/packages/canyon-backend/schema.gql @@ -24,6 +24,8 @@ type Project { name: String! pathWithNamespace: String! description: String! + tag: String! + coverage: String! bu: String! maxCoverage: Float! reportTimes: Float! @@ -216,4 +218,7 @@ type Mutation { """删除项目""" deleteProject(projectID: String!): Project2! + + """更新项目""" + updateProject(projectID: String!, description: String!, tag: String!, coverage: String!): Project2! } \ No newline at end of file diff --git a/packages/canyon-backend/src/project/models/update-project-response.model.ts b/packages/canyon-backend/src/project/models/update-project-response.model.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/canyon-backend/src/project/project.model.ts b/packages/canyon-backend/src/project/project.model.ts index b76df7be..e4190edb 100755 --- a/packages/canyon-backend/src/project/project.model.ts +++ b/packages/canyon-backend/src/project/project.model.ts @@ -14,6 +14,12 @@ export class Project { @Field(() => String) description: string; + @Field(() => String) + tag: string; + + @Field(() => String) + coverage: string; + @Field(() => String) bu: string; diff --git a/packages/canyon-backend/src/project/project.resolver.ts b/packages/canyon-backend/src/project/project.resolver.ts index a2b43299..d2bf3743 100755 --- a/packages/canyon-backend/src/project/project.resolver.ts +++ b/packages/canyon-backend/src/project/project.resolver.ts @@ -150,4 +150,24 @@ export class ProjectResolver { ): Promise { return this.projectService.deleteProject(user, projectID); } + + @Mutation(() => Project2, { + description: '更新项目', + }) + @UseGuards(GqlAuthGuard) + updateProject( + @GqlUser() user: AuthUser, + @Args('projectID', { type: () => String }) projectID: string, + @Args('description', { type: () => String }) description: string, + @Args('tag', { type: () => String }) tag: string, + @Args('coverage', { type: () => String }) coverage: string, + ): Promise { + return this.projectService.updateProject( + user, + projectID, + description, + tag, + coverage, + ); + } } diff --git a/packages/canyon-backend/src/project/services/get-projects.service.ts b/packages/canyon-backend/src/project/services/get-projects.service.ts index 7aac758f..7478bfdb 100644 --- a/packages/canyon-backend/src/project/services/get-projects.service.ts +++ b/packages/canyon-backend/src/project/services/get-projects.service.ts @@ -156,6 +156,7 @@ export class GetProjectsService { maxCoverage: maxCoverage, reportTimes: [...new Set(summarys.map(({ sha }) => sha))].length, pathWithNamespace: project.pathWithNamespace, + tag: project.tag, }; }), ); diff --git a/packages/canyon-backend/src/project/services/project.service.ts b/packages/canyon-backend/src/project/services/project.service.ts index b31fd5cb..ced68fe4 100755 --- a/packages/canyon-backend/src/project/services/project.service.ts +++ b/packages/canyon-backend/src/project/services/project.service.ts @@ -66,6 +66,8 @@ export class ProjectService { name: name, description: description || '', bu: bu || '默认', + coverage: '', + tag: '', }, }); } @@ -78,6 +80,31 @@ export class ProjectService { }); } + async updateProject(user, projectID, description, tag, coverage) { + function removeEmptyValues(obj) { + for (const key in obj) { + if ( + obj[key] === undefined || + obj[key] === null || + obj[key] === '__null__' + ) { + delete obj[key]; + } + } + return obj; + } + return this.prisma.project.update({ + where: { + id: projectID, + }, + data: removeEmptyValues({ + description: description, + tag: tag, + coverage: coverage, + }), + }); + } + async getProjectByID(projectID): Promise { return this.prisma.project .findFirst({ @@ -85,19 +112,32 @@ export class ProjectService { id: projectID, }, }) - .then(({ id, name, pathWithNamespace, description, bu, createdAt }) => { - return { + .then( + ({ id, name, pathWithNamespace, description, + bu, createdAt, - bu: bu, - reportTimes: 0, - lastReportTime: new Date(), - maxCoverage: 0, - }; - }); + coverage, + tag, + }) => { + return { + id, + name, + pathWithNamespace, + description, + createdAt, + bu: bu, + reportTimes: 0, + lastReportTime: new Date(), + maxCoverage: 0, + tag, + coverage, + }; + }, + ); } async getProjectsBuOptions() { diff --git a/packages/canyon-backend/src/tasks/services/consumer-coverage.service.ts b/packages/canyon-backend/src/tasks/services/consumer-coverage.service.ts index 61e07040..a4e7a9a4 100755 --- a/packages/canyon-backend/src/tasks/services/consumer-coverage.service.ts +++ b/packages/canyon-backend/src/tasks/services/consumer-coverage.service.ts @@ -18,7 +18,7 @@ import { import { PullChangeCodeAndInsertDbService } from './pull-change-code-and-insert-db.service'; import { logger } from '../../logger'; const randomInteger = Math.floor(Math.random() * 2000) + 2000; - +import * as TestExclude from 'test-exclude'; @Injectable() export class ConsumerCoverageService { constructor( @@ -101,6 +101,40 @@ export class ConsumerCoverageService { }); } + async filterCoverage(projectID, coverage) { + const project = await this.prisma.project.findFirst({ + where: { + id: projectID, + }, + }); + + let matchRule: any = {}; // Default value + + try { + // Attempt to parse project?.coverage + matchRule = JSON.parse(project?.coverage || '{}'); + } catch (error) { + // console.error('Error parsing coverage:', error); + // Log the error or handle it as needed + // You can also return an empty object or any default value + } + const exclude = new TestExclude({ + cwd: '~', + include: matchRule.include, + exclude: matchRule.exclude, + extension: matchRule.extensions, + }); + + const filterCoverage = {}; + + for (const filterCoverageKey of Object.keys(coverage)) { + if (exclude.shouldInstrument(filterCoverageKey)) { + filterCoverage[filterCoverageKey] = coverage[filterCoverageKey]; + } + } + return Object.keys(filterCoverage).length > 0 ? filterCoverage : coverage; + } + @Interval(randomInteger) //添加随机数,防止分布式服务同时执行,务必确保原子性,1-2s async lock() { const acquired = await this.acquireLock('consumer_coverage', 60000); @@ -243,10 +277,17 @@ export class ConsumerCoverageService { }, }); + const mainCovFilterCoverage = await this.filterCoverage( + normalCoverage.projectID, + mainCov, + ); + // !!!!!/ // 创建新的覆盖率数据 - const { insertedId: newKey } = await createNewCoverageData(mainCov); + const { insertedId: newKey } = await createNewCoverageData( + mainCovFilterCoverage, + ); if (newKey === null) { logger({ @@ -268,7 +309,7 @@ export class ConsumerCoverageService { // 生成覆盖率概览数据 const coverageSummaryMap = genSummaryMapByCoverageMap( - mainCov, + mainCovFilterCoverage, codechanges, ); const allSummary = getSummaryByPath('~', coverageSummaryMap); diff --git a/packages/canyon-platform/src/helpers/backend/gql/mutations/UpdateProject.graphql b/packages/canyon-platform/src/helpers/backend/gql/mutations/UpdateProject.graphql new file mode 100644 index 00000000..fb166794 --- /dev/null +++ b/packages/canyon-platform/src/helpers/backend/gql/mutations/UpdateProject.graphql @@ -0,0 +1,5 @@ +mutation UpdateProject($projectID: String!,$description: String!,$tag: String!,$coverage: String!) { + updateProject(projectID: $projectID,description: $description,tag: $tag,coverage: $coverage) { + id + } +} diff --git a/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjectByID.graphql b/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjectByID.graphql index 0cf4a8d5..73850f42 100755 --- a/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjectByID.graphql +++ b/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjectByID.graphql @@ -6,5 +6,7 @@ query GetProjectByID($projectID: ID!) { description reportTimes lastReportTime + coverage + tag } } diff --git a/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjects.graphql b/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjects.graphql index 02b9fb0f..9058d605 100755 --- a/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjects.graphql +++ b/packages/canyon-platform/src/helpers/backend/gql/queries/GetProjects.graphql @@ -8,7 +8,8 @@ query GetProjects($current: Int!, $pageSize: Int!, $keyword: String!,$bu: [Strin bu reportTimes lastReportTime - maxCoverage + maxCoverage, + tag } } } diff --git a/packages/canyon-platform/src/pages/index/projects/[id]/configure.tsx b/packages/canyon-platform/src/pages/index/projects/[id]/configure.tsx deleted file mode 100644 index bd4674b6..00000000 --- a/packages/canyon-platform/src/pages/index/projects/[id]/configure.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { - CloseCircleFilled, - CloseOutlined, - CloseSquareOutlined, - PlusOutlined, -} from '@ant-design/icons'; -import { Button, Form, Input, Popover, Tag } from 'antd'; -import { useState } from 'react'; - -const ProjectConfigure = () => { - const [value, setValue] = useState<{ text: string; color: string }[]>([ - { - color: '#f50', - text: 'rwed', - }, - ]); - - const content = ( -
-
- - - - - - - -
-
- -
-
- ); - return ( -
- {value.map((item, index) => { - return ( - - - {item.text} - - - - ); - // return {item.text}; - })} - - - New Tag - - -
- ); -}; - -export default ProjectConfigure; diff --git a/packages/canyon-platform/src/pages/index/projects/[id]/configure/helper/BasicForms.tsx b/packages/canyon-platform/src/pages/index/projects/[id]/configure/helper/BasicForms.tsx new file mode 100644 index 00000000..8485406a --- /dev/null +++ b/packages/canyon-platform/src/pages/index/projects/[id]/configure/helper/BasicForms.tsx @@ -0,0 +1,126 @@ +import { ArrowRightOutlined } from '@ant-design/icons'; +import { useMutation } from '@apollo/client'; +import { Button, Form, Input, message, Space, Tag, Typography } from 'antd'; +import { FC, useState } from 'react'; +import { useParams } from 'react-router-dom'; + +import { UpdateProjectDocument } from '../../../../../../helpers/backend/gen/graphql.ts'; + +const { TextArea } = Input; + +const { Text } = Typography; + +const { CheckableTag } = Tag; + +const tagsData = ['V2Vi', 'Q1JO', 'VHJpcC5jb20=', 'Q3RyaXA='].map(atob); + +const colors = ['#4FA15B', '#087EA4', '#287DFA', '#FFB400']; + +// value, onChange提供给antd的Form使用 +const TagComponent: FC<{ value?: string; onChange?: (value: string) => void }> = ({ + value, + onChange = () => {}, +}) => { + const [selectedTags, setSelectedTags] = useState(value ? value.split(',') : []); + const handleChange = (tag: string, checked: boolean) => { + const nextSelectedTags = checked + ? [...selectedTags, tag] + : selectedTags.filter((t) => t !== tag); + setSelectedTags(nextSelectedTags); + + onChange(nextSelectedTags.join(',')); + }; + + return ( + <> + + {tagsData.map((tag) => ( + handleChange(tag, checked)} + > + {tag} + + ))} + +
+ + {selectedTags.map((tag) => ( + -1 ? colors[tagsData.indexOf(tag)] : '#108ee9'} + > + {tag} + + ))} + {selectedTags.length === 0 && ( + + 请选择标签 + + )} +
+ + ); +}; + +const BasicForms: FC<{ data: any }> = ({ data }) => { + const [updateProject] = useMutation(UpdateProjectDocument); + const prm: any = useParams(); + const onFinish = (values: any) => { + updateProject({ + variables: { + projectID: prm.id, + coverage: '__null__', + tag: values.tag, + description: values.description, + }, + }).then(() => { + message.success('成功'); + }); + }; + if (data) { + return ( +
+
+ label='项目名称' name='pathWithNamespace' className={'flex-1 mr-10'}> + + + + className={'flex-3'} label='项目ID' name='projectID'> + + +
+ + label='描述' name='description'> +