From 9c1152aad86b7e53fc4db4ae74726d0c7e9a901e Mon Sep 17 00:00:00 2001 From: abeizn Date: Thu, 19 Sep 2024 10:35:17 +0800 Subject: [PATCH 01/32] fix: increase cq_issuescomponent length to text (#8068) --- .../domainlayer/codequality/cq_issues.go | 2 +- ...0919_increase_cq_issue_component_length.go | 40 +++++++++++++++++++ .../core/models/migrationscripts/register.go | 1 + 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 backend/core/models/migrationscripts/20240919_increase_cq_issue_component_length.go diff --git a/backend/core/models/domainlayer/codequality/cq_issues.go b/backend/core/models/domainlayer/codequality/cq_issues.go index 6f5d2a465e8..6856b8f7cbb 100644 --- a/backend/core/models/domainlayer/codequality/cq_issues.go +++ b/backend/core/models/domainlayer/codequality/cq_issues.go @@ -26,7 +26,7 @@ type CqIssue struct { domainlayer.DomainEntity Rule string `gorm:"type:varchar(255)"` Severity string `gorm:"type:varchar(100)"` - Component string `gorm:"type:varchar(255)"` + Component string ProjectKey string `gorm:"index;type:varchar(100)"` //domain project key Line int Status string `gorm:"type:varchar(20)"` diff --git a/backend/core/models/migrationscripts/20240919_increase_cq_issue_component_length.go b/backend/core/models/migrationscripts/20240919_increase_cq_issue_component_length.go new file mode 100644 index 00000000000..aa1483e0686 --- /dev/null +++ b/backend/core/models/migrationscripts/20240919_increase_cq_issue_component_length.go @@ -0,0 +1,40 @@ +/* +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 = (*increaseCqIssueComponentLength)(nil) + +type increaseCqIssueComponentLength struct{} + +func (script *increaseCqIssueComponentLength) Up(basicRes context.BasicRes) errors.Error { + return basicRes.GetDal().ModifyColumnType("cq_issues", "component", "text") +} + +func (*increaseCqIssueComponentLength) Version() uint64 { + return 20240919160242 +} + +func (*increaseCqIssueComponentLength) Name() string { + return "increase cq_issues.component length to text" +} diff --git a/backend/core/models/migrationscripts/register.go b/backend/core/models/migrationscripts/register.go index fa349d6b3b4..709099d59b7 100644 --- a/backend/core/models/migrationscripts/register.go +++ b/backend/core/models/migrationscripts/register.go @@ -133,5 +133,6 @@ func All() []plugin.MigrationScript { new(addAssigneeToIncident), new(addIsSubtaskToIssue), new(addIsChildToCicdPipeline), + new(increaseCqIssueComponentLength), } } From aa011880625edfcc3af9f5c3943391fd5b33dadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Toublanc?= Date: Thu, 19 Sep 2024 05:16:26 +0200 Subject: [PATCH 02/32] feat: add deployment URL mapping to webhook plugin (#8000) --- backend/plugins/webhook/api/deployments.go | 2 ++ config-ui/src/plugins/register/webhook/components/utils.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/backend/plugins/webhook/api/deployments.go b/backend/plugins/webhook/api/deployments.go index 366cf11b71c..cc5b9782732 100644 --- a/backend/plugins/webhook/api/deployments.go +++ b/backend/plugins/webhook/api/deployments.go @@ -43,6 +43,7 @@ type WebhookDeploymentReq struct { Result string `mapstructure:"result"` Environment string `validate:"omitempty,oneof=PRODUCTION STAGING TESTING DEVELOPMENT"` Name string `mapstructure:"name"` + Url string `mapstructure:"url"` // DeploymentCommits is used for multiple commits in one deployment DeploymentCommits []WebhookDeploymentCommitReq `mapstructure:"deploymentCommits" validate:"omitempty,dive"` CreatedDate *time.Time `mapstructure:"createdDate"` @@ -209,6 +210,7 @@ func CreateDeploymentAndDeploymentCommits(connection *models.WebhookConnection, deployment.StartedDate = request.StartedDate deployment.FinishedDate = request.FinishedDate deployment.Result = request.Result + deployment.Url = request.Url if err := tx.CreateOrUpdate(deployment); err != nil { logger.Error(err, "failed to save deployment") return err diff --git a/config-ui/src/plugins/register/webhook/components/utils.ts b/config-ui/src/plugins/register/webhook/components/utils.ts index 73824d14883..e41721614b5 100644 --- a/config-ui/src/plugins/register/webhook/components/utils.ts +++ b/config-ui/src/plugins/register/webhook/components/utils.ts @@ -41,6 +41,7 @@ export const transformURI = (prefix: string, webhook: IWebhook, apiKey: string) "startedDate": "2023-01-01T12:00:00+00:00", "finishedDate": "2023-01-01T12:00:00+00:00", "result": "SUCCESS", + "url": "Optional. The URL of the deployment", "deploymentCommits":[ { "repoUrl": "your-git-url", From b5bdc25fbf1b200a9381e493ede1ac247aaa7f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Thu, 19 Sep 2024 20:52:33 +1200 Subject: [PATCH 03/32] fix: error encode operate when updating project name (#8073) --- config-ui/src/api/project/index.ts | 5 +---- config-ui/src/routes/project/additional-settings/index.tsx | 2 +- config-ui/src/routes/project/layout/index.tsx | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/config-ui/src/api/project/index.ts b/config-ui/src/api/project/index.ts index ca008480a56..8e79ee5fa2f 100644 --- a/config-ui/src/api/project/index.ts +++ b/config-ui/src/api/project/index.ts @@ -40,8 +40,5 @@ export const remove = (name: string) => export const update = (name: string, data: Pick) => request(`/projects/${encodeURIComponent(name)}`, { method: 'patch', - data: { - ...data, - name: encodeURIComponent(data.name), - }, + data, }); diff --git a/config-ui/src/routes/project/additional-settings/index.tsx b/config-ui/src/routes/project/additional-settings/index.tsx index 50cde0b74b1..f8ebce37755 100644 --- a/config-ui/src/routes/project/additional-settings/index.tsx +++ b/config-ui/src/routes/project/additional-settings/index.tsx @@ -108,7 +108,7 @@ export const ProjectAdditionalSettings = () => { if (success) { setVersion((v) => v + 1); - navigate(`/projects/${encodeURIComponent(pname)}`, { + navigate(`/projects/${encodeURIComponent(name)}`, { state: { tabId: 'settings', }, diff --git a/config-ui/src/routes/project/layout/index.tsx b/config-ui/src/routes/project/layout/index.tsx index ae0647c2253..d96747a297c 100644 --- a/config-ui/src/routes/project/layout/index.tsx +++ b/config-ui/src/routes/project/layout/index.tsx @@ -124,7 +124,7 @@ export const ProjectLayout = () => {

{breadcrumbs(paths).map((b, i) => ( - {i !== paths.length - 2 ? {b.name} : {b.name}} + {i !== paths.length - 2 ? {b.name} : {decodeURIComponent(b.name)}} / ))} From ee21e3e3e5f18de18341ad1d7b37cb02faf1f84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Thu, 19 Sep 2024 20:52:55 +1200 Subject: [PATCH 04/32] fix: incomplete historical pipelines (#8072) --- config-ui/src/api/blueprint/index.ts | 2 +- .../routes/blueprint/detail/status-panel.tsx | 42 ++++++++----------- .../src/routes/pipeline/components/table.tsx | 2 +- config-ui/src/routes/pipeline/pipelines.tsx | 4 +- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/config-ui/src/api/blueprint/index.ts b/config-ui/src/api/blueprint/index.ts index 727c026de68..3876d3e20da 100644 --- a/config-ui/src/api/blueprint/index.ts +++ b/config-ui/src/api/blueprint/index.ts @@ -34,7 +34,7 @@ export const remove = (id: ID) => request(`/blueprints/${id}`, { method: 'delete export const update = (id: ID, data: Partial) => request(`/blueprints/${id}`, { method: 'patch', data }); -export const pipelines = (id: ID) => request(`/blueprints/${id}/pipelines`); +export const pipelines = (id: ID, data?: Pagination) => request(`/blueprints/${id}/pipelines`, { data }); type TriggerQuery = { skipCollectors?: boolean; diff --git a/config-ui/src/routes/blueprint/detail/status-panel.tsx b/config-ui/src/routes/blueprint/detail/status-panel.tsx index bbc04ee6aed..09d2fdf2529 100644 --- a/config-ui/src/routes/blueprint/detail/status-panel.tsx +++ b/config-ui/src/routes/blueprint/detail/status-panel.tsx @@ -24,9 +24,9 @@ import { Card, Modal, Switch, Button, Tooltip, Dropdown, Flex, Space } from 'ant import API from '@/api'; import { Message } from '@/components'; import { getCron } from '@/config'; -import { useAutoRefresh } from '@/hooks'; +import { useRefreshData } from '@/hooks'; import { PipelineInfo, PipelineTasks, PipelineTable } from '@/routes/pipeline'; -import { IBlueprint, IPipeline, IPipelineStatus } from '@/types'; +import { IBlueprint } from '@/types'; import { formatTime, operator } from '@/utils'; import { FromEnum } from '../types'; @@ -40,32 +40,17 @@ interface Props { export const StatusPanel = ({ from, blueprint, pipelineId, onRefresh }: Props) => { const [type, setType] = useState<'delete' | 'fullSync'>(); + const [page, setPage] = useState(1); + const [pageSize] = useState(10); const [operating, setOperating] = useState(false); const navigate = useNavigate(); const cron = useMemo(() => getCron(blueprint.isManual, blueprint.cronConfig), [blueprint]); - const { loading, data } = useAutoRefresh( - async () => { - const res = await API.blueprint.pipelines(blueprint.id); - return res.pipelines; - }, - [], - { - cancel: (data) => - !!( - data && - data.every((it) => - [ - IPipelineStatus.COMPLETED, - IPipelineStatus.PARTIAL, - IPipelineStatus.CANCELLED, - IPipelineStatus.FAILED, - ].includes(it.status), - ) - ), - }, + const { ready, data } = useRefreshData( + () => API.blueprint.pipelines(blueprint.id, { page, pageSize }), + [blueprint.id, page, pageSize], ); const handleResetType = () => { @@ -209,10 +194,19 @@ export const StatusPanel = ({ from, blueprint, pipelineId, onRefresh }: Props) =

Historical Pipelines

- {!data?.length ? ( + {!data?.count ? ( There are no historical runs associated with this blueprint. ) : ( - + )} diff --git a/config-ui/src/routes/pipeline/components/table.tsx b/config-ui/src/routes/pipeline/components/table.tsx index d63ddd6cedc..ca16ed890bf 100644 --- a/config-ui/src/routes/pipeline/components/table.tsx +++ b/config-ui/src/routes/pipeline/components/table.tsx @@ -37,7 +37,7 @@ interface Props { dataSource: IPipeline[]; pagination?: { total: number; - page: number; + current: number; pageSize: number; onChange: (page: number) => void; }; diff --git a/config-ui/src/routes/pipeline/pipelines.tsx b/config-ui/src/routes/pipeline/pipelines.tsx index 778d200d980..3411ec810ea 100644 --- a/config-ui/src/routes/pipeline/pipelines.tsx +++ b/config-ui/src/routes/pipeline/pipelines.tsx @@ -42,9 +42,9 @@ export const Pipelines = () => { loading={!ready} dataSource={dataSource} pagination={{ - total, - page, + current: page, pageSize, + total, onChange: setPage, }} /> From 3ad9839fae4ffdc06d154b327807b8905db5b3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Thu, 19 Sep 2024 20:53:29 +1200 Subject: [PATCH 05/32] feat: improve the pipeline duration display (#8071) --- .../routes/pipeline/components/duration.tsx | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/config-ui/src/routes/pipeline/components/duration.tsx b/config-ui/src/routes/pipeline/components/duration.tsx index 7558f9fb313..67ea9e290f4 100644 --- a/config-ui/src/routes/pipeline/components/duration.tsx +++ b/config-ui/src/routes/pipeline/components/duration.tsx @@ -20,6 +20,28 @@ import dayjs from 'dayjs'; import { IPipelineStatus } from '@/types'; +const duration = (minute: number) => { + if (minute < 1) { + return '1m'; + } + + if (minute < 60) { + return `${Math.ceil(minute / 60)}m`; + } + + if (minute < 60 * 24) { + const hours = Math.floor(minute / 60); + const minutes = minute - hours * 60; + return `${hours}h${minutes}m`; + } + + const days = Math.floor(minute / (60 * 24)); + const hours = Math.floor((minute - days * 60 * 24) / 60); + const minutes = minute - days * 60 * 24 - hours * 60; + + return `${days}d${hours}h${minutes}m`; +}; + interface Props { status: IPipelineStatus; beganAt: string | null; @@ -36,12 +58,12 @@ export const PipelineDuration = ({ status, beganAt, finishedAt }: Props) => { status, ) ) { - return {dayjs(beganAt).toNow(true)}; + return {duration(dayjs(beganAt).diff(dayjs(), 'm'))}; } if (!finishedAt) { return -; } - return {dayjs(beganAt).from(finishedAt, true)}; + return {duration(dayjs(beganAt).diff(dayjs(finishedAt), 'm'))}; }; From b3633555db2f1ebb42712403e4a4603709012f22 Mon Sep 17 00:00:00 2001 From: abeizn Date: Thu, 19 Sep 2024 17:39:10 +0800 Subject: [PATCH 06/32] fix: graphql collector fails on transferred issues (#8075) --- backend/helpers/pluginhelper/api/graphql_collector.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/helpers/pluginhelper/api/graphql_collector.go b/backend/helpers/pluginhelper/api/graphql_collector.go index e83435e9bbf..47368d0077a 100644 --- a/backend/helpers/pluginhelper/api/graphql_collector.go +++ b/backend/helpers/pluginhelper/api/graphql_collector.go @@ -22,6 +22,7 @@ import ( "encoding/json" "net/http" "reflect" + "strings" "time" "github.com/apache/incubator-devlake/core/dal" @@ -276,7 +277,11 @@ func (collector *GraphqlCollector) fetchAsync(reqData *GraphqlRequestData, handl if len(dataErrors) > 0 { if !collector.args.IgnoreQueryErrors { for _, dataError := range dataErrors { - collector.checkError(errors.Default.Wrap(dataError, `graphql query got error`)) + if strings.Contains(dataError.Error(), "Could not resolve to an Issue") { + collector.args.Ctx.GetLogger().Warn(nil, "Issue may have been transferred.") + } else { + collector.checkError(errors.Default.Wrap(dataError, `graphql query got error`)) + } } return } From 6f0e0dbb48e6abb585bbd4e693e20db7fd595576 Mon Sep 17 00:00:00 2001 From: Lynwee <1507509064@qq.com> Date: Fri, 20 Sep 2024 09:58:43 +0800 Subject: [PATCH 07/32] fix(migration): panic when `ExecuteMigration` fails (#8070) --- backend/server/api/api.go | 7 +------ backend/server/services/init.go | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/backend/server/api/api.go b/backend/server/api/api.go index 69ca8a37477..a2b590be494 100644 --- a/backend/server/api/api.go +++ b/backend/server/api/api.go @@ -122,12 +122,7 @@ func SetupApiServer(router *gin.Engine) { // Endpoint to proceed database migration router.GET("/proceed-db-migration", func(ctx *gin.Context) { // Execute database migration - err := services.ExecuteMigration() - if err != nil { - // Return error response - shared.ApiOutputError(ctx, errors.Default.Wrap(err, "error executing migration")) - return - } + errors.Must(services.ExecuteMigration()) // Return success response shared.ApiOutputSuccess(ctx, nil, http.StatusOK) }) diff --git a/backend/server/services/init.go b/backend/server/services/init.go index 7e794e68a68..a4eb334c241 100644 --- a/backend/server/services/init.go +++ b/backend/server/services/init.go @@ -96,7 +96,7 @@ func registerPluginsMigrationScripts() { func InitExecuteMigration() { // check if there are pending migration - logger.Info("has pending scripts? %v, FORCE_MIGRATION: %s", migrator.HasPendingScripts(), cfg.GetBool("FORCE_MIGRATION")) + logger.Info("has pending scripts? %v, FORCE_MIGRATION: %v", migrator.HasPendingScripts(), cfg.GetBool("FORCE_MIGRATION")) if migrator.HasPendingScripts() { if cfg.GetBool("FORCE_MIGRATION") { errors.Must(ExecuteMigration()) From f8c3a46885f0b3613ee8b85045f94801a1cb7840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Fri, 20 Sep 2024 14:37:37 +1200 Subject: [PATCH 08/32] fix: typo (#8074) --- config-ui/src/routes/project/additional-settings/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-ui/src/routes/project/additional-settings/index.tsx b/config-ui/src/routes/project/additional-settings/index.tsx index f8ebce37755..5d670bb772b 100644 --- a/config-ui/src/routes/project/additional-settings/index.tsx +++ b/config-ui/src/routes/project/additional-settings/index.tsx @@ -149,7 +149,7 @@ export const ProjectAdditionalSettings = () => { setDora({ enable: e.target.checked })}> - Enable DORA Metrics + Enable DORA metrics } description="DORA metrics are four widely-adopted metrics for measuring software delivery performance." From d69f95c4db989d558a6ee224d58a8d1c4aee33c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Fri, 20 Sep 2024 14:37:51 +1200 Subject: [PATCH 09/32] fix: data scope doesn't display name when selecting in project (#8077) --- .../components/data-scope-select/index.tsx | 50 +++++++++++-------- .../blueprint/connection-detail/index.tsx | 18 ++++--- .../blueprint/connection-detail/table.tsx | 16 +++--- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/config-ui/src/plugins/components/data-scope-select/index.tsx b/config-ui/src/plugins/components/data-scope-select/index.tsx index 79899f7e5b2..9ac0bfe18f4 100644 --- a/config-ui/src/plugins/components/data-scope-select/index.tsx +++ b/config-ui/src/plugins/components/data-scope-select/index.tsx @@ -44,14 +44,25 @@ export const DataScopeSelect = ({ onCancel, }: Props) => { const [selectedIds, setSelectedIds] = useState([]); - const [originData, setOriginData] = useState([]); + const [selectedScope, setSelectedScope] = useState< + Array<{ + id: ID; + name: string; + }> + >([]); const [search, setSearch] = useState(''); const [version, setVersion] = useState(0); const searchDebounce = useDebounce(search, { wait: 500 }); useEffect(() => { - setSelectedIds((initialScope ?? []).map((sc) => sc.id)); + setSelectedIds((initialScope ?? []).map((it) => getPluginScopeId(plugin, it.scope))); + setSelectedScope( + (initialScope ?? []).map((it) => ({ + id: getPluginScopeId(plugin, it.scope), + name: it.scope.fullName ?? it.scope.name, + })), + ); }, []); const request = useCallback( @@ -87,21 +98,10 @@ export const DataScopeSelect = ({ - Select the data scope in this Connection that you wish to associate with this Project. If you wish to add - more Data Scope to this Connection, please{' '} - go to the Connection page. - - ) : ( - <> - There is no Data Scope in this connection yet, please{' '} - - add Data Scope and manage their Scope Configs - {' '} - first. - - ) + <> + If no Data Scope appears in the dropdown list, please{' '} + add one to this connection first. + } required > @@ -125,9 +125,8 @@ export const DataScopeSelect = ({ )} - {selectedIds.length ? ( - selectedIds.map((id) => { - const item = originData.find((it) => getPluginScopeId(plugin, it.scope) === `${id}`); + {selectedScope.length ? ( + selectedScope.map(({ id, name }) => { return ( setSelectedIds(selectedIds.filter((it) => it !== id))} > - {item?.scope.fullName ?? item?.scope.name} + {name} ); }) @@ -168,7 +167,14 @@ export const DataScopeSelect = ({ selectedIds={selectedIds} onSelectedIds={(ids, data) => { setSelectedIds(ids); - setOriginData(data ?? []); + setSelectedScope( + data + ?.filter((it) => ids.includes(getPluginScopeId(plugin, it.scope))) + .map((it) => ({ + id: getPluginScopeId(plugin, it.scope), + name: it.scope.fullName ?? it.scope.name, + })) ?? [], + ); }} /> diff --git a/config-ui/src/routes/blueprint/connection-detail/index.tsx b/config-ui/src/routes/blueprint/connection-detail/index.tsx index 8483051aef7..de37d1bb7e9 100644 --- a/config-ui/src/routes/blueprint/connection-detail/index.tsx +++ b/config-ui/src/routes/blueprint/connection-detail/index.tsx @@ -60,6 +60,13 @@ export const BlueprintConnectionDetailPage = () => { API.connection.get(plugin, connectionId), ]); + const scopeIds = + blueprint.connections + .find((cs) => cs.pluginName === plugin && cs.connectionId === +connectionId) + ?.scopes?.map((sc: any) => sc.scopeId) ?? []; + + const scopes = await Promise.all(scopeIds.map((scopeId) => API.scope.get(plugin, connectionId, scopeId))); + return { blueprint, connection: { @@ -68,10 +75,7 @@ export const BlueprintConnectionDetailPage = () => { id: +connectionId, name: connection.name, }, - scopeIds: - blueprint.connections - .find((cs) => cs.pluginName === plugin && cs.connectionId === +connectionId) - ?.scopes?.map((sc: any) => sc.scopeId) ?? [], + scopes, }; }, [version, pname, bid]); @@ -79,7 +83,7 @@ export const BlueprintConnectionDetailPage = () => { return ; } - const { blueprint, connection, scopeIds } = data; + const { blueprint, connection, scopes } = data; const handleShowDataScope = () => setOpen(true); const handleHideDataScope = () => setOpen(false); @@ -228,14 +232,14 @@ export const BlueprintConnectionDetailPage = () => { Manage Data Scope - + ({ id }))} + initialScope={scopes} onCancel={handleHideDataScope} onSubmit={handleChangeDataScope} /> diff --git a/config-ui/src/routes/blueprint/connection-detail/table.tsx b/config-ui/src/routes/blueprint/connection-detail/table.tsx index 7036d59a233..002818e3f6f 100644 --- a/config-ui/src/routes/blueprint/connection-detail/table.tsx +++ b/config-ui/src/routes/blueprint/connection-detail/table.tsx @@ -16,35 +16,31 @@ * */ -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import { Table } from 'antd'; -import API from '@/api'; -import { useRefreshData } from '@/hooks'; import { getPluginScopeId, ScopeConfig } from '@/plugins'; interface Props { plugin: string; connectionId: ID; - scopeIds: ID[]; + scopes: any[]; } -export const BlueprintConnectionDetailTable = ({ plugin, connectionId, scopeIds }: Props) => { +export const BlueprintConnectionDetailTable = ({ plugin, connectionId, scopes }: Props) => { const [version, setVersion] = useState(1); - const { ready, data } = useRefreshData(async () => { - const scopes = await Promise.all(scopeIds.map((scopeId) => API.scope.get(plugin, connectionId, scopeId))); + const dataSource = useMemo(() => { return scopes.map((sc) => ({ id: getPluginScopeId(plugin, sc.scope), name: sc.scope.fullName ?? sc.scope.name, scopeConfigId: sc.scopeConfig?.id, scopeConfigName: sc.scopeConfig?.name, })); - }, [version]); + }, [scopes]); return ( ); }; From a6205951617377576e63196b8d6cf7d6ace0bf35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Fri, 20 Sep 2024 15:35:20 +1200 Subject: [PATCH 10/32] fix: dispaly < 1m when duration less than 1m (#8078) --- config-ui/src/routes/pipeline/components/duration.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-ui/src/routes/pipeline/components/duration.tsx b/config-ui/src/routes/pipeline/components/duration.tsx index 67ea9e290f4..3620fa4bd3e 100644 --- a/config-ui/src/routes/pipeline/components/duration.tsx +++ b/config-ui/src/routes/pipeline/components/duration.tsx @@ -22,7 +22,7 @@ import { IPipelineStatus } from '@/types'; const duration = (minute: number) => { if (minute < 1) { - return '1m'; + return '< 1m'; } if (minute < 60) { From 230e1f5dbd6179d0dce8149df626ee80bcbfac8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Fri, 20 Sep 2024 15:35:37 +1200 Subject: [PATCH 11/32] fix: set status to done when onboard tour close (#8079) --- config-ui/src/index.css | 5 +++++ config-ui/src/routes/onboard/components/tour.tsx | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/config-ui/src/index.css b/config-ui/src/index.css index c322bc785f7..a2d32515dd1 100644 --- a/config-ui/src/index.css +++ b/config-ui/src/index.css @@ -70,3 +70,8 @@ p { #root { height: 100vh; } + + +.ant-tour-title { + padding-right: 28px; +} \ No newline at end of file diff --git a/config-ui/src/routes/onboard/components/tour.tsx b/config-ui/src/routes/onboard/components/tour.tsx index bac65ce67e1..5d780a2083f 100644 --- a/config-ui/src/routes/onboard/components/tour.tsx +++ b/config-ui/src/routes/onboard/components/tour.tsx @@ -18,8 +18,8 @@ import { Tour } from 'antd'; -import { selectOnboard } from '@/features/onboard'; -import { useAppSelector } from '@/hooks'; +import { done as doneFuc, selectOnboard } from '@/features/onboard'; +import { useAppDispatch, useAppSelector } from '@/hooks'; interface Props { nameRef: React.RefObject; @@ -28,6 +28,7 @@ interface Props { } export const OnboardTour = ({ nameRef, connectionRef, configRef }: Props) => { + const dispatch = useAppDispatch(); const { step, done } = useAppSelector(selectOnboard); const steps = [ @@ -53,5 +54,5 @@ export const OnboardTour = ({ nameRef, connectionRef, configRef }: Props) => { return null; } - return ; + return dispatch(doneFuc())} />; }; From cef7f773f3fa443925ca9461ccdd9f7f6d824868 Mon Sep 17 00:00:00 2001 From: Lynwee <1507509064@qq.com> Date: Fri, 20 Sep 2024 11:45:08 +0800 Subject: [PATCH 12/32] fix(project): project cannot be deleted when its pipelines are not finished (#8081) --- backend/core/models/task.go | 5 +++- backend/server/services/blueprint.go | 7 ++++++ backend/server/services/project.go | 34 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/backend/core/models/task.go b/backend/core/models/task.go index 661ba091ade..34be9eff733 100644 --- a/backend/core/models/task.go +++ b/backend/core/models/task.go @@ -34,7 +34,10 @@ const ( TASK_PARTIAL = "TASK_PARTIAL" ) -var PendingTaskStatus = []string{TASK_CREATED, TASK_RERUN, TASK_RUNNING} +var ( + PendingTaskStatus = []string{TASK_CREATED, TASK_RERUN, TASK_RUNNING} + FinishedTaskStatus = []string{TASK_PARTIAL, TASK_CANCELLED, TASK_FAILED, TASK_COMPLETED} +) type TaskProgressDetail struct { TotalSubTasks int `json:"totalSubTasks"` diff --git a/backend/server/services/blueprint.go b/backend/server/services/blueprint.go index d400abae27a..037149d0b2c 100644 --- a/backend/server/services/blueprint.go +++ b/backend/server/services/blueprint.go @@ -238,6 +238,13 @@ func DeleteBlueprint(id uint64) errors.Error { if err != nil { return err } + pipelinesAreUnfinished, err := thereAreUnfinishedPipelinesUnderBlueprint(bp.ID) + if err != nil { + return err + } + if pipelinesAreUnfinished { + return errors.Default.New("There are unfinished pipelines under current blueprint. It can not be deleted now.") + } err = bpManager.DeleteBlueprint(bp.ID) if err != nil { return errors.Default.Wrap(err, "Failed to delete the blueprint") diff --git a/backend/server/services/project.go b/backend/server/services/project.go index 4739232ad20..11ce1be7883 100644 --- a/backend/server/services/project.go +++ b/backend/server/services/project.go @@ -20,6 +20,7 @@ package services import ( "fmt" "github.com/apache/incubator-devlake/helpers/pluginhelper/services" + "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" "strings" "time" @@ -322,6 +323,31 @@ func PatchProject(name string, body map[string]interface{}) (*models.ApiOutputPr return makeProjectOutput(project, false) } +func thereAreUnfinishedPipelinesUnderProject(projectName string) (bool, errors.Error) { + blueprint, err := GetBlueprintByProjectName(projectName) + if err != nil { + return false, err + } + return thereAreUnfinishedPipelinesUnderBlueprint(blueprint.ID) +} + +func thereAreUnfinishedPipelinesUnderBlueprint(blueprintID uint64) (bool, errors.Error) { + // get the first page + dbPipelines, count, err := GetDbPipelines(&PipelineQuery{BlueprintId: blueprintID}) + if err != nil { + return false, err + } + if count <= 0 { + return false, nil + } + for _, pipeline := range dbPipelines { + if !slices.Contains(models.FinishedTaskStatus, pipeline.Status) { + return true, nil + } + } + return false, nil +} + // DeleteProject FIXME ... func DeleteProject(name string) errors.Error { // verify input @@ -333,6 +359,14 @@ func DeleteProject(name string) errors.Error { if err != nil { return err } + // make sure there is no running pipelines in current projects + pipelinesAreUnfinished, err := thereAreUnfinishedPipelinesUnderProject(name) + if err != nil { + return err + } + if pipelinesAreUnfinished { + return errors.Default.New("There are unfinished pipelines under current project. It can not be deleted now.") + } err = deleteProjectBlueprint(name) if err != nil { return err From e524ea74db2292349e5f19d637830c0c253f6c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Fri, 20 Sep 2024 22:12:11 +1200 Subject: [PATCH 13/32] fix: the start and end times are reversed (#8084) --- config-ui/src/routes/pipeline/components/duration.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config-ui/src/routes/pipeline/components/duration.tsx b/config-ui/src/routes/pipeline/components/duration.tsx index 3620fa4bd3e..136b70e5cc0 100644 --- a/config-ui/src/routes/pipeline/components/duration.tsx +++ b/config-ui/src/routes/pipeline/components/duration.tsx @@ -26,20 +26,20 @@ const duration = (minute: number) => { } if (minute < 60) { - return `${Math.ceil(minute / 60)}m`; + return `${minute}m`; } if (minute < 60 * 24) { const hours = Math.floor(minute / 60); const minutes = minute - hours * 60; - return `${hours}h${minutes}m`; + return `${hours}h${minutes !== 0 ? `${minutes}m` : ''}`; } const days = Math.floor(minute / (60 * 24)); const hours = Math.floor((minute - days * 60 * 24) / 60); const minutes = minute - days * 60 * 24 - hours * 60; - return `${days}d${hours}h${minutes}m`; + return `${days}d${hours !== 0 ? `${hours}h` : ''}${minutes !== 0 ? `${minutes}m` : ''}`; }; interface Props { @@ -58,12 +58,12 @@ export const PipelineDuration = ({ status, beganAt, finishedAt }: Props) => { status, ) ) { - return {duration(dayjs(beganAt).diff(dayjs(), 'm'))}; + return {duration(dayjs().diff(dayjs(beganAt), 'm'))}; } if (!finishedAt) { return -; } - return {duration(dayjs(beganAt).diff(dayjs(finishedAt), 'm'))}; + return {duration(dayjs(finishedAt).diff(dayjs(beganAt), 'm'))}; }; From 8949c4f794bcf6c312443d5a6e58f827c6cec010 Mon Sep 17 00:00:00 2001 From: abeizn Date: Fri, 20 Sep 2024 18:53:09 +0800 Subject: [PATCH 14/32] fix: version tag (#8083) * fix: version tag * fix: version tag * fix: version tag --- Makefile | 4 ++-- backend/Makefile | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 9417f650530..80197be9eb7 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,8 @@ # https://stackoverflow.com/questions/920413/make-error-missing-separator # https://tutorialedge.net/golang/makefiles-for-go-developers/ -SHA := $(shell if [ -d .git ]; then git show -s --format=%h; else echo "default_SHA"; fi) -TAG := $(shell if [ -d .git ]; then git tag --points-at HEAD; else echo "default_TAG"; fi) +SHA ?= $(shell git show -s --format=%h 2>/dev/null || echo "default_SHA") +TAG ?= $(shell git tag --points-at HEAD 2>/dev/null || echo "default_TAG") IMAGE_REPO ?= "apache" VERSION = $(TAG)@$(SHA) diff --git a/backend/Makefile b/backend/Makefile index bb321473c38..554ecfe20d9 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -17,13 +17,12 @@ # https://stackoverflow.com/questions/920413/make-error-missing-separator # https://tutorialedge.net/golang/makefiles-for-go-developers/ -SHA := $(shell if [ -d .git ]; then git show -s --format=%h; else echo "default_SHA"; fi) -TAG := $(shell if [ -d .git ]; then git tag --points-at HEAD; else echo "default_TAG"; fi) +SHA ?= $(shell git show -s --format=%h 2>/dev/null || echo "default_SHA") +TAG ?= $(shell git tag --points-at HEAD 2>/dev/null || echo "default_TAG") IMAGE_REPO ?= "apache" VERSION = $(TAG)@$(SHA) PYTHON_DIR ?= "./python" - all: build go-dep: From 1c99dbc90094ac3b598b674adaa5d4cbd275304a Mon Sep 17 00:00:00 2001 From: Lynwee <1507509064@qq.com> Date: Fri, 20 Sep 2024 19:20:52 +0800 Subject: [PATCH 15/32] Update error message (#8086) * fix(project): project cannot be deleted when its pipelines are not finished * chore(framework): update error message --- backend/server/services/blueprint.go | 2 +- backend/server/services/project.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/server/services/blueprint.go b/backend/server/services/blueprint.go index 037149d0b2c..4d106674d24 100644 --- a/backend/server/services/blueprint.go +++ b/backend/server/services/blueprint.go @@ -243,7 +243,7 @@ func DeleteBlueprint(id uint64) errors.Error { return err } if pipelinesAreUnfinished { - return errors.Default.New("There are unfinished pipelines under current blueprint. It can not be deleted now.") + return errors.Default.New("There are unfinished pipelines in the current project. It cannot be deleted at this time.") } err = bpManager.DeleteBlueprint(bp.ID) if err != nil { diff --git a/backend/server/services/project.go b/backend/server/services/project.go index 11ce1be7883..98c9600a076 100644 --- a/backend/server/services/project.go +++ b/backend/server/services/project.go @@ -365,7 +365,7 @@ func DeleteProject(name string) errors.Error { return err } if pipelinesAreUnfinished { - return errors.Default.New("There are unfinished pipelines under current project. It can not be deleted now.") + return errors.Default.New("There are unfinished pipelines in the current project. It cannot be deleted at this time.") } err = deleteProjectBlueprint(name) if err != nil { From 0ca6acf0952a80254e95a569e04d906b541e2e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Mon, 23 Sep 2024 15:24:22 +1200 Subject: [PATCH 16/32] fix: add a space for pipeline duration (#8089) --- config-ui/src/routes/pipeline/components/duration.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-ui/src/routes/pipeline/components/duration.tsx b/config-ui/src/routes/pipeline/components/duration.tsx index 136b70e5cc0..4712860f496 100644 --- a/config-ui/src/routes/pipeline/components/duration.tsx +++ b/config-ui/src/routes/pipeline/components/duration.tsx @@ -32,14 +32,14 @@ const duration = (minute: number) => { if (minute < 60 * 24) { const hours = Math.floor(minute / 60); const minutes = minute - hours * 60; - return `${hours}h${minutes !== 0 ? `${minutes}m` : ''}`; + return `${hours}h${minutes !== 0 ? ` ${minutes}m` : ''}`; } const days = Math.floor(minute / (60 * 24)); const hours = Math.floor((minute - days * 60 * 24) / 60); const minutes = minute - days * 60 * 24 - hours * 60; - return `${days}d${hours !== 0 ? `${hours}h` : ''}${minutes !== 0 ? `${minutes}m` : ''}`; + return `${days}d${hours !== 0 ? ` ${hours}h` : ''}${minutes !== 0 ? ` ${minutes}m` : ''}`; }; interface Props { From bcc3c5f2132433e3c07c4925ba8ea1d7d6180770 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 22 Sep 2024 23:27:55 -0400 Subject: [PATCH 17/32] fix(github-plugin): removes the processed org check to return all the org repos, and pulls the repository data when adding scope (#8088) previous behavior would return a single repository. Also no repo data was returned so the user could not add the repo to devlake fixes part of my issue in #7655 --- backend/plugins/github/api/remote_api.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/backend/plugins/github/api/remote_api.go b/backend/plugins/github/api/remote_api.go index 4044a1d70c4..4d9db29c521 100644 --- a/backend/plugins/github/api/remote_api.go +++ b/backend/plugins/github/api/remote_api.go @@ -202,18 +202,25 @@ func listGithubAppInstalledRepos( } var appRepos GithubAppRepo errors.Must(api.UnmarshalResponse(resApp, &appRepos)) - processedOrgs := make(map[string]struct{}) for _, r := range appRepos.Repositories { orgName := r.Owner.Login - if _, exists := processedOrgs[orgName]; !exists && orgName != "" { + if orgName != "" { children = append(children, dsmodels.DsRemoteApiScopeListEntry[models.GithubRepo]{ Type: api.RAS_ENTRY_TYPE_SCOPE, ParentId: &orgName, Id: fmt.Sprintf("%v", r.ID), Name: fmt.Sprintf("%v", r.Name), FullName: fmt.Sprintf("%v", r.FullName), + Data: &models.GithubRepo{ + GithubId: r.ID, + Name: r.Name, + FullName: r.FullName, + HTMLUrl: r.HTMLURL, + Description: r.Description, + OwnerId: r.Owner.ID, + CloneUrl: r.CloneURL, + }, }) - processedOrgs[orgName] = struct{}{} } } if len(appRepos.Repositories) == page.PerPage { From 3367db446f5e354dba1c6eabb6f0e10495055626 Mon Sep 17 00:00:00 2001 From: sstojak1 <18380216+sstojak1@users.noreply.github.com> Date: Mon, 23 Sep 2024 05:34:49 +0200 Subject: [PATCH 18/32] refactor: CollectAccounts now uses simple ApiCollector (#8067) Co-authored-by: Josip Stojak --- backend/plugins/sonarqube/tasks/accounts_collector.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/backend/plugins/sonarqube/tasks/accounts_collector.go b/backend/plugins/sonarqube/tasks/accounts_collector.go index a6e3f67ebf2..6bb02272e12 100644 --- a/backend/plugins/sonarqube/tasks/accounts_collector.go +++ b/backend/plugins/sonarqube/tasks/accounts_collector.go @@ -36,11 +36,7 @@ func CollectAccounts(taskCtx plugin.SubTaskContext) errors.Error { logger := taskCtx.GetLogger() logger.Info("collect accounts") rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ACCOUNTS_TABLE) - collectorWithState, err := helper.NewStatefulApiCollector(*rawDataSubTaskArgs) - if err != nil { - return err - } - if err := collectorWithState.InitCollector(helper.ApiCollectorArgs{ + collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{ RawDataSubTaskArgs: *rawDataSubTaskArgs, ApiClient: data.ApiClient, PageSize: 100, @@ -59,11 +55,12 @@ func CollectAccounts(taskCtx plugin.SubTaskContext) errors.Error { err := helper.UnmarshalResponse(res, &resData) return resData.Data, err }, - }); err != nil { + }) + if err != nil { return err } - return collectorWithState.Execute() + return collector.Execute() } var CollectAccountsMeta = plugin.SubTaskMeta{ From 9251c42a7599d3b20aae1d0868a25024b3d7bb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Tue, 24 Sep 2024 21:09:56 +1200 Subject: [PATCH 19/32] feat: use redux rewrite project detail (#8095) --- config-ui/src/app/store.ts | 2 + config-ui/src/features/project/index.ts | 19 ++++++ config-ui/src/features/project/slice.ts | 65 +++++++++++++++++++ .../plugins/register/webhook/connection.tsx | 5 +- .../project/additional-settings/index.tsx | 11 ++-- .../routes/project/general-settings/index.tsx | 15 ++--- config-ui/src/routes/project/layout/index.tsx | 18 ++++- .../src/routes/project/webhook/index.tsx | 61 ++++++++++------- config-ui/src/types/webhook.ts | 4 +- 9 files changed, 153 insertions(+), 47 deletions(-) create mode 100644 config-ui/src/features/project/index.ts create mode 100644 config-ui/src/features/project/slice.ts diff --git a/config-ui/src/app/store.ts b/config-ui/src/app/store.ts index f95900a4635..5932edc7faa 100644 --- a/config-ui/src/app/store.ts +++ b/config-ui/src/app/store.ts @@ -21,12 +21,14 @@ import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'; import { versionSlice } from '@/features/version'; import { connectionsSlice } from '@/features/connections'; import { onboardSlice } from '@/features/onboard'; +import { projectSlice } from '@/features/project'; export const store = configureStore({ reducer: { version: versionSlice.reducer, connections: connectionsSlice.reducer, onboard: onboardSlice.reducer, + project: projectSlice.reducer, }, }); diff --git a/config-ui/src/features/project/index.ts b/config-ui/src/features/project/index.ts new file mode 100644 index 00000000000..513ab48a7f8 --- /dev/null +++ b/config-ui/src/features/project/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + * + */ + +export * from './slice'; diff --git a/config-ui/src/features/project/slice.ts b/config-ui/src/features/project/slice.ts new file mode 100644 index 00000000000..0c59dba73e3 --- /dev/null +++ b/config-ui/src/features/project/slice.ts @@ -0,0 +1,65 @@ +/* + * 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. + * + */ + +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; + +import API from '@/api'; +import type { RootState } from '@/app/store'; +import type { IStatus, IProject } from '@/types'; + +export const request = createAsyncThunk('project/request', async (name: string) => { + const res = await API.project.get(name); + return res; +}); + +const initialState: { status: IStatus; data?: IProject } = { + status: 'loading', +}; + +export const projectSlice = createSlice({ + name: 'project', + initialState, + reducers: { + updateBlueprint: (state, action) => { + if (state.data) { + state.data.blueprint = action.payload; + } + }, + }, + extraReducers: (builder) => { + builder + .addCase(request.pending, (state) => { + state.status = 'loading'; + }) + .addCase(request.fulfilled, (state, action) => { + state.status = 'success'; + state.data = action.payload; + }) + .addCase(request.rejected, (state) => { + state.status = 'failed'; + }); + }, +}); + +export const { updateBlueprint } = projectSlice.actions; + +export default projectSlice.reducer; + +export const selectProjectStatus = (state: RootState) => state.project.status; + +export const selectProject = (state: RootState) => state.project.data; diff --git a/config-ui/src/plugins/register/webhook/connection.tsx b/config-ui/src/plugins/register/webhook/connection.tsx index 32bfd6f5e8b..c83f1813d13 100644 --- a/config-ui/src/plugins/register/webhook/connection.tsx +++ b/config-ui/src/plugins/register/webhook/connection.tsx @@ -115,7 +115,10 @@ export const WebHookConnection = ({ filterIds, fromProject = false, onAssociate, title="Remove this Webhook?" okText="Confirm" onCancel={handleHideDialog} - onOk={() => onRemove?.(currentID)} + onOk={() => { + onRemove?.(currentID); + handleHideDialog(); + }} > diff --git a/config-ui/src/routes/project/additional-settings/index.tsx b/config-ui/src/routes/project/additional-settings/index.tsx index 5d670bb772b..feac602150d 100644 --- a/config-ui/src/routes/project/additional-settings/index.tsx +++ b/config-ui/src/routes/project/additional-settings/index.tsx @@ -17,12 +17,13 @@ */ import { useEffect, useState } from 'react'; -import { useParams, useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import { Flex, Space, Card, Modal, Input, Checkbox, Button } from 'antd'; import API from '@/api'; import { Block, HelpTooltip, Message } from '@/components'; -import { useRefreshData } from '@/hooks'; +import { selectProject } from '@/features/project'; +import { useAppSelector } from '@/hooks'; import { operator } from '@/utils'; const RegexPrIssueDefaultValue = '(?mi)(Closes)[\\s]*.*(((and )?#\\d+[ ]*)+)'; @@ -41,13 +42,10 @@ export const ProjectAdditionalSettings = () => { }); const [operating, setOperating] = useState(false); const [open, setOpen] = useState(false); - const [version, setVersion] = useState(0); const navigate = useNavigate(); - const { pname } = useParams() as { pname: string }; - - const { data: project } = useRefreshData(() => API.project.get(pname), [pname, version]); + const project = useAppSelector(selectProject); useEffect(() => { if (!project) { @@ -107,7 +105,6 @@ export const ProjectAdditionalSettings = () => { ); if (success) { - setVersion((v) => v + 1); navigate(`/projects/${encodeURIComponent(name)}`, { state: { tabId: 'settings', diff --git a/config-ui/src/routes/project/general-settings/index.tsx b/config-ui/src/routes/project/general-settings/index.tsx index ef538afcc1b..4a7245a066e 100644 --- a/config-ui/src/routes/project/general-settings/index.tsx +++ b/config-ui/src/routes/project/general-settings/index.tsx @@ -16,20 +16,15 @@ * */ -import { useParams } from 'react-router-dom'; - -import API from '@/api'; -import { PageLoading } from '@/components'; -import { useRefreshData } from '@/hooks'; +import { selectProject } from '@/features/project'; +import { useAppSelector } from '@/hooks'; import { BlueprintDetail, FromEnum } from '@/routes'; export const ProjectGeneralSettings = () => { - const { pname } = useParams() as { pname: string }; - - const { ready, data: project } = useRefreshData(() => API.project.get(pname), [pname]); + const project = useAppSelector(selectProject); - if (!ready || !project) { - return ; + if (!project) { + return null; } return ; diff --git a/config-ui/src/routes/project/layout/index.tsx b/config-ui/src/routes/project/layout/index.tsx index d96747a297c..23d5e4dcac9 100644 --- a/config-ui/src/routes/project/layout/index.tsx +++ b/config-ui/src/routes/project/layout/index.tsx @@ -16,12 +16,14 @@ * */ -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { useParams, useNavigate, useLocation, Link, Outlet } from 'react-router-dom'; import { RollbackOutlined } from '@ant-design/icons'; import { Layout, Menu } from 'antd'; -import { PageHeader } from '@/components'; +import { PageHeader, PageLoading } from '@/components'; +import { request, selectProjectStatus, selectProject } from '@/features/project'; +import { useAppDispatch, useAppSelector } from '@/hooks'; import { ProjectSelector } from './project-selector'; import * as S from './styled'; @@ -86,6 +88,14 @@ export const ProjectLayout = () => { const navigate = useNavigate(); const { pathname } = useLocation(); + const dispatch = useAppDispatch(); + const status = useAppSelector(selectProjectStatus); + const project = useAppSelector(selectProject); + + useEffect(() => { + dispatch(request(pname)); + }, [pname]); + const { paths, selectedKeys, title } = useMemo(() => { const paths = pathname.split('/'); const key = paths.pop(); @@ -103,6 +113,10 @@ export const ProjectLayout = () => { }; }, [pathname]); + if (status === 'loading' || !project) { + return ; + } + return ( diff --git a/config-ui/src/routes/project/webhook/index.tsx b/config-ui/src/routes/project/webhook/index.tsx index 20e828f714f..3c9d937f3bd 100644 --- a/config-ui/src/routes/project/webhook/index.tsx +++ b/config-ui/src/routes/project/webhook/index.tsx @@ -17,13 +17,15 @@ */ import { useState, useMemo } from 'react'; -import { useParams, Link } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import { PlusOutlined } from '@ant-design/icons'; import { Alert, Button } from 'antd'; import API from '@/api'; import { NoData } from '@/components'; -import { useRefreshData } from '@/hooks'; +import { selectProject, updateBlueprint } from '@/features/project'; +import { selectWebhooks } from '@/features/connections'; +import { useAppDispatch, useAppSelector } from '@/hooks'; import type { WebhookItemType } from '@/plugins/register/webhook'; import { WebhookCreateDialog, WebhookSelectorDialog, WebHookConnection } from '@/plugins/register/webhook'; import { operator } from '@/utils'; @@ -31,18 +33,20 @@ import { operator } from '@/utils'; export const ProjectWebhook = () => { const [type, setType] = useState<'selectExist' | 'create'>(); const [operating, setOperating] = useState(false); - const [version, setVersion] = useState(0); - const { pname } = useParams() as { pname: string }; - - const { data } = useRefreshData(() => API.project.get(pname), [pname, version]); + const dispatch = useAppDispatch(); + const project = useAppSelector(selectProject); + const webhooks = useAppSelector(selectWebhooks); const webhookIds = useMemo( () => - data?.blueprint - ? data?.blueprint.connections.filter((cs) => cs.pluginName === 'webhook').map((cs: any) => cs.connectionId) + project?.blueprint + ? project?.blueprint.connections + .filter((cs) => cs.pluginName === 'webhook') + .filter((cs) => webhooks.map((wh) => wh.id).includes(cs.connectionId)) + .map((cs: any) => cs.connectionId) : [], - [data], + [project], ); const handleCancel = () => { @@ -50,14 +54,16 @@ export const ProjectWebhook = () => { }; const handleCreate = async (id: ID) => { - if (!data) { + if (!project) { return; } const payload = { - ...data.blueprint, + ...project.blueprint, connections: [ - ...data.blueprint.connections, + ...project.blueprint.connections.filter( + (cs) => cs.pluginName !== 'webhook' || webhookIds.includes(cs.connectionId), + ), { pluginName: 'webhook', connectionId: id, @@ -65,25 +71,28 @@ export const ProjectWebhook = () => { ], }; - const [success] = await operator(() => API.blueprint.update(data.blueprint.id, payload), { + const [success] = await operator(() => API.blueprint.update(project.blueprint.id, payload), { setOperating, + hideToast: true, }); if (success) { - setVersion(version + 1); handleCancel(); + dispatch(updateBlueprint(payload)); } }; const handleSelect = async (items: WebhookItemType[]) => { - if (!data) { + if (!project) { return; } const payload = { - ...data.blueprint, + ...project.blueprint, connections: [ - ...data.blueprint.connections, + ...project.blueprint.connections.filter( + (cs) => cs.pluginName !== 'webhook' || webhookIds.includes(cs.connectionId), + ), ...items.map((it) => ({ pluginName: 'webhook', connectionId: it.id, @@ -91,33 +100,35 @@ export const ProjectWebhook = () => { ], }; - const [success] = await operator(() => API.blueprint.update(data.blueprint.id, payload), { + const [success] = await operator(() => API.blueprint.update(project.blueprint.id, payload), { setOperating, }); if (success) { - setVersion(version + 1); handleCancel(); + dispatch(updateBlueprint(payload)); } }; const handleDelete = async (id: ID) => { - if (!data) { + if (!project) { return; } const payload = { - ...data.blueprint, - connections: data.blueprint.connections.filter((cs) => !(cs.pluginName === 'webhook' && cs.connectionId === id)), + ...project.blueprint, + connections: project.blueprint.connections + .filter((cs) => cs.pluginName !== 'webhook' || webhookIds.includes(cs.connectionId)) + .filter((cs) => !(cs.pluginName === 'webhook' && cs.connectionId === id)), }; - const [success] = await operator(() => API.blueprint.update(data.blueprint.id, payload), { + const [success] = await operator(() => API.blueprint.update(project.blueprint.id, payload), { setOperating, }); if (success) { - setVersion(version + 1); handleCancel(); + dispatch(updateBlueprint(payload)); } }; @@ -135,7 +146,7 @@ export const ProjectWebhook = () => {
To calculate DORA after receiving Webhook data immediately, you can visit the{' '} - Status tab + Status tab {' '} of the Blueprint page and click on Run Now.
diff --git a/config-ui/src/types/webhook.ts b/config-ui/src/types/webhook.ts index 2035bf67595..5ea4b89cd17 100644 --- a/config-ui/src/types/webhook.ts +++ b/config-ui/src/types/webhook.ts @@ -17,7 +17,7 @@ */ export interface IWebhookAPI { - id: number; + id: ID; name: string; postIssuesEndpoint: string; closeIssuesEndpoint: string; @@ -29,7 +29,7 @@ export interface IWebhookAPI { } export interface IWebhook { - id: number; + id: ID; name: string; postIssuesEndpoint: string; closeIssuesEndpoint: string; From f3b134bee2b6ae6dcbfc07b422514050664794ed Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Wed, 25 Sep 2024 08:50:14 +0200 Subject: [PATCH 20/32] Add missing URL (#8097) * Fix missing link * add actual link --- config-ui/src/plugins/components/scope-config-form/index.tsx | 4 ++-- config-ui/src/release/stable.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config-ui/src/plugins/components/scope-config-form/index.tsx b/config-ui/src/plugins/components/scope-config-form/index.tsx index 5c27d84d454..ab2aabef78f 100644 --- a/config-ui/src/plugins/components/scope-config-form/index.tsx +++ b/config-ui/src/plugins/components/scope-config-form/index.tsx @@ -150,8 +150,8 @@ export const ScopeConfigForm = ({ title="Data Entities" description={ <> - Select the data entities you wish to collect for the Data Scope. - Learn about data entities + Select the data entities you wish to collect for the Data Scope. + Learn about data entities } required diff --git a/config-ui/src/release/stable.ts b/config-ui/src/release/stable.ts index 5e725302094..c782752e953 100644 --- a/config-ui/src/release/stable.ts +++ b/config-ui/src/release/stable.ts @@ -21,6 +21,7 @@ const URLS = { ADVANCED_MODE: { EXAMPLES: 'https://devlake.apache.org/docs/Configuration/AdvancedMode/#examples', }, + DATA_ENTITIES: 'https://devlake.apache.org/docs/Overview/KeyConcepts#data-entities', DORA: 'https://devlake.apache.org/docs/DORA/', PLUGIN: { AZUREDEVOPS: { From 323b98e6653034a4be40f4c3b8e2c0ae04225861 Mon Sep 17 00:00:00 2001 From: Klesh Wong Date: Wed, 25 Sep 2024 16:14:50 +0800 Subject: [PATCH 21/32] feat: improve performance of the listing-scope-config-projects-and-scopes (#8104) * feat: improve performance of the listing-scope-config-projects-and-scopes * fix: linting --- .../srvhelper/scope_config_service_helper.go | 102 ++++++++---------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/backend/helpers/srvhelper/scope_config_service_helper.go b/backend/helpers/srvhelper/scope_config_service_helper.go index c06354d25c9..6c7e3e05f0e 100644 --- a/backend/helpers/srvhelper/scope_config_service_helper.go +++ b/backend/helpers/srvhelper/scope_config_service_helper.go @@ -18,6 +18,9 @@ limitations under the License. package srvhelper import ( + "fmt" + "strings" + "github.com/apache/incubator-devlake/core/context" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" @@ -57,67 +60,56 @@ func (scopeConfigSrv *ScopeConfigSrvHelper[C, S, SC]) GetAllByConnectionId(conne } func (scopeConfigSrv *ScopeConfigSrvHelper[C, S, SC]) GetProjectsByScopeConfig(pluginName string, scopeConfig *SC) (*models.ProjectScopeOutput, errors.Error) { - ps := &models.ProjectScopeOutput{} - projectMap := make(map[string]*models.ProjectScope) - // 1. get all scopes that are using the scopeConfigId - var scope []*S - err := scopeConfigSrv.db.All(&scope, - dal.Where("scope_config_id = ?", (*scopeConfig).ScopeConfigId()), - ) - if err != nil { - return nil, err + s := new(S) + // find out the primary key of the scope model + sPk := errors.Must1(dal.GetPrimarykeyColumnNames(scopeConfigSrv.db, (interface{}(s)).(dal.Tabler))) + if len(sPk) != 2 { + return nil, errors.Internal.New("Scope model should have 2 primary key fields") } - for _, s := range scope { - // 2. get blueprint id by connection id and scope id - bpScope := []*models.BlueprintScope{} - err = scopeConfigSrv.db.All(&bpScope, - dal.Where("plugin_name = ? and connection_id = ? and scope_id = ?", pluginName, (*s).ScopeConnectionId(), (*s).ScopeId()), - ) - if err != nil { - return nil, err - } - - for _, bs := range bpScope { - // 3. get project details by blueprint id - bp := models.Blueprint{} - err = scopeConfigSrv.db.All(&bp, - dal.Where("id = ?", bs.BlueprintId), - ) - if err != nil { - return nil, err - } - if project, exists := projectMap[bp.ProjectName]; exists { - project.Scopes = append(project.Scopes, struct { - ScopeID string `json:"scopeId"` - ScopeName string `json:"scopeName"` - }{ - ScopeID: bs.ScopeId, - ScopeName: (*s).ScopeName(), - }) - } else { - projectMap[bp.ProjectName] = &models.ProjectScope{ - Name: bp.ProjectName, - BlueprintId: bp.ID, - Scopes: []struct { - ScopeID string `json:"scopeId"` - ScopeName string `json:"scopeName"` - }{ - { - ScopeID: bs.ScopeId, - ScopeName: (*s).ScopeName(), - }, - }, - } + theOtherPk := sPk[0] + if strings.HasSuffix(theOtherPk, ".connection_id") { + theOtherPk = sPk[1] + } + var bpss []struct { + S *S `gorm:"embedded"` + BlueprintId uint64 + ProjectName string + ScopeId string + } + scopeTable := (*s).TableName() + errors.Must(scopeConfigSrv.db.All( + &bpss, + dal.Select(fmt.Sprintf("bp.id AS blueprint_id, bp.project_name, bps.scope_id, %s.*", scopeTable)), + dal.From("_devlake_blueprint_scopes bps"), + dal.Join("LEFT JOIN _devlake_blueprints bp ON (bp.id = bps.blueprint_id)"), + dal.Join(fmt.Sprintf("LEFT JOIN %s ON (%s.connection_id = bps.connection_id AND %s = bps.scope_id)", scopeTable, scopeTable, theOtherPk)), + dal.Where("bps.plugin_name = ? AND bps.connection_id = ?", pluginName, (*scopeConfig).ScopeConfigConnectionId()), + )) + projectScopeMap := make(map[string]*models.ProjectScope) + for _, bps := range bpss { + if _, ok := projectScopeMap[bps.ProjectName]; !ok { + projectScopeMap[bps.ProjectName] = &models.ProjectScope{ + Name: bps.ProjectName, + BlueprintId: bps.BlueprintId, } } + projectScopeMap[bps.ProjectName].Scopes = append( + projectScopeMap[bps.ProjectName].Scopes, + struct { + ScopeID string `json:"scopeId"` + ScopeName string `json:"scopeName"` + }{ + ScopeID: bps.ScopeId, + ScopeName: (*bps.S).ScopeName(), + }, + ) } - // 4. combine all projects - for _, project := range projectMap { - ps.Projects = append(ps.Projects, *project) + ps := &models.ProjectScopeOutput{} + for _, projectScope := range projectScopeMap { + ps.Projects = append(ps.Projects, *projectScope) } ps.Count = len(ps.Projects) - - return ps, err + return ps, nil } func (scopeConfigSrv *ScopeConfigSrvHelper[C, S, SC]) DeleteScopeConfig(scopeConfig *SC) (refs []*S, err errors.Error) { From fb0dd2e878aee3e866480304eff40e9d96cafbbe Mon Sep 17 00:00:00 2001 From: abeizn Date: Wed, 25 Sep 2024 16:19:24 +0800 Subject: [PATCH 22/32] feat: dora config (#8103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: github/graphql dora config and adjust regex function (#8026) * feat: adjust the part of github scope config cicd * fix: github dora config api (#8032) * feat: jenkins dora config (#8033) * feat: circleci dora config (#8038) * feat: bitbucket dora config (#8043) * fix: check match items cannot iterable * fix: some style for github transformation cicd * feat: bamboo dora config (#8045) * feat: gitlab dora config + bamboo fix (#8047) * fix: adjust the return value for api * feat: adjust the github transformation cicd style * feat: regex match nil value (#8051) * fix: check match items total * fix: useCustom just defined onece * chore: upgrade antd and @ant-design/icons * fix: check match items total logic error * feat: add github workflow run guideline * fix: return values (#8052) * feat: azure dora config (#8053) * fix: prod match when is nil (#8056) * fix: some bugs for dora config * fix: adjust the deploymentPattern and productionPattern default value * feat: add a new component ShowMore * refactor: use ShowMore component in github transformation * feat: imporve the jenkins transformation cicd configuration * feat: imporve the gitlab transformation cicd configuration * feat: improve the bitbucket transformation cicd configuration * feat: improve the azuredevops transformation cicd configuration * feat: improve the circleci transformation cicd configuration * fix: update github trans-to-deployment scope config to pointer (#8060) * fix: update gitlab trans-to-deployment scope config to pointer (#8062) * fix: update bamboo/bitbuctet/jenkins trans-to-deployment scope config… (#8065) * fix: update bamboo/bitbuctet/jenkins trans-to-deployment scope config to pointer * fix: update circleci trans-to-deployment scope config to pointer * fix: bamboo lint * feat: improve the bamboo transformation cicd configuration * fix: not reset state in check matched items * fix: remove default value about jenkins cicd * fix: cannot check in bitbucket cicd * fix: error default value in deployment * fix: jenkins can not get scope config (#8080) * fix: jenkins can not get scope config * fix: jenkins can not get scope config * fix: some error about miller column * fix: deployment doesn't set value * fix: bitbucket sql (#8085) * fix: missed cicd default value in circleci * fix: throw the error when check matched items request failed * fix: enrich with regex can not match (#8090) * fix: enrich with regex can not match * fix: cannot check in bamboo cicd * fix: bamboo using api client in tool/domain layer (#8094) * fix: not set value for envNamePattern * fix: bamboo repo url * fix: type error * fix: bitbucket e2e * fix: bitbucket e2e * fix: circle ci e2e test * fix: circle ci e2e test * fix: github e2e test * fix: gitlab e2e test * fix: jenkins e2e test * fix: jenkins e2e test * fix: jenkins e2e test * fix: jenkins e2e test --------- Co-authored-by: mintsweet <0x1304570@gmail.com> --- .../models/domainlayer/devops/cicd_task.go | 10 + .../pluginhelper/api/enrich_with_regex.go | 53 +- .../helpers/pluginhelper/api/pagenation.go | 24 + backend/plugins/bamboo/api/connection_api.go | 127 ++++ .../plugins/bamboo/e2e/deploy_build_test.go | 12 +- backend/plugins/bamboo/e2e/job_build_test.go | 11 +- backend/plugins/bamboo/e2e/job_test.go | 7 +- .../bamboo/e2e/plan_build_commits_test.go | 8 +- backend/plugins/bamboo/e2e/plan_build_test.go | 12 +- .../e2e/snapshot_tables/cicd_deployments.csv | 28 +- backend/plugins/bamboo/impl/impl.go | 33 +- ...40906_add_env_name_list_to_scope_config.go | 52 ++ .../models/migrationscripts/register.go | 1 + backend/plugins/bamboo/models/scope_config.go | 5 +- ...oy_build_to_deployment_commit_convertor.go | 6 +- .../deploy_build_to_deployment_convertor.go | 2 +- .../bamboo/tasks/job_build_extractor.go | 6 +- .../bamboo/tasks/plan_build_convertor.go | 2 +- .../bamboo/tasks/plan_build_extractor.go | 9 +- .../plugins/bamboo/tasks/plan_convertor.go | 5 +- backend/plugins/bamboo/tasks/shared.go | 2 +- backend/plugins/bamboo/tasks/shared_test.go | 2 +- .../plugins/bitbucket/api/connection_api.go | 98 +++ .../plugins/bitbucket/e2e/deployments_test.go | 7 +- .../bitbucket/e2e/pipeline_steps_test.go | 8 +- .../plugins/bitbucket/e2e/pipelines_test.go | 8 +- backend/plugins/bitbucket/impl/impl.go | 15 +- .../plugins/bitbucket/models/scope_config.go | 4 +- .../bitbucket/tasks/pipeline_extractor.go | 6 +- .../tasks/pipeline_steps_extractor.go | 6 +- .../plugins/circleci/api/connection_api.go | 96 +++ backend/plugins/circleci/e2e/job_test.go | 7 +- backend/plugins/circleci/e2e/workflow_test.go | 7 +- backend/plugins/circleci/impl/impl.go | 15 +- .../plugins/circleci/models/scope_config.go | 4 +- .../plugins/circleci/tasks/job_converter.go | 6 +- .../circleci/tasks/workflow_converter.go | 6 +- backend/plugins/github/api/connection_api.go | 123 ++++ backend/plugins/github/e2e/cicd_job_test.go | 6 + backend/plugins/github/e2e/cicd_run_test.go | 6 + backend/plugins/github/impl/impl.go | 29 +- ...40906_add_env_name_list_to_scope_config.go | 52 ++ .../models/migrationscripts/register.go | 1 + backend/plugins/github/models/scope_config.go | 5 +- .../github/tasks/cicd_job_extractor.go | 7 +- .../github/tasks/cicd_run_extractor.go | 6 +- backend/plugins/github_graphql/impl/impl.go | 25 +- .../tasks/deployment_convertor.go | 3 +- .../github_graphql/tasks/job_extractor.go | 6 +- backend/plugins/gitlab/api/connection_api.go | 124 ++++ backend/plugins/gitlab/e2e/job_test.go | 7 +- backend/plugins/gitlab/impl/impl.go | 29 +- ...40906_add_env_name_list_to_scope_config.go | 52 ++ .../models/migrationscripts/register.go | 1 + backend/plugins/gitlab/models/scope_config.go | 5 +- .../gitlab/tasks/deployment_convertor.go | 2 +- backend/plugins/gitlab/tasks/job_convertor.go | 7 +- .../gitlab/tasks/pipeline_detail_extractor.go | 6 +- backend/plugins/jenkins/api/connection_api.go | 96 +++ backend/plugins/jenkins/e2e/builds_test.go | 2 +- .../cicd_pipeline_commits_multibranch.csv | 26 +- .../e2e/snapshot_tables/cicd_pipelines.csv | 26 +- .../cicd_pipelines_multibranch.csv | 32 +- .../e2e/snapshot_tables/cicd_tasks.csv | 24 +- .../cicd_tasks_after_stages.csv | 4 +- .../cicd_tasks_after_stages_no_prod_regex.csv | 28 +- .../cicd_tasks_multibranch.csv | 6 +- .../cicd_tasks_no_prod_regex.csv | 24 +- backend/plugins/jenkins/e2e/stages_test.go | 1 + backend/plugins/jenkins/impl/impl.go | 22 +- backend/plugins/jenkins/models/build.go | 20 +- .../20240911_add_url_for_builds.go | 46 ++ .../models/migrationscripts/register.go | 1 + backend/plugins/jenkins/models/response.go | 1 + .../plugins/jenkins/models/scope_config.go | 4 +- .../jenkins/tasks/build_cicd_convertor.go | 12 +- .../plugins/jenkins/tasks/build_collector.go | 2 +- .../plugins/jenkins/tasks/build_extractor.go | 1 + .../plugins/jenkins/tasks/stage_convertor.go | 6 +- .../services/remote/plugin/connection_api.go | 89 ++- .../services/remote/plugin/default_api.go | 3 + config-ui/package.json | 6 +- config-ui/src/api/scope-config/index.ts | 18 +- config-ui/src/api/scope-config/types.ts | 5 + .../components/action/icon-button/index.tsx | 2 +- config-ui/src/components/index.ts | 1 + config-ui/src/components/show-more/index.tsx | 49 ++ .../components/check-matched-items/index.tsx | 115 ++++ .../data-scope-remote/search-local.tsx | 139 +++-- .../data-scope-remote/search-remote.tsx | 8 +- .../components/data-scope-select/index.tsx | 26 +- .../plugins/components/deployments/index.tsx | 109 ++++ config-ui/src/plugins/components/index.ts | 2 + .../components/scope-config-form/index.tsx | 24 +- .../register/azure/assets/workflow-run.jpeg | Bin 0 -> 149316 bytes .../src/plugins/register/azure/config.tsx | 2 - .../plugins/register/azure/transformation.tsx | 30 +- .../plugins/register/azure/workflow-run.tsx | 98 +++ .../register/bamboo/assets/workflow-run.jpeg | Bin 0 -> 113157 bytes .../src/plugins/register/bamboo/config.tsx | 6 +- .../register/bamboo/transformation.tsx | 120 ++-- .../plugins/register/bamboo/workflow-run.tsx | 94 +++ .../bitbucket/assets/workflow-run-1.jpeg | Bin 0 -> 71873 bytes .../bitbucket/assets/workflow-run-2.jpeg | Bin 0 -> 52643 bytes .../src/plugins/register/bitbucket/config.tsx | 2 - .../register/bitbucket/transformation.tsx | 107 ++-- .../register/bitbucket/workflow-run.tsx | 104 ++++ .../circleci/assets/workflow-run.jpeg | Bin 0 -> 197685 bytes .../src/plugins/register/circleci/config.tsx | 5 +- .../register/circleci/transformation.tsx | 41 +- .../register/circleci/workflow-run.tsx | 97 +++ .../register/github/assets/workflow-run.jpeg | Bin 0 -> 189484 bytes .../src/plugins/register/github/config.tsx | 3 - .../register/github/transformation.tsx | 129 ++-- .../plugins/register/github/workflow-run.tsx | 103 ++++ .../register/gitlab/assets/workflow-run.jpeg | Bin 0 -> 193279 bytes .../src/plugins/register/gitlab/config.tsx | 6 +- .../register/gitlab/transformation.tsx | 131 ++-- .../plugins/register/gitlab/workflow-run.tsx | 100 ++++ .../register/jenkins/assets/workflow-run.jpeg | Bin 0 -> 238201 bytes .../src/plugins/register/jenkins/config.tsx | 5 +- .../register/jenkins/transformation.tsx | 35 +- .../plugins/register/jenkins/workflow-run.tsx | 97 +++ .../add-connection-dialog/index.tsx | 2 +- config-ui/yarn.lock | 560 +++++++++++------- 125 files changed, 3266 insertions(+), 803 deletions(-) create mode 100644 backend/plugins/bamboo/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go create mode 100644 backend/plugins/github/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go create mode 100644 backend/plugins/gitlab/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go create mode 100644 backend/plugins/jenkins/models/migrationscripts/20240911_add_url_for_builds.go create mode 100644 config-ui/src/components/show-more/index.tsx create mode 100644 config-ui/src/plugins/components/check-matched-items/index.tsx create mode 100644 config-ui/src/plugins/components/deployments/index.tsx create mode 100644 config-ui/src/plugins/register/azure/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/azure/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/bamboo/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/bamboo/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/bitbucket/assets/workflow-run-1.jpeg create mode 100644 config-ui/src/plugins/register/bitbucket/assets/workflow-run-2.jpeg create mode 100644 config-ui/src/plugins/register/bitbucket/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/circleci/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/circleci/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/github/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/github/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/gitlab/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/gitlab/workflow-run.tsx create mode 100644 config-ui/src/plugins/register/jenkins/assets/workflow-run.jpeg create mode 100644 config-ui/src/plugins/register/jenkins/workflow-run.tsx diff --git a/backend/core/models/domainlayer/devops/cicd_task.go b/backend/core/models/domainlayer/devops/cicd_task.go index 5fd00bbe490..098836fdace 100644 --- a/backend/core/models/domainlayer/devops/cicd_task.go +++ b/backend/core/models/domainlayer/devops/cicd_task.go @@ -36,6 +36,16 @@ const ( const ENV_NAME_PATTERN = "ENV_NAME_PATTERN" +type TransformDeployment struct { + Name string `json:"name"` + URL string `json:"url"` +} + +type TransformDeploymentResponse struct { + Total int `json:"total"` + Data []TransformDeployment `json:"data"` +} + type CICDTask struct { domainlayer.DomainEntity Name string `gorm:"type:varchar(255)"` diff --git a/backend/helpers/pluginhelper/api/enrich_with_regex.go b/backend/helpers/pluginhelper/api/enrich_with_regex.go index 5e7bd2a3a76..4425fe32188 100644 --- a/backend/helpers/pluginhelper/api/enrich_with_regex.go +++ b/backend/helpers/pluginhelper/api/enrich_with_regex.go @@ -28,12 +28,13 @@ import ( // TODO: remove Enricher from naming since it is more like a util function type RegexEnricher struct { // This field will store compiled regular expression for every pattern - regexpMap map[string]*regexp.Regexp + regexpMap map[string]*regexp.Regexp + regexMapList map[string][]*regexp.Regexp } // NewRegexEnricher initialize a regexEnricher func NewRegexEnricher() *RegexEnricher { - return &RegexEnricher{regexpMap: make(map[string]*regexp.Regexp)} + return &RegexEnricher{regexpMap: make(map[string]*regexp.Regexp), regexMapList: make(map[string][]*regexp.Regexp)} } // AddRegexp will add compiled regular expression for pattern to regexpMap @@ -105,3 +106,51 @@ func (r *RegexEnricher) ReturnNameIfOmittedOrMatched(name string, targets ...str } return r.ReturnNameIfMatched(name, targets...) } + +// TryAdd a named regexp if given pattern is not empty +func (r *RegexEnricher) TryAddList(name string, patterns ...string) errors.Error { + if _, ok := r.regexMapList[name]; ok { + return errors.Default.New(fmt.Sprintf("Regex pattern with name: %s already exists", name)) + } + var regexList []*regexp.Regexp + for _, pattern := range patterns { + if pattern == "" { + continue + } + regex, err := errors.Convert01(regexp.Compile(pattern)) + if err != nil { + return errors.BadInput.Wrap(err, fmt.Sprintf("Fail to compile pattern for regex pattern: %s", pattern)) + } + regexList = append(regexList, regex) + } + + // Only save non-empty regexList + if len(regexList) > 0 { + r.regexMapList[name] = regexList + } + return nil +} + +// ReturnNameIfMatched will return name if any of the targets matches the regex associated with the given name +func (r *RegexEnricher) ReturnNameIfMatchedList(name string, targets ...string) string { + if regexList, ok := r.regexMapList[name]; !ok { + return "" + } else { + for _, regex := range regexList { + for _, target := range targets { + if regex.MatchString(target) { + return name + } + } + } + return "" // If any regex fails to match, return "" + } +} + +// ReturnNameIfOmittedOrMatched returns the given name if regex of the given name is omitted or fallback to ReturnNameIfMatched +func (r *RegexEnricher) ReturnNameIfOmittedOrMatchedList(name string, targets ...string) string { + if _, ok := r.regexMapList[name]; !ok { + return name + } + return r.ReturnNameIfMatched(name, targets...) +} diff --git a/backend/helpers/pluginhelper/api/pagenation.go b/backend/helpers/pluginhelper/api/pagenation.go index 784ac61e49a..6c3ea7e5f5f 100644 --- a/backend/helpers/pluginhelper/api/pagenation.go +++ b/backend/helpers/pluginhelper/api/pagenation.go @@ -20,6 +20,8 @@ package api import ( "net/url" "strconv" + + "github.com/go-errors/errors" ) const pageSize = 50 @@ -47,3 +49,25 @@ func GetLimitOffset(q url.Values, pageSizeKey, pageKey string) (limit int, offse offset = (page - 1) * limit return limit, offset } + +func ParsePageParam(body map[string]interface{}, paramName string, defaultValue int) (int, error) { + value, exists := body[paramName] + if !exists { + return defaultValue, nil + } + + switch v := value.(type) { + case int: + return v, nil + case float64: + return int(v), nil + case string: + parsedValue, err := strconv.Atoi(v) + if err != nil { + return 0, errors.New("invalid " + paramName + " value") + } + return parsedValue, nil + default: + return 0, errors.New(paramName + " must be int or string") + } +} diff --git a/backend/plugins/bamboo/api/connection_api.go b/backend/plugins/bamboo/api/connection_api.go index 3fd72a22e48..bf35d5ac3e1 100644 --- a/backend/plugins/bamboo/api/connection_api.go +++ b/backend/plugins/bamboo/api/connection_api.go @@ -21,10 +21,12 @@ import ( "context" "net/http" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/bamboo/models" + "github.com/apache/incubator-devlake/plugins/bamboo/tasks" "github.com/apache/incubator-devlake/server/api/shared" ) @@ -162,3 +164,128 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return dsHelper.ConnApi.GetDetail(input) } + +// GetConnectionDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/bamboo +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {array} string "List of Environment Names" +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/bamboo/connections/{connectionId}/deployments [GET] +func GetConnectionDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + var environments []string + err := db.All(&environments, + dal.From(&models.BambooDeployBuild{}), + dal.Where("connection_id = ?", connectionId), + dal.Select("DISTINCT environment")) + if err != nil { + return nil, err + } + + return &plugin.ApiResourceOutput{ + Body: environments, + }, nil +} + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/bamboo +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/bamboo/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT plan_build_key, link_href, build_started_time + FROM( + SELECT plan_build_key, link_href, build_started_time + FROM _tool_bamboo_plan_builds + WHERE connection_id = ? + AND (plan_name REGEXP ?) + AND (? = '' OR plan_name REGEXP ?) + UNION + SELECT p.plan_build_key, p.link_href, p.build_started_time + FROM _tool_bamboo_job_builds j + LEFT JOIN _tool_bamboo_plan_builds p on p.plan_build_key = j.plan_build_key + WHERE j.connection_id = ? + AND (j.job_name REGEXP ?) + AND (? = '' OR j.job_name REGEXP ?) + ORDER BY build_started_time DESC + ) AS t + ORDER BY build_started_time DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + PlanBuildKey string + LinkHref string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + url, err := tasks.GetBambooHomePage(sf.LinkHref) + if err != nil { + url = sf.LinkHref + } + transformed := transformedFields{ + Name: sf.PlanBuildKey, + URL: url + "/browse/" + sf.PlanBuildKey, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} diff --git a/backend/plugins/bamboo/e2e/deploy_build_test.go b/backend/plugins/bamboo/e2e/deploy_build_test.go index 380d4e26e24..fbcaf086417 100644 --- a/backend/plugins/bamboo/e2e/deploy_build_test.go +++ b/backend/plugins/bamboo/e2e/deploy_build_test.go @@ -41,20 +41,22 @@ func getFakeAPIClient() *helper.ApiAsyncClient { func TestBambooDeployBuildDataFlow(t *testing.T) { var bamboo impl.Bamboo dataflowTester := e2ehelper.NewDataFlowTester(t, "bamboo", bamboo) + dPattern := "(?i)release" + pPattern := "(?i)release" taskData := &tasks.BambooOptions{ Options: &models.BambooOptions{ ConnectionId: 1, PlanKey: "TEST-PLA2", BambooScopeConfig: &models.BambooScopeConfig{ - DeploymentPattern: "(?i)release", - ProductionPattern: "(?i)release", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, RegexEnricher: helper.NewRegexEnricher(), ApiClient: getFakeAPIClient(), } - taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, taskData.Options.DeploymentPattern) - taskData.RegexEnricher.TryAdd(devops.PRODUCTION, taskData.Options.ProductionPattern) + taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, *taskData.Options.DeploymentPattern) + taskData.RegexEnricher.TryAdd(devops.PRODUCTION, *taskData.Options.ProductionPattern) // import raw data table dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bamboo_api_deploy_builds.csv", "_raw_bamboo_api_deploy_builds") @@ -102,7 +104,7 @@ func TestBambooDeployBuildDataFlow(t *testing.T) { dataflowTester.VerifyTableWithOptions(&devops.CicdDeploymentCommit{}, e2ehelper.TableOptions{ CSVRelPath: "./snapshot_tables/cicd_deployment_commits.csv", IgnoreTypes: []interface{}{common.NoPKModel{}}, - IgnoreFields: []string{"created_date", "queued_date", "started_date", "finished_date"}, + IgnoreFields: []string{"created_date", "queued_date", "started_date", "finished_date", "repo_url"}, }) dataflowTester.VerifyTableWithOptions(&devops.CicdDeploymentCommit{}, e2ehelper.TableOptions{ CSVRelPath: "./snapshot_tables/cicd_deployments.csv", diff --git a/backend/plugins/bamboo/e2e/job_build_test.go b/backend/plugins/bamboo/e2e/job_build_test.go index 7ed7709bc45..4914a5bb942 100644 --- a/backend/plugins/bamboo/e2e/job_build_test.go +++ b/backend/plugins/bamboo/e2e/job_build_test.go @@ -30,22 +30,23 @@ import ( ) func TestBambooJobBuildDataFlow(t *testing.T) { - var bamboo impl.Bamboo dataflowTester := e2ehelper.NewDataFlowTester(t, "bamboo", bamboo) + dPattern := "(?i)release" + pPattern := "(?i)release" taskData := &tasks.BambooOptions{ Options: &models.BambooOptions{ ConnectionId: 1, PlanKey: "TEST-PLA3", BambooScopeConfig: &models.BambooScopeConfig{ - DeploymentPattern: "(?i)compile", - ProductionPattern: "(?i)compile", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, RegexEnricher: helper.NewRegexEnricher(), ApiClient: getFakeAPIClient(), } - taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, taskData.Options.DeploymentPattern) + taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, *taskData.Options.DeploymentPattern) // import raw data table // SELECT * FROM _raw_bamboo_api_job_build INTO OUTFILE "/tmp/_raw_bamboo_api_job_builds.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\r\n'; dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bamboo_api_job_builds.csv", "_raw_bamboo_api_job_builds") @@ -63,7 +64,7 @@ func TestBambooJobBuildDataFlow(t *testing.T) { ) // verify extraction - taskData.RegexEnricher.TryAdd(devops.PRODUCTION, taskData.Options.ProductionPattern) + taskData.RegexEnricher.TryAdd(devops.PRODUCTION, *taskData.Options.ProductionPattern) dataflowTester.FlushTabler(&models.BambooJobBuild{}) dataflowTester.Subtask(tasks.ExtractJobBuildMeta, taskData) dataflowTester.VerifyTable( diff --git a/backend/plugins/bamboo/e2e/job_test.go b/backend/plugins/bamboo/e2e/job_test.go index 8d3a29b0b07..c3efc372a1e 100644 --- a/backend/plugins/bamboo/e2e/job_test.go +++ b/backend/plugins/bamboo/e2e/job_test.go @@ -30,14 +30,15 @@ func TestBambooJobDataFlow(t *testing.T) { var bamboo impl.Bamboo dataflowTester := e2ehelper.NewDataFlowTester(t, "bamboo", bamboo) - + dPattern := "(?i)release" + pPattern := "(?i)release" taskData := &tasks.BambooOptions{ Options: &models.BambooOptions{ ConnectionId: 1, PlanKey: "TEST-PLA1", BambooScopeConfig: &models.BambooScopeConfig{ - DeploymentPattern: "(?i)compile", - ProductionPattern: "(?i)compile", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, ApiClient: getFakeAPIClient(), diff --git a/backend/plugins/bamboo/e2e/plan_build_commits_test.go b/backend/plugins/bamboo/e2e/plan_build_commits_test.go index 99294fd8b2b..2a489d1b878 100644 --- a/backend/plugins/bamboo/e2e/plan_build_commits_test.go +++ b/backend/plugins/bamboo/e2e/plan_build_commits_test.go @@ -29,17 +29,17 @@ import ( ) func TestBambooPlanBuildCommitsDataFlow(t *testing.T) { - var bamboo impl.Bamboo dataflowTester := e2ehelper.NewDataFlowTester(t, "bamboo", bamboo) - + dPattern := "(?i)release" + pPattern := "(?i)release" taskData := &tasks.BambooOptions{ Options: &models.BambooOptions{ ConnectionId: 1, PlanKey: "TEST-PLA2", BambooScopeConfig: &models.BambooScopeConfig{ - DeploymentPattern: "(?i)compile", - ProductionPattern: "(?i)compile", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, ApiClient: getFakeAPIClient(), diff --git a/backend/plugins/bamboo/e2e/plan_build_test.go b/backend/plugins/bamboo/e2e/plan_build_test.go index 67584f8f166..9db7b9eccce 100644 --- a/backend/plugins/bamboo/e2e/plan_build_test.go +++ b/backend/plugins/bamboo/e2e/plan_build_test.go @@ -30,24 +30,24 @@ import ( ) func TestBambooPlanBuildDataFlow(t *testing.T) { - var bamboo impl.Bamboo dataflowTester := e2ehelper.NewDataFlowTester(t, "bamboo", bamboo) - + dPattern := "(?i)release" + pPattern := "(?i)release" taskData := &tasks.BambooOptions{ Options: &models.BambooOptions{ ConnectionId: 1, PlanKey: "TEST-PLA2", BambooScopeConfig: &models.BambooScopeConfig{ - DeploymentPattern: "(?i)compile", - ProductionPattern: "(?i)compile", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, RegexEnricher: helper.NewRegexEnricher(), ApiClient: getFakeAPIClient(), } - taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, taskData.Options.DeploymentPattern) - taskData.RegexEnricher.TryAdd(devops.PRODUCTION, taskData.Options.ProductionPattern) + taskData.RegexEnricher.TryAdd(devops.DEPLOYMENT, *taskData.Options.DeploymentPattern) + taskData.RegexEnricher.TryAdd(devops.PRODUCTION, *taskData.Options.ProductionPattern) // import raw data table // SELECT * FROM _raw_bamboo_api_job_build INTO OUTFILE "/tmp/_raw_bamboo_api_job_builds.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\r\n'; dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_bamboo_api_plan_builds.csv", "_raw_bamboo_api_plan_builds") diff --git a/backend/plugins/bamboo/e2e/snapshot_tables/cicd_deployments.csv b/backend/plugins/bamboo/e2e/snapshot_tables/cicd_deployments.csv index 74cb2db5dfc..357fe6f5b22 100644 --- a/backend/plugins/bamboo/e2e/snapshot_tables/cicd_deployments.csv +++ b/backend/plugins/bamboo/e2e/snapshot_tables/cicd_deployments.csv @@ -1,15 +1,15 @@ id,commit_sha,cicd_scope_id,cicd_deployment_id,name,display_title,url,result,status,original_status,original_result,environment,original_environment,duration_sec,queued_duration_sec,commit_msg,ref_name,repo_id,repo_url,prev_success_deployment_commit_id,subtask_name -bamboo:deployBuildWithVcsRevision:1:130001:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130001:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130002:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130002:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,FAILURE,IN_PROGRESS,IN_PROGRESS,FAILED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130003:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130003:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,IN_PROGRESS,PENDING,REPLACED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130004:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130004:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,IN_PROGRESS,QUEUED,SKIPPED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130005:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130005:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,NEVER,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130006:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130006:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,QUEUED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130007:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130007:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,IN PROGRESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:130008:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130008:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,NOT BUILT,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540100:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540100:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,FAILURE,DONE,FINISHED,FAILED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540101:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540101:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,FAILURE,DONE,FINISHED,FAILED,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540102:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540102:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540105:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540105:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540106:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540106:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, -bamboo:deployBuildWithVcsRevision:1:1540117:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540117:622595,test_project2 - test_plan/release-3,test_project2 - test_plan/release-3,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,fake://127.0.0.1:8080/repos/622595,, +bamboo:deployBuildWithVcsRevision:1:130001:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130001:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130002:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130002:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,FAILURE,IN_PROGRESS,IN_PROGRESS,FAILED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130003:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130003:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,IN_PROGRESS,PENDING,REPLACED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130004:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130004:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,IN_PROGRESS,QUEUED,SKIPPED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130005:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130005:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,NEVER,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130006:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130006:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,QUEUED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130007:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130007:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,IN PROGRESS,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:130008:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:130008:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,,OTHER,NOT_BUILT,NOT BUILT,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540100:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540100:622595,test_project2 - test_plan/release-1,test_project2 - test_plan/release-1,,FAILURE,DONE,FINISHED,FAILED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540101:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540101:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,FAILURE,DONE,FINISHED,FAILED,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540102:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540102:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540105:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540105:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540106:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540106:622595,test_project2 - test_plan/release-2,test_project2 - test_plan/release-2,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,,, +bamboo:deployBuildWithVcsRevision:1:1540117:622595,79b062bd53af15c701193c90b543386557cb7a3a,bamboo:BambooPlan:1:TEST-PLA2,bamboo:deployBuildWithVcsRevision:1:1540117:622595,test_project2 - test_plan/release-3,test_project2 - test_plan/release-3,,SUCCESS,DONE,FINISHED,SUCCESS,dev,dev,0,,,,622595,,, diff --git a/backend/plugins/bamboo/impl/impl.go b/backend/plugins/bamboo/impl/impl.go index 2aae7ad5efa..b90331df1ca 100644 --- a/backend/plugins/bamboo/impl/impl.go +++ b/backend/plugins/bamboo/impl/impl.go @@ -160,11 +160,7 @@ func (p Bamboo) PrepareTaskData(taskCtx plugin.TaskContext, options map[string]i if err != nil { return nil, err } - op.ScopeConfigId = scope.ScopeConfigId - if err != nil { - return nil, errors.Default.Wrap(err, fmt.Sprintf("fail to find plan: %s", op.PlanKey)) - } } if op.BambooScopeConfig == nil && op.ScopeConfigId != 0 { @@ -183,14 +179,25 @@ func (p Bamboo) PrepareTaskData(taskCtx plugin.TaskContext, options map[string]i op.BambooScopeConfig = new(models.BambooScopeConfig) } regexEnricher := helper.NewRegexEnricher() - if err := regexEnricher.TryAdd(devops.DEPLOYMENT, op.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.DeploymentPattern != nil { + if err := regexEnricher.TryAdd(devops.DEPLOYMENT, *op.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err := regexEnricher.TryAdd(devops.PRODUCTION, op.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ProductionPattern != nil { + if err := regexEnricher.TryAdd(devops.PRODUCTION, *op.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } - if err := regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.EnvNamePattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + if len(op.BambooScopeConfig.EnvNameList) > 0 || (len(op.BambooScopeConfig.EnvNameList) == 0 && op.BambooScopeConfig.EnvNamePattern == "") { + if err = regexEnricher.TryAddList(devops.ENV_NAME_PATTERN, op.BambooScopeConfig.EnvNameList...); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNameList`") + } + } else { + if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.BambooScopeConfig.EnvNamePattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + } + } return &tasks.BambooOptions{ Options: op, @@ -248,6 +255,12 @@ func (p Bamboo) ApiResources() map[string]map[string]plugin.ApiResourceHandler { "connections/:connectionId/search-remote-scopes": { "GET": api.SearchRemoteScopes, }, + "connections/:connectionId/deployments": { + "GET": api.GetConnectionDeployments, + }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scopes/:scopeId": { "GET": api.GetScope, "PATCH": api.PatchScope, diff --git a/backend/plugins/bamboo/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go b/backend/plugins/bamboo/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go new file mode 100644 index 00000000000..e0a439e060d --- /dev/null +++ b/backend/plugins/bamboo/models/migrationscripts/20240906_add_env_name_list_to_scope_config.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 = (*addEnvNameListToScopeConfig)(nil) + +type scopeConfig20240906 struct { + EnvNameList []string `gorm:"type:json;serializer:json" json:"env_name_list" mapstructure:"env_name_list"` +} + +func (scopeConfig20240906) TableName() string { + return "_tool_bamboo_scope_configs" +} + +type addEnvNameListToScopeConfig struct{} + +func (*addEnvNameListToScopeConfig) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + if err := db.AutoMigrate(&scopeConfig20240906{}); err != nil { + return err + } + return nil +} + +func (*addEnvNameListToScopeConfig) Version() uint64 { + return 20240906142102 +} + +func (*addEnvNameListToScopeConfig) Name() string { + return "add env_name_list to _tool_bamboo_scope_configs" +} diff --git a/backend/plugins/bamboo/models/migrationscripts/register.go b/backend/plugins/bamboo/models/migrationscripts/register.go index d7ef35c7e55..435368026f3 100644 --- a/backend/plugins/bamboo/models/migrationscripts/register.go +++ b/backend/plugins/bamboo/models/migrationscripts/register.go @@ -38,5 +38,6 @@ func All() []plugin.MigrationScript { new(addMissingPrimaryKeyForBambooPlanBuildVcsRevision), new(addQueuedFieldsInJobBuild20231128), new(addLinkHrefToBambooPlanBuild), + new(addEnvNameListToScopeConfig), } } diff --git a/backend/plugins/bamboo/models/scope_config.go b/backend/plugins/bamboo/models/scope_config.go index 587ba991e4d..46703664aeb 100644 --- a/backend/plugins/bamboo/models/scope_config.go +++ b/backend/plugins/bamboo/models/scope_config.go @@ -24,9 +24,10 @@ import ( type BambooScopeConfig struct { common.ScopeConfig `mapstructure:",squash" json:",inline" gorm:"embedded"` RepoMap map[string][]int `json:"repoMap" gorm:"type:json;serializer:json"` // should be {realRepoName: [bamboo_repoId, ...]} - DeploymentPattern string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` - ProductionPattern string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` + DeploymentPattern *string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` + ProductionPattern *string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` EnvNamePattern string `mapstructure:"envNamePattern,omitempty" json:"envNamePattern" gorm:"type:varchar(255)"` + EnvNameList []string `gorm:"type:json;serializer:json" json:"envNameList" mapstructure:"envNameList"` } func (BambooScopeConfig) TableName() string { diff --git a/backend/plugins/bamboo/tasks/deploy_build_to_deployment_commit_convertor.go b/backend/plugins/bamboo/tasks/deploy_build_to_deployment_commit_convertor.go index 9dc4600efb0..4a68b0e8e7e 100644 --- a/backend/plugins/bamboo/tasks/deploy_build_to_deployment_commit_convertor.go +++ b/backend/plugins/bamboo/tasks/deploy_build_to_deployment_commit_convertor.go @@ -146,7 +146,7 @@ func ConvertDeployBuildsToDeploymentCommits(taskCtx plugin.SubTaskContext) error RepoId: strconv.Itoa(input.RepositoryId), DisplayTitle: input.GenerateCICDDeploymentCommitName(), } - u, err := url.Parse(data.ApiClient.GetEndpoint()) + u, err := url.Parse(data.EndPoint) if err != nil { log.Fatal(err) } @@ -162,9 +162,9 @@ func ConvertDeployBuildsToDeploymentCommits(taskCtx plugin.SubTaskContext) error duration := float64(input.FinishedDate.Sub(*input.ExecutedDate).Milliseconds() / 1e3) deploymentCommit.DurationSec = &duration } - fakeRepoUrl, err := generateFakeRepoUrl(data.ApiClient.GetEndpoint(), input.RepositoryId) + fakeRepoUrl, err := generateFakeRepoUrl(data.EndPoint, input.RepositoryId) if err != nil { - logger.Warn(err, "generate fake repo url, endpoint: %s, repo id: %d", data.ApiClient.GetEndpoint(), input.RepositoryId) + logger.Warn(err, "generate fake repo url, endpoint: %s, repo id: %d", data.EndPoint, input.RepositoryId) } else { deploymentCommit.RepoUrl = fakeRepoUrl } diff --git a/backend/plugins/bamboo/tasks/deploy_build_to_deployment_convertor.go b/backend/plugins/bamboo/tasks/deploy_build_to_deployment_convertor.go index badf42a530c..ffa6568b230 100644 --- a/backend/plugins/bamboo/tasks/deploy_build_to_deployment_convertor.go +++ b/backend/plugins/bamboo/tasks/deploy_build_to_deployment_convertor.go @@ -105,7 +105,7 @@ func ConvertDeployBuildsToDeployments(taskCtx plugin.SubTaskContext) errors.Erro }, DisplayTitle: name, } - if data.RegexEnricher.ReturnNameIfMatched(devops.ENV_NAME_PATTERN, input.Environment) != "" { + if data.RegexEnricher.ReturnNameIfMatchedList(devops.ENV_NAME_PATTERN, input.Environment) != "" { deployment.Environment = devops.PRODUCTION } if input.FinishedDate != nil && input.ExecutedDate != nil { diff --git a/backend/plugins/bamboo/tasks/job_build_extractor.go b/backend/plugins/bamboo/tasks/job_build_extractor.go index 2077aa46749..23bbb04f0cd 100644 --- a/backend/plugins/bamboo/tasks/job_build_extractor.go +++ b/backend/plugins/bamboo/tasks/job_build_extractor.go @@ -52,8 +52,10 @@ func ExtractJobBuild(taskCtx plugin.SubTaskContext) errors.Error { body.PlanKey = data.Options.PlanKey body.PlanName = plan.PlanName body.PlanBuildKey = fmt.Sprintf("%s-%v", plan.PlanKey, body.Number) - body.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.JobName) - body.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, body.JobName) + if data.Options.DeploymentPattern != nil || data.Options.ProductionPattern != nil { + body.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.JobName) + body.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, body.JobName) + } results := make([]interface{}, 0) results = append(results, body) return results, nil diff --git a/backend/plugins/bamboo/tasks/plan_build_convertor.go b/backend/plugins/bamboo/tasks/plan_build_convertor.go index c86e8ae5381..02d4b8ec481 100644 --- a/backend/plugins/bamboo/tasks/plan_build_convertor.go +++ b/backend/plugins/bamboo/tasks/plan_build_convertor.go @@ -91,7 +91,7 @@ func ConvertPlanBuilds(taskCtx plugin.SubTaskContext) errors.Error { OriginalStatus: line.LifeCycleState, DisplayTitle: line.GenerateCICDPipeLineName(), } - homepage, err := getBambooHomePage(line.LinkHref) + homepage, err := GetBambooHomePage(line.LinkHref) if err != nil { logger.Warn(err, "get bamboo home") } else { diff --git a/backend/plugins/bamboo/tasks/plan_build_extractor.go b/backend/plugins/bamboo/tasks/plan_build_extractor.go index c5ef6d50c12..386ec2856a1 100644 --- a/backend/plugins/bamboo/tasks/plan_build_extractor.go +++ b/backend/plugins/bamboo/tasks/plan_build_extractor.go @@ -45,11 +45,12 @@ func ExtractPlanBuild(taskCtx plugin.SubTaskContext) errors.Error { body := res.Convert() body.ConnectionId = data.Options.ConnectionId body.PlanKey = data.Options.PlanKey - body.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.PlanName) - body.Environment = data.RegexEnricher.ReturnNameIfMatched(devops.PRODUCTION, body.PlanName) - + if data.Options.DeploymentPattern != nil || data.Options.ProductionPattern != nil { + body.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.PlanName) + body.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, body.PlanName) + } var url string - homepage, errGetHomePage := getBambooHomePage(body.LinkHref) + homepage, errGetHomePage := GetBambooHomePage(body.LinkHref) if errGetHomePage != nil { logger.Warn(errGetHomePage, "get bamboo home") } else { diff --git a/backend/plugins/bamboo/tasks/plan_convertor.go b/backend/plugins/bamboo/tasks/plan_convertor.go index ba04a8ce785..5125b6c781d 100644 --- a/backend/plugins/bamboo/tasks/plan_convertor.go +++ b/backend/plugins/bamboo/tasks/plan_convertor.go @@ -18,6 +18,8 @@ limitations under the License. package tasks import ( + "reflect" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer" @@ -26,7 +28,6 @@ import ( "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" bambooModels "github.com/apache/incubator-devlake/plugins/bamboo/models" - "reflect" ) const RAW_PLAN_TABLE = "bamboo_plan" @@ -62,7 +63,7 @@ func ConvertPlans(taskCtx plugin.SubTaskContext) errors.Error { Name: bambooPlan.Name, Description: bambooPlan.Description, } - homepage, err := getBambooHomePage(bambooPlan.Href) + homepage, err := GetBambooHomePage(bambooPlan.Href) if err != nil { logger.Warn(err, "get bamboo home") } else { diff --git a/backend/plugins/bamboo/tasks/shared.go b/backend/plugins/bamboo/tasks/shared.go index 182670b954d..544ca698684 100644 --- a/backend/plugins/bamboo/tasks/shared.go +++ b/backend/plugins/bamboo/tasks/shared.go @@ -112,7 +112,7 @@ func GetResultsResult(res *http.Response) ([]json.RawMessage, errors.Error) { } // getBambooHomePage receive endpoint like "http://127.0.0.1:30001/rest/api/latest/" and return bamboo's homepage like "http://127.0.0.1:30001/" -func getBambooHomePage(endpoint string) (string, error) { +func GetBambooHomePage(endpoint string) (string, error) { if endpoint == "" { return "", errors.Default.New("empty endpoint") } diff --git a/backend/plugins/bamboo/tasks/shared_test.go b/backend/plugins/bamboo/tasks/shared_test.go index 941643c4842..18d31c12d17 100644 --- a/backend/plugins/bamboo/tasks/shared_test.go +++ b/backend/plugins/bamboo/tasks/shared_test.go @@ -68,7 +68,7 @@ func Test_getBambooWebURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := getBambooHomePage(tt.args.endpoint) + got, err := GetBambooHomePage(tt.args.endpoint) if (err != nil) != tt.wantErr { t.Errorf("getbambooHomePage() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/backend/plugins/bitbucket/api/connection_api.go b/backend/plugins/bitbucket/api/connection_api.go index 15851e3ab07..a26a48be999 100644 --- a/backend/plugins/bitbucket/api/connection_api.go +++ b/backend/plugins/bitbucket/api/connection_api.go @@ -19,6 +19,7 @@ package api import ( "context" + "fmt" "net/http" "github.com/apache/incubator-devlake/server/api/shared" @@ -173,3 +174,100 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return dsHelper.ConnApi.GetDetail(input) } + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/bitbucket +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/bitbucket/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT build_number, ref_name, repo_id, web_url, bitbucket_created_on + FROM( + SELECT build_number, ref_name, repo_id, web_url, bitbucket_created_on + FROM _tool_bitbucket_pipelines + WHERE connection_id = ? + AND (ref_name REGEXP ?) + AND (? = '' OR ref_name REGEXP ?) + UNION + SELECT build_number, ref_name, p.repo_id, web_url,bitbucket_created_on + FROM _tool_bitbucket_pipelines p + LEFT JOIN _tool_bitbucket_pipeline_steps s on s.pipeline_id = p.bitbucket_id + WHERE s.connection_id = ? + AND (s.name REGEXP ?) + AND (? = '' OR s.name REGEXP ?) + ) AS t + ORDER BY bitbucket_created_on DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + BuildNumber int + RefName string + RepoId string + WebUrl string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("#%d - %s", sf.BuildNumber, sf.RepoId), + URL: fmt.Sprintf("%s%s/pipelines/results/%d", BITBUCKET_CLOUD_URL, sf.RepoId, sf.BuildNumber), + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} + +const BITBUCKET_CLOUD_URL = "https://bitbucket.org/" diff --git a/backend/plugins/bitbucket/e2e/deployments_test.go b/backend/plugins/bitbucket/e2e/deployments_test.go index 8d68a0dff25..9e060d19c23 100644 --- a/backend/plugins/bitbucket/e2e/deployments_test.go +++ b/backend/plugins/bitbucket/e2e/deployments_test.go @@ -31,14 +31,15 @@ import ( func TestDeloymentsDataFlow(t *testing.T) { var bitbucket impl.Bitbucket dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", bitbucket) - + dPattern := "" + pPattern := "" taskData := &tasks.BitbucketTaskData{ Options: &tasks.BitbucketOptions{ ConnectionId: 1, FullName: "likyh/likyhphp", BitbucketScopeConfig: &models.BitbucketScopeConfig{ - DeploymentPattern: "", - ProductionPattern: "", + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, }, }, } diff --git a/backend/plugins/bitbucket/e2e/pipeline_steps_test.go b/backend/plugins/bitbucket/e2e/pipeline_steps_test.go index 85fa31db898..4323c9be103 100644 --- a/backend/plugins/bitbucket/e2e/pipeline_steps_test.go +++ b/backend/plugins/bitbucket/e2e/pipeline_steps_test.go @@ -29,10 +29,10 @@ import ( ) func TestBitbucketPipelineStepsDataFlow(t *testing.T) { - var bitbucket impl.Bitbucket dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", bitbucket) - + dPattern := "" + pPattern := "" regexEnricher := helper.NewRegexEnricher() _ = regexEnricher.TryAdd(devops.DEPLOYMENT, "staging") // _ = regexEnricher.TryAdd(devops.PRODUCTION, "pipeline") // when production regex is omitted, all steps will be treated as production @@ -40,6 +40,10 @@ func TestBitbucketPipelineStepsDataFlow(t *testing.T) { Options: &tasks.BitbucketOptions{ ConnectionId: 1, FullName: "likyh/likyhphp", + BitbucketScopeConfig: &models.BitbucketScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/bitbucket/e2e/pipelines_test.go b/backend/plugins/bitbucket/e2e/pipelines_test.go index 8cffa56338f..2ca6753e349 100644 --- a/backend/plugins/bitbucket/e2e/pipelines_test.go +++ b/backend/plugins/bitbucket/e2e/pipelines_test.go @@ -30,10 +30,10 @@ import ( ) func TestBitbucketPipelineDataFlow(t *testing.T) { - var bitbucket impl.Bitbucket dataflowTester := e2ehelper.NewDataFlowTester(t, "bitbucket", bitbucket) - + dPattern := "" + pPattern := "" regexEnricher := helper.NewRegexEnricher() _ = regexEnricher.TryAdd(devops.DEPLOYMENT, "main") _ = regexEnricher.TryAdd(devops.PRODUCTION, "pipeline") @@ -41,6 +41,10 @@ func TestBitbucketPipelineDataFlow(t *testing.T) { Options: &tasks.BitbucketOptions{ ConnectionId: 1, FullName: "likyh/likyhphp", + BitbucketScopeConfig: &models.BitbucketScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/bitbucket/impl/impl.go b/backend/plugins/bitbucket/impl/impl.go index 9a23ab1b385..dd917790c71 100644 --- a/backend/plugins/bitbucket/impl/impl.go +++ b/backend/plugins/bitbucket/impl/impl.go @@ -176,11 +176,15 @@ func (p Bitbucket) PrepareTaskData(taskCtx plugin.TaskContext, options map[strin } regexEnricher := helper.NewRegexEnricher() - if err := regexEnricher.TryAdd(devops.DEPLOYMENT, op.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.DeploymentPattern != nil { + if err := regexEnricher.TryAdd(devops.DEPLOYMENT, *op.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err := regexEnricher.TryAdd(devops.PRODUCTION, op.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ProductionPattern != nil { + if err := regexEnricher.TryAdd(devops.PRODUCTION, *op.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } taskData := &tasks.BitbucketTaskData{ Options: op, @@ -247,6 +251,9 @@ func (p Bitbucket) ApiResources() map[string]map[string]plugin.ApiResourceHandle "POST": api.PostScopeConfig, "GET": api.GetScopeConfigList, }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scope-configs/:scopeConfigId": { "PATCH": api.PatchScopeConfig, "GET": api.GetScopeConfig, diff --git a/backend/plugins/bitbucket/models/scope_config.go b/backend/plugins/bitbucket/models/scope_config.go index 207485a104b..ca4811f053a 100644 --- a/backend/plugins/bitbucket/models/scope_config.go +++ b/backend/plugins/bitbucket/models/scope_config.go @@ -24,8 +24,8 @@ import ( type BitbucketScopeConfig struct { common.ScopeConfig `mapstructure:",squash" json:",inline" gorm:"embedded"` - DeploymentPattern string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` - ProductionPattern string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` + DeploymentPattern *string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` + ProductionPattern *string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` Refdiff datatypes.JSONMap `mapstructure:"refdiff,omitempty" json:"refdiff" swaggertype:"object" format:"json"` // a string array, split by `,`. diff --git a/backend/plugins/bitbucket/tasks/pipeline_extractor.go b/backend/plugins/bitbucket/tasks/pipeline_extractor.go index ec924db8d17..c0e23ec7e0a 100644 --- a/backend/plugins/bitbucket/tasks/pipeline_extractor.go +++ b/backend/plugins/bitbucket/tasks/pipeline_extractor.go @@ -103,8 +103,10 @@ func ExtractApiPipelines(taskCtx plugin.SubTaskContext) errors.Error { DurationInSeconds: bitbucketApiPipeline.DurationInSeconds, BitbucketCreatedOn: common.Iso8601TimeToTime(bitbucketApiPipeline.CreatedOn), BitbucketCompleteOn: common.Iso8601TimeToTime(bitbucketApiPipeline.CompletedOn), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, bitbucketApiPipeline.Target.RefName), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, bitbucketApiPipeline.Target.RefName), + } + if data.Options.DeploymentPattern != nil || data.Options.ProductionPattern != nil { + bitbucketPipeline.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, bitbucketApiPipeline.Target.RefName) + bitbucketPipeline.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, bitbucketApiPipeline.Target.RefName) } if bitbucketApiPipeline.State.Result != nil { bitbucketPipeline.Result = bitbucketApiPipeline.State.Result.Name diff --git a/backend/plugins/bitbucket/tasks/pipeline_steps_extractor.go b/backend/plugins/bitbucket/tasks/pipeline_steps_extractor.go index 82bd93bd465..684ada9232c 100644 --- a/backend/plugins/bitbucket/tasks/pipeline_steps_extractor.go +++ b/backend/plugins/bitbucket/tasks/pipeline_steps_extractor.go @@ -93,8 +93,10 @@ func ExtractPipelineSteps(taskCtx plugin.SubTaskContext) errors.Error { DurationInSeconds: apiPipelineStep.DurationInSeconds, BuildSecondsUsed: apiPipelineStep.BuildSecondsUsed, RunNumber: apiPipelineStep.RunNumber, - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, apiPipelineStep.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, apiPipelineStep.Name), + } + if data.Options.DeploymentPattern != nil || data.Options.ProductionPattern != nil { + bitbucketStep.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, apiPipelineStep.Name) + bitbucketStep.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, apiPipelineStep.Name) } return []interface{}{ bitbucketStep, diff --git a/backend/plugins/circleci/api/connection_api.go b/backend/plugins/circleci/api/connection_api.go index 37f8389ee43..b2a8c567a99 100644 --- a/backend/plugins/circleci/api/connection_api.go +++ b/backend/plugins/circleci/api/connection_api.go @@ -167,3 +167,99 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return dsHelper.ConnApi.GetDetail(input) } + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/circleci +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/circleci/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT pipeline_number, name, project_slug, created_date + FROM( + SELECT pipeline_number, name, project_slug, created_date + FROM _tool_circleci_workflows + WHERE connection_id = ? + AND (name REGEXP ?) + AND (? = '' OR name REGEXP ?) + UNION + SELECT w.pipeline_number, w.name, w.project_slug, w.created_date + FROM _tool_circleci_jobs j + LEFT JOIN _tool_circleci_workflows w on w.id = j.workflow_id + WHERE j.connection_id = ? + AND (j.name REGEXP ?) + AND (? = '' OR j.name REGEXP ?) + ) AS t + ORDER BY created_date DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + PipelineNumber int + Name string + ProjectSlug string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("#%d - %s", sf.PipelineNumber, sf.Name), + URL: CIRCLECI_URL + sf.ProjectSlug, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} + +const CIRCLECI_URL = "https://app.circleci.com/pipelines/" diff --git a/backend/plugins/circleci/e2e/job_test.go b/backend/plugins/circleci/e2e/job_test.go index 4d426b25185..094e2ee23c0 100644 --- a/backend/plugins/circleci/e2e/job_test.go +++ b/backend/plugins/circleci/e2e/job_test.go @@ -32,12 +32,17 @@ import ( func TestCircleciJob(t *testing.T) { var circleci impl.Circleci - + dPattern := "" + pPattern := "" dataflowTester := e2ehelper.NewDataFlowTester(t, "circleci", circleci) taskData := &tasks.CircleciTaskData{ Options: &tasks.CircleciOptions{ ConnectionId: 1, ProjectSlug: "github/coldgust/coldgust.github.io", + ScopeConfig: &models.CircleciScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: api.NewRegexEnricher(), Project: &models.CircleciProject{ diff --git a/backend/plugins/circleci/e2e/workflow_test.go b/backend/plugins/circleci/e2e/workflow_test.go index cc542fdb27f..358e16a5b05 100644 --- a/backend/plugins/circleci/e2e/workflow_test.go +++ b/backend/plugins/circleci/e2e/workflow_test.go @@ -32,12 +32,17 @@ import ( func TestCircleciWorkflow(t *testing.T) { var circleci impl.Circleci - + dPattern := "" + pPattern := "" dataflowTester := e2ehelper.NewDataFlowTester(t, "circleci", circleci) taskData := &tasks.CircleciTaskData{ Options: &tasks.CircleciOptions{ ConnectionId: 1, ProjectSlug: "github/coldgust/coldgust.github.io", + ScopeConfig: &models.CircleciScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: api.NewRegexEnricher(), } diff --git a/backend/plugins/circleci/impl/impl.go b/backend/plugins/circleci/impl/impl.go index 8e052711a97..8cca5895d9b 100644 --- a/backend/plugins/circleci/impl/impl.go +++ b/backend/plugins/circleci/impl/impl.go @@ -153,11 +153,15 @@ func (p Circleci) PrepareTaskData(taskCtx plugin.TaskContext, options map[string op.ScopeConfig = new(models.CircleciScopeConfig) } regexEnricher := helper.NewRegexEnricher() - if err := regexEnricher.TryAdd(devops.DEPLOYMENT, op.ScopeConfig.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.ScopeConfig.DeploymentPattern != nil { + if err := regexEnricher.TryAdd(devops.DEPLOYMENT, *op.ScopeConfig.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err := regexEnricher.TryAdd(devops.PRODUCTION, op.ScopeConfig.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ScopeConfig.ProductionPattern != nil { + if err := regexEnricher.TryAdd(devops.PRODUCTION, *op.ScopeConfig.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } taskData.RegexEnricher = regexEnricher return taskData, nil @@ -208,6 +212,9 @@ func (p Circleci) ApiResources() map[string]map[string]plugin.ApiResourceHandler "POST": api.PostScopeConfig, "GET": api.GetScopeConfigList, }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scope-configs/:scopeConfigId": { "PATCH": api.PatchScopeConfig, "GET": api.GetScopeConfig, diff --git a/backend/plugins/circleci/models/scope_config.go b/backend/plugins/circleci/models/scope_config.go index 8d6a433bd6b..5b7ed1b46b3 100644 --- a/backend/plugins/circleci/models/scope_config.go +++ b/backend/plugins/circleci/models/scope_config.go @@ -23,8 +23,8 @@ import ( type CircleciScopeConfig struct { common.ScopeConfig `mapstructure:",squash" json:",inline" gorm:"embedded"` - DeploymentPattern string `gorm:"type:varchar(255)" mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern"` - ProductionPattern string `gorm:"type:varchar(255)" mapstructure:"productionPattern,omitempty" json:"productionPattern"` + DeploymentPattern *string `gorm:"type:varchar(255)" mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern"` + ProductionPattern *string `gorm:"type:varchar(255)" mapstructure:"productionPattern,omitempty" json:"productionPattern"` } func (t CircleciScopeConfig) TableName() string { diff --git a/backend/plugins/circleci/tasks/job_converter.go b/backend/plugins/circleci/tasks/job_converter.go index 2cb8de1207c..accfa0ce5ba 100644 --- a/backend/plugins/circleci/tasks/job_converter.go +++ b/backend/plugins/circleci/tasks/job_converter.go @@ -86,8 +86,10 @@ func ConvertJobs(taskCtx plugin.SubTaskContext) errors.Error { Failure: []string{"failed", "failing", "error"}, // not_run,canceled Default: devops.RESULT_DEFAULT, }, userTool.Status), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, userTool.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, userTool.Name), + } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + task.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, userTool.Name) + task.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, userTool.Name) } if task.DurationSec == 0 { task.DurationSec = userTool.DurationSec diff --git a/backend/plugins/circleci/tasks/workflow_converter.go b/backend/plugins/circleci/tasks/workflow_converter.go index 78223f5cf5f..7389b22716c 100644 --- a/backend/plugins/circleci/tasks/workflow_converter.go +++ b/backend/plugins/circleci/tasks/workflow_converter.go @@ -81,10 +81,12 @@ func ConvertWorkflows(taskCtx plugin.SubTaskContext) errors.Error { Failure: []string{"failed", "failing", "error"}, // not_run,canceled Default: devops.RESULT_DEFAULT, }, userTool.Status), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, userTool.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, userTool.Name), DisplayTitle: fmt.Sprintf("%s#%d", userTool.Name, userTool.PipelineNumber), } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + pipeline.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, userTool.Name) + pipeline.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, userTool.Name) + } result := make([]interface{}, 0, 2) result = append(result, pipeline) diff --git a/backend/plugins/github/api/connection_api.go b/backend/plugins/github/api/connection_api.go index a5f0e922ded..a4b9dd66300 100644 --- a/backend/plugins/github/api/connection_api.go +++ b/backend/plugins/github/api/connection_api.go @@ -25,6 +25,7 @@ import ( "github.com/mitchellh/mapstructure" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" @@ -402,3 +403,125 @@ func TestExistingConnection(input *plugin.ApiResourceInput) (*plugin.ApiResource } return &plugin.ApiResourceOutput{Body: testConnectionResult, Status: http.StatusOK}, nil } + +// GetConnectionDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/github +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {array} string "List of Environment Names" +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/github/connections/{connectionId}/deployments [GET] +func GetConnectionDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + var environments []string + err := db.All(&environments, + dal.From(&models.GithubDeployment{}), + dal.Where("connection_id = ?", connectionId), + dal.Select("DISTINCT environment")) + if err != nil { + return nil, err + } + + return &plugin.ApiResourceOutput{ + Body: environments, + }, nil +} + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/github +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/github/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT r.run_number, r.name, r.head_branch, r.html_url, r.run_started_at + FROM ( + SELECT id, run_number, name, head_branch, html_url, run_started_at + FROM _tool_github_runs + WHERE connection_id = ? + AND (name REGEXP ?) + AND (? = '' OR name REGEXP ? OR head_branch REGEXP ?) + UNION + SELECT r.id, r.run_number, r.name, r.head_branch, r.html_url, r.run_started_at + FROM _tool_github_jobs j + LEFT JOIN _tool_github_runs r ON j.run_id = r.id + WHERE j.connection_id = ? + AND (j.name REGEXP ?) + AND (? = '' OR j.name REGEXP ?) + ) r + ORDER BY r.run_started_at DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + RunNumber int + Name string + HeadBranch string + HTMLURL string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("#%d - %s", sf.RunNumber, sf.Name), + URL: sf.HTMLURL, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} diff --git a/backend/plugins/github/e2e/cicd_job_test.go b/backend/plugins/github/e2e/cicd_job_test.go index 9e828961bd8..4ba29ae26d4 100644 --- a/backend/plugins/github/e2e/cicd_job_test.go +++ b/backend/plugins/github/e2e/cicd_job_test.go @@ -32,6 +32,8 @@ import ( func TestGithubCICDJobDataFlow(t *testing.T) { var github impl.Github + dPattern := "" + pPattern := "" dataflowTester := e2ehelper.NewDataFlowTester(t, "github", github) regexEnricher := helper.NewRegexEnricher() _ = regexEnricher.TryAdd(devops.DEPLOYMENT, "deploywindows.*") @@ -40,6 +42,10 @@ func TestGithubCICDJobDataFlow(t *testing.T) { ConnectionId: 1, Name: "panjf2000/ants", GithubId: 134018330, + ScopeConfig: &models.GithubScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/github/e2e/cicd_run_test.go b/backend/plugins/github/e2e/cicd_run_test.go index 750b22e5eab..c155a9b2d9d 100644 --- a/backend/plugins/github/e2e/cicd_run_test.go +++ b/backend/plugins/github/e2e/cicd_run_test.go @@ -32,6 +32,8 @@ import ( func TestGithubCICDRunDataFlow(t *testing.T) { var github impl.Github + dPattern := "" + pPattern := "" dataflowTester := e2ehelper.NewDataFlowTester(t, "github", github) regexEnricher := helper.NewRegexEnricher() _ = regexEnricher.TryAdd(devops.DEPLOYMENT, "CodeQL.*") @@ -40,6 +42,10 @@ func TestGithubCICDRunDataFlow(t *testing.T) { ConnectionId: 1, Name: "panjf2000/ants", GithubId: 134018330, + ScopeConfig: &models.GithubScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/github/impl/impl.go b/backend/plugins/github/impl/impl.go index 07342b78690..52a772cf603 100644 --- a/backend/plugins/github/impl/impl.go +++ b/backend/plugins/github/impl/impl.go @@ -158,14 +158,25 @@ func (p Github) PrepareTaskData(taskCtx plugin.TaskContext, options map[string]i } regexEnricher := helper.NewRegexEnricher() - if err = regexEnricher.TryAdd(devops.DEPLOYMENT, op.ScopeConfig.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.ScopeConfig.DeploymentPattern != nil { + if err = regexEnricher.TryAdd(devops.DEPLOYMENT, *op.ScopeConfig.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err = regexEnricher.TryAdd(devops.PRODUCTION, op.ScopeConfig.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ScopeConfig.ProductionPattern != nil { + if err = regexEnricher.TryAdd(devops.PRODUCTION, *op.ScopeConfig.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } - if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + if len(op.ScopeConfig.EnvNameList) > 0 || (len(op.ScopeConfig.EnvNameList) == 0 && op.ScopeConfig.EnvNamePattern == "") { + if err = regexEnricher.TryAddList(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNameList...); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNameList`") + } + } else { + if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + } + } taskData.RegexEnricher = regexEnricher @@ -218,6 +229,12 @@ func (p Github) ApiResources() map[string]map[string]plugin.ApiResourceHandler { "GET": api.GetScopeConfig, "DELETE": api.DeleteScopeConfig, }, + "connections/:connectionId/deployments": { + "GET": api.GetConnectionDeployments, + }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/remote-scopes": { "GET": api.RemoteScopes, }, diff --git a/backend/plugins/github/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go b/backend/plugins/github/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go new file mode 100644 index 00000000000..20226b10e97 --- /dev/null +++ b/backend/plugins/github/models/migrationscripts/20240906_add_env_name_list_to_scope_config.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 = (*addEnvNameListToScopeConfig)(nil) + +type scopeConfig20240906 struct { + EnvNameList []string `gorm:"type:json;serializer:json" json:"env_name_list" mapstructure:"env_name_list"` +} + +func (scopeConfig20240906) TableName() string { + return "_tool_github_scope_configs" +} + +type addEnvNameListToScopeConfig struct{} + +func (*addEnvNameListToScopeConfig) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + if err := db.AutoMigrate(&scopeConfig20240906{}); err != nil { + return err + } + return nil +} + +func (*addEnvNameListToScopeConfig) Version() uint64 { + return 20240906142100 +} + +func (*addEnvNameListToScopeConfig) Name() string { + return "add env_name_list to _tool_github_scope_configs" +} diff --git a/backend/plugins/github/models/migrationscripts/register.go b/backend/plugins/github/models/migrationscripts/register.go index b8a0722eb02..b69d56b856e 100644 --- a/backend/plugins/github/models/migrationscripts/register.go +++ b/backend/plugins/github/models/migrationscripts/register.go @@ -55,5 +55,6 @@ func All() []plugin.MigrationScript { new(addIsDraftToPr), new(changeIssueComponentType), new(addIndexToGithubJobs), + new(addEnvNameListToScopeConfig), } } diff --git a/backend/plugins/github/models/scope_config.go b/backend/plugins/github/models/scope_config.go index 60b298d363c..2bd12cbc36b 100644 --- a/backend/plugins/github/models/scope_config.go +++ b/backend/plugins/github/models/scope_config.go @@ -36,9 +36,10 @@ type GithubScopeConfig struct { IssueTypeBug string `mapstructure:"issueTypeBug,omitempty" json:"issueTypeBug" gorm:"type:varchar(255)"` IssueTypeIncident string `mapstructure:"issueTypeIncident,omitempty" json:"issueTypeIncident" gorm:"type:varchar(255)"` IssueTypeRequirement string `mapstructure:"issueTypeRequirement,omitempty" json:"issueTypeRequirement" gorm:"type:varchar(255)"` - DeploymentPattern string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` - ProductionPattern string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` + DeploymentPattern *string `mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern" gorm:"type:varchar(255)"` + ProductionPattern *string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` EnvNamePattern string `mapstructure:"envNamePattern,omitempty" json:"envNamePattern" gorm:"type:varchar(255)"` + EnvNameList []string `gorm:"type:json;serializer:json" json:"envNameList" mapstructure:"envNameList"` Refdiff datatypes.JSONMap `mapstructure:"refdiff,omitempty" json:"refdiff" swaggertype:"object" format:"json"` } diff --git a/backend/plugins/github/tasks/cicd_job_extractor.go b/backend/plugins/github/tasks/cicd_job_extractor.go index 5701476bcce..bb57852a81c 100644 --- a/backend/plugins/github/tasks/cicd_job_extractor.go +++ b/backend/plugins/github/tasks/cicd_job_extractor.go @@ -84,9 +84,12 @@ func ExtractJobs(taskCtx plugin.SubTaskContext) errors.Error { RunnerID: githubJob.RunID, RunnerName: githubJob.RunnerName, RunnerGroupID: githubJob.RunnerGroupID, - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, githubJob.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, githubJob.Name), } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + githubJobResult.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, githubJob.Name) + githubJobResult.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, githubJob.Name) + } + results = append(results, githubJobResult) return results, nil }, diff --git a/backend/plugins/github/tasks/cicd_run_extractor.go b/backend/plugins/github/tasks/cicd_run_extractor.go index 1e6a3f41a9e..95d7aca9add 100644 --- a/backend/plugins/github/tasks/cicd_run_extractor.go +++ b/backend/plugins/github/tasks/cicd_run_extractor.go @@ -62,8 +62,10 @@ func ExtractRuns(taskCtx plugin.SubTaskContext) errors.Error { } githubRun.RepoId = repoId githubRun.ConnectionId = data.Options.ConnectionId - githubRun.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, githubRun.Name) - githubRun.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, githubRun.Name, githubRun.HeadBranch) + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + githubRun.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, githubRun.Name) + githubRun.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, githubRun.Name, githubRun.HeadBranch) + } return []interface{}{githubRun}, nil }, }) diff --git a/backend/plugins/github_graphql/impl/impl.go b/backend/plugins/github_graphql/impl/impl.go index d4953a18f22..3de0cf34546 100644 --- a/backend/plugins/github_graphql/impl/impl.go +++ b/backend/plugins/github_graphql/impl/impl.go @@ -20,13 +20,14 @@ package impl import ( "context" "fmt" - "github.com/apache/incubator-devlake/core/models/domainlayer/devops" "net/http" "net/url" "reflect" "strings" "time" + "github.com/apache/incubator-devlake/core/models/domainlayer/devops" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/log" @@ -252,14 +253,24 @@ func (p GithubGraphql) PrepareTaskData(taskCtx plugin.TaskContext, options map[s } regexEnricher := helper.NewRegexEnricher() - if err = regexEnricher.TryAdd(devops.DEPLOYMENT, op.ScopeConfig.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.ScopeConfig.DeploymentPattern != nil { + if err = regexEnricher.TryAdd(devops.DEPLOYMENT, *op.ScopeConfig.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err = regexEnricher.TryAdd(devops.PRODUCTION, op.ScopeConfig.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ScopeConfig.ProductionPattern != nil { + if err = regexEnricher.TryAdd(devops.PRODUCTION, *op.ScopeConfig.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } - if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + if len(op.ScopeConfig.EnvNameList) > 0 || (len(op.ScopeConfig.EnvNameList) == 0 && op.ScopeConfig.EnvNamePattern == "") { + if err = regexEnricher.TryAddList(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNameList...); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNameList`") + } + } else { + if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + } } taskData.RegexEnricher = regexEnricher diff --git a/backend/plugins/github_graphql/tasks/deployment_convertor.go b/backend/plugins/github_graphql/tasks/deployment_convertor.go index fdc439553b9..6d292de5640 100644 --- a/backend/plugins/github_graphql/tasks/deployment_convertor.go +++ b/backend/plugins/github_graphql/tasks/deployment_convertor.go @@ -104,11 +104,10 @@ func ConvertDeployment(taskCtx plugin.SubTaskContext) errors.Error { deploymentCommit.DurationSec = &durationSec if data.RegexEnricher != nil { - if data.RegexEnricher.ReturnNameIfMatched(devops.ENV_NAME_PATTERN, githubDeployment.Environment) != "" { + if data.RegexEnricher.ReturnNameIfMatchedList(devops.ENV_NAME_PATTERN, githubDeployment.Environment) != "" { deploymentCommit.Environment = devops.PRODUCTION } } - deploymentCommit.CicdDeploymentId = deploymentCommit.Id return []interface{}{ deploymentCommit, diff --git a/backend/plugins/github_graphql/tasks/job_extractor.go b/backend/plugins/github_graphql/tasks/job_extractor.go index 1bd035a7eee..b60cb6b0ec5 100644 --- a/backend/plugins/github_graphql/tasks/job_extractor.go +++ b/backend/plugins/github_graphql/tasks/job_extractor.go @@ -75,8 +75,6 @@ func ExtractJobs(taskCtx plugin.SubTaskContext) errors.Error { CompletedAt: checkRun.CompletedAt, Name: checkRun.Name, Steps: paramsBytes, - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, checkRun.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, checkRun.Name), // these columns can not fill by graphql //HeadSha: ``, // use _tool_github_runs //RunURL: ``, @@ -86,6 +84,10 @@ func ExtractJobs(taskCtx plugin.SubTaskContext) errors.Error { //RunnerName: ``, // not in use //RunnerGroupID: ``, // not in use } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + githubJob.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, checkRun.Name) + githubJob.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, checkRun.Name) + } results = append(results, githubJob) } return results, nil diff --git a/backend/plugins/gitlab/api/connection_api.go b/backend/plugins/gitlab/api/connection_api.go index 598d5b975e6..ca557a2b865 100644 --- a/backend/plugins/gitlab/api/connection_api.go +++ b/backend/plugins/gitlab/api/connection_api.go @@ -23,6 +23,7 @@ import ( "net/http" "net/url" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" @@ -174,3 +175,126 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return dsHelper.ConnApi.GetDetail(input) } + +// GetConnectionDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/gitlab +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {array} string "List of Environment Names" +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/gitlab/connections/{connectionId}/deployments [GET] +func GetConnectionDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + var environments []string + err := db.All(&environments, + dal.From(&models.GitlabDeployment{}), + dal.Where("connection_id = ?", connectionId), + dal.Select("DISTINCT environment")) + if err != nil { + return nil, err + } + + return &plugin.ApiResourceOutput{ + Body: environments, + }, nil +} + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/gitlab +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/gitlab/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT name, gitlab_id, web_url, started_at + FROM ( + SELECT r.name, p.gitlab_id, p.web_url, p.started_at + FROM _tool_gitlab_pipelines p + LEFT JOIN _tool_gitlab_projects r on r.gitlab_id = p.project_id + WHERE p.connection_id = ? + AND (ref REGEXP ?) + AND (? = '' OR ref REGEXP ?) + UNION + SELECT r.name, p.gitlab_id, p.web_url, p.started_at + FROM _tool_gitlab_pipelines p + LEFT JOIN _tool_gitlab_projects r on r.gitlab_id = p.project_id + LEFT JOIN _tool_gitlab_jobs j on j.pipeline_id = p.gitlab_id + WHERE j.connection_id = ? + AND (j.name REGEXP ?) + AND (? = '' OR j.name REGEXP ?) + ) r + ORDER BY r.started_at DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + Name string + GitlabId int + WebUrl string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("%s-#%d", sf.Name, sf.GitlabId), + URL: sf.WebUrl, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} diff --git a/backend/plugins/gitlab/e2e/job_test.go b/backend/plugins/gitlab/e2e/job_test.go index 1705f59a8c6..810a5ac665a 100644 --- a/backend/plugins/gitlab/e2e/job_test.go +++ b/backend/plugins/gitlab/e2e/job_test.go @@ -30,8 +30,9 @@ import ( ) func TestGitlabJobDataFlow(t *testing.T) { - var gitlab impl.Gitlab + dPattern := "" + pPattern := "" dataflowTester := e2ehelper.NewDataFlowTester(t, "gitlab", gitlab) regexEnricher := api.NewRegexEnricher() _ = regexEnricher.TryAdd(devops.DEPLOYMENT, "(?i)compile") @@ -39,6 +40,10 @@ func TestGitlabJobDataFlow(t *testing.T) { Options: &tasks.GitlabOptions{ ConnectionId: 1, ProjectId: 44, + ScopeConfig: &models.GitlabScopeConfig{ + DeploymentPattern: &dPattern, + ProductionPattern: &pPattern, + }, }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/gitlab/impl/impl.go b/backend/plugins/gitlab/impl/impl.go index 2d4dbb4fc49..d292db691ed 100644 --- a/backend/plugins/gitlab/impl/impl.go +++ b/backend/plugins/gitlab/impl/impl.go @@ -206,14 +206,25 @@ func (p Gitlab) PrepareTaskData(taskCtx plugin.TaskContext, options map[string]i } regexEnricher := helper.NewRegexEnricher() - if err := regexEnricher.TryAdd(devops.DEPLOYMENT, op.ScopeConfig.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.ScopeConfig.DeploymentPattern != nil { + if err := regexEnricher.TryAdd(devops.DEPLOYMENT, *op.ScopeConfig.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err := regexEnricher.TryAdd(devops.PRODUCTION, op.ScopeConfig.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ScopeConfig.ProductionPattern != nil { + if err := regexEnricher.TryAdd(devops.PRODUCTION, *op.ScopeConfig.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } - if err := regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + if len(op.ScopeConfig.EnvNameList) > 0 || (len(op.ScopeConfig.EnvNameList) == 0 && op.ScopeConfig.EnvNamePattern == "") { + if err = regexEnricher.TryAddList(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNameList...); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNameList`") + } + } else { + if err = regexEnricher.TryAdd(devops.ENV_NAME_PATTERN, op.ScopeConfig.EnvNamePattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `envNamePattern`") + } + } taskData := tasks.GitlabTaskData{ @@ -268,6 +279,12 @@ func (p Gitlab) ApiResources() map[string]map[string]plugin.ApiResourceHandler { "GET": api.GetScopeList, "PUT": api.PutScopes, }, + "connections/:connectionId/deployments": { + "GET": api.GetConnectionDeployments, + }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scope-configs": { "POST": api.CreateScopeConfig, "GET": api.GetScopeConfigList, diff --git a/backend/plugins/gitlab/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go b/backend/plugins/gitlab/models/migrationscripts/20240906_add_env_name_list_to_scope_config.go new file mode 100644 index 00000000000..88fa893644f --- /dev/null +++ b/backend/plugins/gitlab/models/migrationscripts/20240906_add_env_name_list_to_scope_config.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 = (*addEnvNameListToScopeConfig)(nil) + +type scopeConfig20240906 struct { + EnvNameList []string `gorm:"type:json;serializer:json" json:"env_name_list" mapstructure:"env_name_list"` +} + +func (scopeConfig20240906) TableName() string { + return "_tool_gitlab_scope_configs" +} + +type addEnvNameListToScopeConfig struct{} + +func (*addEnvNameListToScopeConfig) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + if err := db.AutoMigrate(&scopeConfig20240906{}); err != nil { + return err + } + return nil +} + +func (*addEnvNameListToScopeConfig) Version() uint64 { + return 20240906142101 +} + +func (*addEnvNameListToScopeConfig) Name() string { + return "add env_name_list to _tool_gitlab_scope_configs" +} diff --git a/backend/plugins/gitlab/models/migrationscripts/register.go b/backend/plugins/gitlab/models/migrationscripts/register.go index 1d89b250512..2fb32db0b6c 100644 --- a/backend/plugins/gitlab/models/migrationscripts/register.go +++ b/backend/plugins/gitlab/models/migrationscripts/register.go @@ -52,5 +52,6 @@ func All() []plugin.MigrationScript { new(addGitlabAssigneeAndReviewerPrimaryKey), new(changeIssueComponentType), new(addIsChildToPipelines240906), + new(addEnvNameListToScopeConfig), } } diff --git a/backend/plugins/gitlab/models/scope_config.go b/backend/plugins/gitlab/models/scope_config.go index 78cfd7f2d1d..35cb4ae9db1 100644 --- a/backend/plugins/gitlab/models/scope_config.go +++ b/backend/plugins/gitlab/models/scope_config.go @@ -33,9 +33,10 @@ type GitlabScopeConfig struct { IssueTypeBug string `mapstructure:"issueTypeBug" json:"issueTypeBug"` IssueTypeIncident string `mapstructure:"issueTypeIncident" json:"issueTypeIncident"` IssueTypeRequirement string `mapstructure:"issueTypeRequirement" json:"issueTypeRequirement"` - DeploymentPattern string `mapstructure:"deploymentPattern" json:"deploymentPattern"` - ProductionPattern string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` + DeploymentPattern *string `mapstructure:"deploymentPattern" json:"deploymentPattern"` + ProductionPattern *string `mapstructure:"productionPattern,omitempty" json:"productionPattern" gorm:"type:varchar(255)"` EnvNamePattern string `mapstructure:"envNamePattern,omitempty" json:"envNamePattern" gorm:"type:varchar(255)"` + EnvNameList []string `gorm:"type:json;serializer:json" json:"envNameList" mapstructure:"envNameList"` Refdiff datatypes.JSONMap `mapstructure:"refdiff,omitempty" json:"refdiff" swaggertype:"object" format:"json"` } diff --git a/backend/plugins/gitlab/tasks/deployment_convertor.go b/backend/plugins/gitlab/tasks/deployment_convertor.go index d7ff0d7741f..06ed5923de0 100644 --- a/backend/plugins/gitlab/tasks/deployment_convertor.go +++ b/backend/plugins/gitlab/tasks/deployment_convertor.go @@ -129,7 +129,7 @@ func ConvertDeployment(taskCtx plugin.SubTaskContext) errors.Error { Url: repo.WebUrl + "/environments", } if data.RegexEnricher != nil { - if data.RegexEnricher.ReturnNameIfMatched(devops.ENV_NAME_PATTERN, gitlabDeployment.Environment) != "" { + if data.RegexEnricher.ReturnNameIfMatchedList(devops.ENV_NAME_PATTERN, gitlabDeployment.Environment) != "" { domainDeployCommit.Environment = devops.PRODUCTION } } diff --git a/backend/plugins/gitlab/tasks/job_convertor.go b/backend/plugins/gitlab/tasks/job_convertor.go index 58bd8f712e4..e6e14a41f3e 100644 --- a/backend/plugins/gitlab/tasks/job_convertor.go +++ b/backend/plugins/gitlab/tasks/job_convertor.go @@ -103,9 +103,10 @@ func ConvertJobs(taskCtx plugin.SubTaskContext) (err errors.Error) { }, CicdScopeId: projectIdGen.Generate(data.Options.ConnectionId, gitlabJob.ProjectId), } - domainJob.Type = regexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, gitlabJob.Name) - domainJob.Environment = regexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, gitlabJob.Name) - + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + domainJob.Type = regexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, gitlabJob.Name) + domainJob.Environment = regexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, gitlabJob.Name) + } return []interface{}{ domainJob, }, nil diff --git a/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go b/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go index 1b78362a171..34692dc54df 100644 --- a/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go +++ b/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go @@ -67,10 +67,12 @@ func ExtractApiPipelineDetails(taskCtx plugin.SubTaskContext) errors.Error { Duration: gitlabApiPipeline.Duration, QueuedDuration: gitlabApiPipeline.QueuedDuration, ConnectionId: data.Options.ConnectionId, - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, gitlabApiPipeline.Ref), - Environment: data.RegexEnricher.ReturnNameIfMatched(devops.PRODUCTION, gitlabApiPipeline.Ref), Source: gitlabApiPipeline.Source, } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + gitlabPipeline.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, gitlabApiPipeline.Ref) + gitlabPipeline.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, gitlabApiPipeline.Ref) + } return []interface{}{gitlabPipeline}, nil }, diff --git a/backend/plugins/jenkins/api/connection_api.go b/backend/plugins/jenkins/api/connection_api.go index b213bb06859..6f5e3ab4432 100644 --- a/backend/plugins/jenkins/api/connection_api.go +++ b/backend/plugins/jenkins/api/connection_api.go @@ -19,6 +19,7 @@ package api import ( "context" + "fmt" "net/http" "strings" @@ -176,3 +177,98 @@ func ListConnections(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, func GetConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return dsHelper.ConnApi.GetDetail(input) } + +// GetConnectionTransformToDeployments return one connection deployments +// @Summary return one connection deployments +// @Description return one connection deployments +// @Tags plugins/jenkins +// @Param id path int true "id" +// @Param connectionId path int true "connectionId" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /plugins/jenkins/connections/{connectionId}/transform-to-deployments [POST] +func GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT number, job_name, full_name, url, start_time + FROM( + SELECT number, job_name, full_name, url, start_time + FROM _tool_jenkins_builds + WHERE connection_id = ? + AND (full_name REGEXP ?) + AND (? = '' OR full_name REGEXP ?) + UNION + SELECT number, job_name, full_name, url, start_time + FROM _tool_jenkins_stages s + LEFT JOIN _tool_jenkins_builds b ON b.full_name = s.build_name + WHERE s.connection_id = ? + AND s.name REGEXP ? + AND (? = '' OR s.name REGEXP ?) + ) AS t + ORDER BY start_time DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + Number int + JobName string + FullName string + URL string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("#%d - %s", sf.Number, sf.JobName), + URL: sf.URL, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} diff --git a/backend/plugins/jenkins/e2e/builds_test.go b/backend/plugins/jenkins/e2e/builds_test.go index 2752c10f126..9bb03986309 100644 --- a/backend/plugins/jenkins/e2e/builds_test.go +++ b/backend/plugins/jenkins/e2e/builds_test.go @@ -29,7 +29,6 @@ import ( ) func TestJenkinsBuildsDataFlow(t *testing.T) { - var jenkins impl.Jenkins dataflowTester := e2ehelper.NewDataFlowTester(t, "jenkins", jenkins) @@ -41,6 +40,7 @@ func TestJenkinsBuildsDataFlow(t *testing.T) { JobName: `devlake`, JobFullName: `Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake`, JobPath: `job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`, + ScopeConfig: new(models.JenkinsScopeConfig), }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits_multibranch.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits_multibranch.csv index 934da5a2921..2e54af1d4c4 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits_multibranch.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipeline_commits_multibranch.csv @@ -1,14 +1,14 @@ pipeline_id,commit_sha,repo_id,repo_url,branch,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#1","aba54481a73573c0587f26fbd4c9788eb2bf2398",,"git@github.com:gustavobini/devlake-jenkins.git","PR-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",6, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#2","49359d217ea617c7e4771235979b56015172ba6c",,"git@github.com:gustavobini/devlake-jenkins.git","PR-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",5, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#1","87f0f9ee7c305c561c96f66ed8c71c85df4b940f",,"git@github.com:gustavobini/devlake-jenkins.git","feature-1","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",9, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#2","eae3667426e1da0d8cab523e372e6771a39b16a7",,"git@github.com:gustavobini/devlake-jenkins.git","feature-1","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",8, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#3","3ff14f4a781018e6e800ded3a5ac95fa2f9bb26f",,"git@github.com:gustavobini/devlake-jenkins.git","feature-1","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",7, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#1","2578423ba5c348fb9948279f3ea64ed650fecd8a",,"git@github.com:gustavobini/devlake-jenkins.git","feature-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",15, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#2","2578423ba5c348fb9948279f3ea64ed650fecd8a",,"git@github.com:gustavobini/devlake-jenkins.git","feature-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",14, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#3","881b398774e020772bca7fdd7fdc60e7250f53ef",,"git@github.com:gustavobini/devlake-jenkins.git","feature-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",13, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#6","aba54481a73573c0587f26fbd4c9788eb2bf2398",,"git@github.com:gustavobini/devlake-jenkins.git","feature-2","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",10, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#1","87f0f9ee7c305c561c96f66ed8c71c85df4b940f",,"git@github.com:gustavobini/devlake-jenkins.git","main","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",4, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#2","f521ff9c806e74b9100c8fc87d07ac504f828f93",,"git@github.com:gustavobini/devlake-jenkins.git","main","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",3, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#3","78b8e3a2029f991982039e4ed6d7b1f9c6670497",,"git@github.com:gustavobini/devlake-jenkins.git","main","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",2, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#4","c83ae02076382670e286ac2474b7a7327fc28cde",,"git@github.com:gustavobini/devlake-jenkins.git","main","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",1, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#1,aba54481a73573c0587f26fbd4c9788eb2bf2398,,git@github.com:gustavobini/devlake-jenkins.git,PR-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,6, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#2,49359d217ea617c7e4771235979b56015172ba6c,,git@github.com:gustavobini/devlake-jenkins.git,PR-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,5, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#1,87f0f9ee7c305c561c96f66ed8c71c85df4b940f,,git@github.com:gustavobini/devlake-jenkins.git,feature-1,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,9, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#2,eae3667426e1da0d8cab523e372e6771a39b16a7,,git@github.com:gustavobini/devlake-jenkins.git,feature-1,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,8, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#3,3ff14f4a781018e6e800ded3a5ac95fa2f9bb26f,,git@github.com:gustavobini/devlake-jenkins.git,feature-1,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,7, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#1,2578423ba5c348fb9948279f3ea64ed650fecd8a,,git@github.com:gustavobini/devlake-jenkins.git,feature-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,15, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#2,2578423ba5c348fb9948279f3ea64ed650fecd8a,,git@github.com:gustavobini/devlake-jenkins.git,feature-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,14, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#3,881b398774e020772bca7fdd7fdc60e7250f53ef,,git@github.com:gustavobini/devlake-jenkins.git,feature-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,13, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#6,aba54481a73573c0587f26fbd4c9788eb2bf2398,,git@github.com:gustavobini/devlake-jenkins.git,feature-2,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,10, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#1,87f0f9ee7c305c561c96f66ed8c71c85df4b940f,,git@github.com:gustavobini/devlake-jenkins.git,main,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,4, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#2,f521ff9c806e74b9100c8fc87d07ac504f828f93,,git@github.com:gustavobini/devlake-jenkins.git,main,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,3, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#3,78b8e3a2029f991982039e4ed6d7b1f9c6670497,,git@github.com:gustavobini/devlake-jenkins.git,main,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,2, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#4,c83ae02076382670e286ac2474b7a7327fc28cde,,git@github.com:gustavobini/devlake-jenkins.git,main,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,1, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv index b16d2e7cd3b..af050edf4a4 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines.csv @@ -1,14 +1,14 @@ id,name,result,status,original_result,original_status,type,duration_sec,environment,created_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,,IN_PROGRESS,SUCCESS,true,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,,IN_PROGRESS,FAILURE,true,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,FAILURE,DONE,ABORTED,false,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,,DONE,NOT_BUILD,false,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,,DONE,UNSTABLE,false,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,14.82,PRODUCTION,2022-04-15T10:10:16.000+00:00,2022-04-15T10:10:30.820+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,0.057,PRODUCTION,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.057+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,2.121,PRODUCTION,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.121+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,0.061,PRODUCTION,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.061+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,SUCCESS,true,DEPLOYMENT,0.004,PRODUCTION,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,1.587,PRODUCTION,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.587+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,0.003,PRODUCTION,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.003+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,0.006,PRODUCTION,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.006+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,,IN_PROGRESS,SUCCESS,true,,0.004,,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,,IN_PROGRESS,FAILURE,true,,0.004,,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,FAILURE,DONE,ABORTED,false,,0.004,,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,,DONE,NOT_BUILD,false,,0.004,,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,,DONE,UNSTABLE,false,,0.004,,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,SUCCESS,DONE,SUCCESS,false,,14.82,,2022-04-15T10:10:16.000+00:00,2022-04-15T10:10:30.820+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,95, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,SUCCESS,false,,0.057,,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.057+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,SUCCESS,false,,2.121,,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.121+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,SUCCESS,false,,0.061,,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.061+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,SUCCESS,true,,0.004,,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,SUCCESS,false,,1.587,,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.587+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,SUCCESS,false,,0.003,,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.003+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,SUCCESS,false,,0.006,,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.006+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines_multibranch.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines_multibranch.csv index 97f54305484..2ce617bc92a 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines_multibranch.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_pipelines_multibranch.csv @@ -1,16 +1,16 @@ -id,name,result,original_result,status,original_status,type,duration_sec,environment,created_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#1","github_org/devlake-jenkins/PR-2#1","FAILURE","ABORTED","DONE","false","",7.39,"PRODUCTION","2024-03-24T10:51:51.000+00:00","2024-03-24T10:51:58.390+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",6, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#2","github_org/devlake-jenkins/PR-2#2","SUCCESS","SUCCESS","DONE","false","",30.086,"PRODUCTION","2024-03-24T10:52:21.000+00:00","2024-03-24T10:52:51.086+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",5, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#1","github_org/devlake-jenkins/feature-1#1","SUCCESS","SUCCESS","DONE","false","",39.545,"PRODUCTION","2024-03-24T10:23:35.000+00:00","2024-03-24T10:24:14.545+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",9, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#2","github_org/devlake-jenkins/feature-1#2","SUCCESS","SUCCESS","DONE","false","",35.351,"PRODUCTION","2024-03-24T10:32:06.000+00:00","2024-03-24T10:32:41.351+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",8, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#3","github_org/devlake-jenkins/feature-1#3","SUCCESS","SUCCESS","DONE","false","",35.354,"PRODUCTION","2024-03-24T10:44:31.000+00:00","2024-03-24T10:45:06.354+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",7, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#1","github_org/devlake-jenkins/feature-2#1","SUCCESS","SUCCESS","DONE","false","",35.206,"PRODUCTION","2024-03-24T10:45:41.000+00:00","2024-03-24T10:46:16.206+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",15, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#2","github_org/devlake-jenkins/feature-2#2","SUCCESS","SUCCESS","DONE","false","",35.162,"PRODUCTION","2024-03-24T10:45:56.000+00:00","2024-03-24T10:46:31.162+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",14, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#3","github_org/devlake-jenkins/feature-2#3","SUCCESS","SUCCESS","DONE","false","",35.435,"PRODUCTION","2024-03-24T10:46:31.000+00:00","2024-03-24T10:47:06.435+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",13, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4","github_org/devlake-jenkins/feature-2#4","FAILURE","FAILURE","DONE","false","",0.976,"PRODUCTION","2024-03-24T10:47:41.000+00:00","2024-03-24T10:47:41.976+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",12, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5","github_org/devlake-jenkins/feature-2#5","FAILURE","FAILURE","DONE","false","",1.098,"PRODUCTION","2024-03-24T10:49:31.000+00:00","2024-03-24T10:49:32.098+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",11, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#6","github_org/devlake-jenkins/feature-2#6","FAILURE","ABORTED","DONE","false","",5.993,"PRODUCTION","2024-03-24T10:50:56.000+00:00","2024-03-24T10:51:01.993+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",10, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#1","github_org/devlake-jenkins/main#1","SUCCESS","SUCCESS","DONE","false","",36.568,"PRODUCTION","2024-03-24T10:23:35.000+00:00","2024-03-24T10:24:11.568+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",4, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#2","github_org/devlake-jenkins/main#2","SUCCESS","SUCCESS","DONE","false","",35.26,"PRODUCTION","2024-03-24T10:48:21.000+00:00","2024-03-24T10:48:56.260+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",3, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#3","github_org/devlake-jenkins/main#3","SUCCESS","SUCCESS","DONE","false","",35.435,"PRODUCTION","2024-03-24T10:51:41.000+00:00","2024-03-24T10:52:16.435+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",2, -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#4","github_org/devlake-jenkins/main#4","SUCCESS","SUCCESS","DONE","false","",30.415,"PRODUCTION","2024-03-24T10:52:31.000+00:00","2024-03-24T10:53:01.415+00:00","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",1, +id,name,result,status,original_result,original_status,type,duration_sec,environment,created_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#1,github_org/devlake-jenkins/PR-2#1,FAILURE,DONE,ABORTED,false,,7.39,,2024-03-24T10:51:51.000+00:00,2024-03-24T10:51:58.390+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,6, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/PR-2#2,github_org/devlake-jenkins/PR-2#2,SUCCESS,DONE,SUCCESS,false,,30.086,,2024-03-24T10:52:21.000+00:00,2024-03-24T10:52:51.086+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,5, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#1,github_org/devlake-jenkins/feature-1#1,SUCCESS,DONE,SUCCESS,false,,39.545,,2024-03-24T10:23:35.000+00:00,2024-03-24T10:24:14.545+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,9, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#2,github_org/devlake-jenkins/feature-1#2,SUCCESS,DONE,SUCCESS,false,,35.351,,2024-03-24T10:32:06.000+00:00,2024-03-24T10:32:41.351+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,8, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-1#3,github_org/devlake-jenkins/feature-1#3,SUCCESS,DONE,SUCCESS,false,,35.354,,2024-03-24T10:44:31.000+00:00,2024-03-24T10:45:06.354+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,7, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#1,github_org/devlake-jenkins/feature-2#1,SUCCESS,DONE,SUCCESS,false,,35.206,,2024-03-24T10:45:41.000+00:00,2024-03-24T10:46:16.206+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,15, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#2,github_org/devlake-jenkins/feature-2#2,SUCCESS,DONE,SUCCESS,false,,35.162,,2024-03-24T10:45:56.000+00:00,2024-03-24T10:46:31.162+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,14, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#3,github_org/devlake-jenkins/feature-2#3,SUCCESS,DONE,SUCCESS,false,,35.435,,2024-03-24T10:46:31.000+00:00,2024-03-24T10:47:06.435+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,13, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4,github_org/devlake-jenkins/feature-2#4,FAILURE,DONE,FAILURE,false,,0.976,,2024-03-24T10:47:41.000+00:00,2024-03-24T10:47:41.976+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,12, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5,github_org/devlake-jenkins/feature-2#5,FAILURE,DONE,FAILURE,false,,1.098,,2024-03-24T10:49:31.000+00:00,2024-03-24T10:49:32.098+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,11, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#6,github_org/devlake-jenkins/feature-2#6,FAILURE,DONE,ABORTED,false,,5.993,,2024-03-24T10:50:56.000+00:00,2024-03-24T10:51:01.993+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,10, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#1,github_org/devlake-jenkins/main#1,SUCCESS,DONE,SUCCESS,false,,36.568,,2024-03-24T10:23:35.000+00:00,2024-03-24T10:24:11.568+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,4, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#2,github_org/devlake-jenkins/main#2,SUCCESS,DONE,SUCCESS,false,,35.26,,2024-03-24T10:48:21.000+00:00,2024-03-24T10:48:56.260+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,3, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#3,github_org/devlake-jenkins/main#3,SUCCESS,DONE,SUCCESS,false,,35.435,,2024-03-24T10:51:41.000+00:00,2024-03-24T10:52:16.435+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,2, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/main#4,github_org/devlake-jenkins/main#4,SUCCESS,DONE,SUCCESS,false,,30.415,,2024-03-24T10:52:31.000+00:00,2024-03-24T10:53:01.415+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,1, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv index ee602331fd2..631f6adc546 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks.csv @@ -1,13 +1,13 @@ id,name,pipeline_id,result,status,original_result,original_status,type,environment,duration_sec,started_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,,IN_PROGRESS,SUCCESS,true,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,,IN_PROGRESS,FAILURE,true,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,FAILURE,DONE,ABORTED,false,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,,DONE,NOT_BUILD,false,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,,DONE,UNSTABLE,false,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,0.057,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.057+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,2.121,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.121+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,0.061,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.061+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,SUCCESS,true,DEPLOYMENT,PRODUCTION,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,1.587,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.587+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,0.003,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.003+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,SUCCESS,false,DEPLOYMENT,PRODUCTION,0.006,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.006+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,,IN_PROGRESS,SUCCESS,true,,,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,,IN_PROGRESS,FAILURE,true,,,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,FAILURE,DONE,ABORTED,false,,,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,,DONE,NOT_BUILD,false,,,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,,DONE,UNSTABLE,false,,,0.004,2022-04-15T10:06:17.000+00:00,2022-04-15T10:06:17.004+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,SUCCESS,DONE,SUCCESS,false,,,0.057,2022-04-15T10:05:53.000+00:00,2022-04-15T10:05:53.057+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,SUCCESS,DONE,SUCCESS,false,,,2.121,2022-04-15T11:35:48.000+00:00,2022-04-15T11:35:50.121+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,SUCCESS,DONE,SUCCESS,false,,,0.061,2022-09-08T14:26:51.000+00:00,2022-09-08T14:26:51.061+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,IN_PROGRESS,SUCCESS,true,,,0.004,2022-04-15T10:06:17.000+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,SUCCESS,DONE,SUCCESS,false,,,1.587,2022-04-15T12:00:49.000+00:00,2022-04-15T12:00:50.587+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,SUCCESS,DONE,SUCCESS,false,,,0.003,2022-04-15T10:06:26.000+00:00,2022-04-15T10:06:26.003+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,SUCCESS,DONE,SUCCESS,false,,,0.006,2022-04-15T11:35:56.000+00:00,2022-04-15T11:35:56.006+00:00,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages.csv index 29662112caf..9face118836 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages.csv @@ -1,9 +1,9 @@ id,name,pipeline_id,result,status,original_result,original_status,type,duration_sec,started_date,finished_date,environment,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10:8,scp-f/b,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10,SUCCESS,OTHER,SUCCESS,FAILED,,0,2019-10-29T04:01:34.000+00:00,2019-10-29T04:01:35.067+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13577, jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11:9,gitlabInit,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11,SUCCESS,OTHER,SUCCESS,,,1312,2021-03-09T13:35:10.000+00:00,2021-03-09T13:57:02.888+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13578, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12:1,gitlabAutoSync,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12,SUCCESS,DONE,SUCCESS,SUCCESS,DEPLOYMENT,14,2020-02-07T11:54:28.000+00:00,2020-02-07T11:54:43.104+00:00,PRODUCTION,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13579, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12:1,gitlabAutoSync,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12,SUCCESS,DONE,SUCCESS,SUCCESS,,14,2020-02-07T11:54:28.000+00:00,2020-02-07T11:54:43.104+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13579, jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13:2,gitlabInit,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13,SUCCESS,OTHER,SUCCESS,ABORTED,,5,2020-03-18T02:19:17.000+00:00,2020-03-18T02:19:22.999+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13580, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14:3,gitlabAutoSync,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14,SUCCESS,DONE,SUCCESS,SUCCESS,DEPLOYMENT,83,2020-03-12T02:45:25.000+00:00,2020-03-12T02:46:49.106+00:00,PRODUCTION,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13581, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14:3,gitlabAutoSync,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14,SUCCESS,DONE,SUCCESS,SUCCESS,,83,2020-03-12T02:45:25.000+00:00,2020-03-12T02:46:49.106+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13581, jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#1:6,Hello,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#1,SUCCESS,DONE,SUCCESS,SUCCESS,,0,2022-09-08T15:40:34.000+00:00,2022-09-08T15:40:34.503+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,1, jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#2:7,Hello,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#2,SUCCESS,DONE,SUCCESS,SUCCESS,,0,2022-09-08T15:40:49.000+00:00,2022-09-08T15:40:49.751+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,2, jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#3:8,Hello,jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#3,SUCCESS,DONE,SUCCESS,SUCCESS,,0,2022-09-08T15:40:49.000+00:00,2022-09-08T15:40:49.751+00:00,,jenkins:JenkinsJob:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,3, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages_no_prod_regex.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages_no_prod_regex.csv index 8c5c203fa0c..0730f0dd543 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages_no_prod_regex.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_after_stages_no_prod_regex.csv @@ -1,15 +1,15 @@ id,environment,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10:8,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13577, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11:9,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13578, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12:1,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13579, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13:2,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13580, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14:3,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13581, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#1:6,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,1, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#2:7,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,2, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#3:8,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,3, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#4:9,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,4, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#5:10,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,5, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#6:11,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,6, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#7:12,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13574, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#8:6,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13575, -jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#9:7,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13576, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10:8,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13577, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#11:9,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13578, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#12:1,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13579, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#13:2,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13580, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#14:3,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13581, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#1:6,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,1, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#2:7,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,2, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#3:8,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,3, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#4:9,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,4, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#5:10,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,5, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#6:11,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,6, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#7:12,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13574, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#8:6,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13575, +jenkins:JenkinsStage:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#9:7,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_stages,13576, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_multibranch.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_multibranch.csv index a27a8bdb09e..e1e46f47c77 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_multibranch.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_multibranch.csv @@ -1,3 +1,3 @@ -id,name,pipeline_id,result,original_result,status,original_status,type,started_date,finished_date,duration_sec,environment,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4","github_org/devlake-jenkins","jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4","FAILURE","FAILURE","DONE","false","","2024-03-24T10:47:41.000+00:00","2024-03-24T10:47:41.976+00:00",0.976,"PRODUCTION","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",12,"" -"jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5","github_org/devlake-jenkins","jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5","FAILURE","FAILURE","DONE","false","","2024-03-24T10:49:31.000+00:00","2024-03-24T10:49:32.098+00:00",1.098,"PRODUCTION","jenkins:JenkinsJob:1:github_org/devlake-jenkins","{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}","_raw_jenkins_api_builds",11,"" \ No newline at end of file +id,name,pipeline_id,result,status,original_result,original_status,type,environment,duration_sec,started_date,finished_date,cicd_scope_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4,github_org/devlake-jenkins,jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#4,FAILURE,DONE,FAILURE,false,,,0.976,2024-03-24T10:47:41.000+00:00,2024-03-24T10:47:41.976+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,12, +jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5,github_org/devlake-jenkins,jenkins:JenkinsBuild:1:github_org/devlake-jenkins/feature-2#5,FAILURE,DONE,FAILURE,false,,,1.098,2024-03-24T10:49:31.000+00:00,2024-03-24T10:49:32.098+00:00,jenkins:JenkinsJob:1:github_org/devlake-jenkins,"{""ConnectionId"":1,""FullName"":""github_org/devlake-jenkins""}",_raw_jenkins_api_builds,11, diff --git a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_no_prod_regex.csv b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_no_prod_regex.csv index 7002356233d..89c17bbd3f1 100644 --- a/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_no_prod_regex.csv +++ b/backend/plugins/jenkins/e2e/snapshot_tables/cicd_tasks_no_prod_regex.csv @@ -1,13 +1,13 @@ id,environment,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, -jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,PRODUCTION,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10001,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10001, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10002,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10002, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10003,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10003, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10004,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10004, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#10005,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,10005, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#17,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,124, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#21,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,94, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#23,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,96, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#27,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,123, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#31,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,93, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#37,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,122, +jenkins:JenkinsBuild:1:Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake#47,,"{""ConnectionId"":1,""FullName"":""Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake""}",_raw_jenkins_api_builds,121, diff --git a/backend/plugins/jenkins/e2e/stages_test.go b/backend/plugins/jenkins/e2e/stages_test.go index 527698a8a48..d484325c82a 100644 --- a/backend/plugins/jenkins/e2e/stages_test.go +++ b/backend/plugins/jenkins/e2e/stages_test.go @@ -40,6 +40,7 @@ func TestJenkinsStagesDataFlow(t *testing.T) { JobName: `devlake`, JobFullName: `Test-jenkins-dir/test-jenkins-sub-dir/test-sub-sub-dir/devlake`, JobPath: `job/Test-jenkins-dir/job/test-jenkins-sub-dir/job/test-sub-sub-dir/`, + ScopeConfig: new(models.JenkinsScopeConfig), }, RegexEnricher: regexEnricher, } diff --git a/backend/plugins/jenkins/impl/impl.go b/backend/plugins/jenkins/impl/impl.go index 7411f7543c2..2a686037fd4 100644 --- a/backend/plugins/jenkins/impl/impl.go +++ b/backend/plugins/jenkins/impl/impl.go @@ -118,9 +118,6 @@ func (p Jenkins) PrepareTaskData(taskCtx plugin.TaskContext, options map[string] nil, p.Name(), ) - if err != nil { - return nil, err - } err = connectionHelper.FirstById(connection, op.ConnectionId) if err != nil { return nil, err @@ -144,11 +141,15 @@ func (p Jenkins) PrepareTaskData(taskCtx plugin.TaskContext, options map[string] } regexEnricher := helper.NewRegexEnricher() - if err := regexEnricher.TryAdd(devops.DEPLOYMENT, op.ScopeConfig.DeploymentPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + if op.ScopeConfig.DeploymentPattern != nil { + if err := regexEnricher.TryAdd(devops.DEPLOYMENT, *op.ScopeConfig.DeploymentPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `deploymentPattern`") + } } - if err := regexEnricher.TryAdd(devops.PRODUCTION, op.ScopeConfig.ProductionPattern); err != nil { - return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + if op.ScopeConfig.ProductionPattern != nil { + if err := regexEnricher.TryAdd(devops.PRODUCTION, *op.ScopeConfig.ProductionPattern); err != nil { + return nil, errors.BadInput.Wrap(err, "invalid value for `productionPattern`") + } } taskData := &tasks.JenkinsTaskData{ Options: op, @@ -216,6 +217,9 @@ func (p Jenkins) ApiResources() map[string]map[string]plugin.ApiResourceHandler "POST": api.CreateScopeConfig, "GET": api.GetScopeConfigList, }, + "connections/:connectionId/transform-to-deployments": { + "POST": api.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scope-configs/:scopeConfigId": { "PATCH": api.UpdateScopeConfig, "GET": api.GetScopeConfig, @@ -288,7 +292,7 @@ func EnrichOptions(taskCtx plugin.TaskContext, op.JobPath = fmt.Sprintf("%s/", op.JobPath) } // We only set op.JenkinsScopeConfig when it's nil and we have op.ScopeConfigId != 0 - if op.ScopeConfig.DeploymentPattern == "" && op.ScopeConfig.ProductionPattern == "" && op.ScopeConfigId != 0 { + if (op.ScopeConfig.DeploymentPattern == nil && op.ScopeConfig.ProductionPattern == nil || *op.ScopeConfig.DeploymentPattern == "" && *op.ScopeConfig.ProductionPattern == "") && op.ScopeConfigId != 0 { var scopeConfig models.JenkinsScopeConfig err = taskCtx.GetDal().First(&scopeConfig, dal.Where("id = ?", op.ScopeConfigId)) if err != nil { @@ -297,7 +301,7 @@ func EnrichOptions(taskCtx plugin.TaskContext, op.ScopeConfig = &scopeConfig } - if op.ScopeConfig.DeploymentPattern == "" && op.ScopeConfig.ProductionPattern == "" && op.ScopeConfigId == 0 { + if (op.ScopeConfig.DeploymentPattern == nil && op.ScopeConfig.ProductionPattern == nil || *op.ScopeConfig.DeploymentPattern == "" && *op.ScopeConfig.ProductionPattern == "") && op.ScopeConfigId == 0 { op.ScopeConfig = new(models.JenkinsScopeConfig) } diff --git a/backend/plugins/jenkins/models/build.go b/backend/plugins/jenkins/models/build.go index 203d81d0023..804c5521cfc 100644 --- a/backend/plugins/jenkins/models/build.go +++ b/backend/plugins/jenkins/models/build.go @@ -18,22 +18,24 @@ limitations under the License. package models import ( - "github.com/apache/incubator-devlake/core/models/common" "time" + + "github.com/apache/incubator-devlake/core/models/common" ) // JenkinsBuild db entity for jenkins build type JenkinsBuild struct { common.NoPKModel // collected fields - ConnectionId uint64 `gorm:"primaryKey"` - JobName string `gorm:"index;type:varchar(255)"` - JobPath string `gorm:"index;type:varchar(255)"` - Duration float64 // build time - FullName string `gorm:"primaryKey;type:varchar(255)"` // "path/job name#7" - EstimatedDuration float64 // EstimatedDuration - Number int64 `gorm:"index"` - Result string // Result + ConnectionId uint64 `gorm:"primaryKey"` + JobName string `gorm:"index;type:varchar(255)"` + JobPath string `gorm:"index;type:varchar(255)"` + Duration float64 // build time + FullName string `gorm:"primaryKey;type:varchar(255)"` // "path/job name#7" + EstimatedDuration float64 // EstimatedDuration + Number int64 `gorm:"index"` + Result string // Result + Url string Timestamp int64 // start time StartTime time.Time // convered by timestamp Type string `gorm:"index;type:varchar(255)"` diff --git a/backend/plugins/jenkins/models/migrationscripts/20240911_add_url_for_builds.go b/backend/plugins/jenkins/models/migrationscripts/20240911_add_url_for_builds.go new file mode 100644 index 00000000000..d3959b55a21 --- /dev/null +++ b/backend/plugins/jenkins/models/migrationscripts/20240911_add_url_for_builds.go @@ -0,0 +1,46 @@ +/* +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" +) + +type addUrlForBuilds struct{} + +type jenkinsBuild20240911 struct { + Url string +} + +func (jenkinsBuild20240911) TableName() string { + return "_tool_jenkins_builds" +} + +func (script *addUrlForBuilds) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + return db.AutoMigrate(&jenkinsBuild20240911{}) +} + +func (*addUrlForBuilds) Version() uint64 { + return 20240911231237 +} + +func (*addUrlForBuilds) Name() string { + return "add url for builds" +} diff --git a/backend/plugins/jenkins/models/migrationscripts/register.go b/backend/plugins/jenkins/models/migrationscripts/register.go index 1dc1eb84b15..ff2c9ac7acd 100644 --- a/backend/plugins/jenkins/models/migrationscripts/register.go +++ b/backend/plugins/jenkins/models/migrationscripts/register.go @@ -36,5 +36,6 @@ func All() []plugin.MigrationScript { new(renameTr2ScopeConfig), new(addRawParamTableForScope), new(addNumberToJenkinsBuildCommit), + new(addUrlForBuilds), } } diff --git a/backend/plugins/jenkins/models/response.go b/backend/plugins/jenkins/models/response.go index 643bec69136..962a875af03 100644 --- a/backend/plugins/jenkins/models/response.go +++ b/backend/plugins/jenkins/models/response.go @@ -102,6 +102,7 @@ type ApiBuildResponse struct { Class string `json:"_class"` Number int64 `json:"number"` Result string `json:"result"` + Url string `json:"url"` Building bool `json:"building"` Actions []Action `json:"actions"` Duration float64 `json:"duration"` diff --git a/backend/plugins/jenkins/models/scope_config.go b/backend/plugins/jenkins/models/scope_config.go index 1eb889ca43f..7f7b9003925 100644 --- a/backend/plugins/jenkins/models/scope_config.go +++ b/backend/plugins/jenkins/models/scope_config.go @@ -23,8 +23,8 @@ import ( type JenkinsScopeConfig struct { common.ScopeConfig `mapstructure:",squash" json:",inline" gorm:"embedded"` - DeploymentPattern string `gorm:"type:varchar(255)" mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern"` - ProductionPattern string `gorm:"type:varchar(255)" mapstructure:"productionPattern,omitempty" json:"productionPattern"` + DeploymentPattern *string `gorm:"type:varchar(255)" mapstructure:"deploymentPattern,omitempty" json:"deploymentPattern"` + ProductionPattern *string `gorm:"type:varchar(255)" mapstructure:"productionPattern,omitempty" json:"productionPattern"` } func (t JenkinsScopeConfig) TableName() string { diff --git a/backend/plugins/jenkins/tasks/build_cicd_convertor.go b/backend/plugins/jenkins/tasks/build_cicd_convertor.go index 34ec88d576b..f09f27b7579 100644 --- a/backend/plugins/jenkins/tasks/build_cicd_convertor.go +++ b/backend/plugins/jenkins/tasks/build_cicd_convertor.go @@ -128,8 +128,10 @@ func ConvertBuildsToCicdTasks(taskCtx plugin.SubTaskContext) (err errors.Error) }, DurationSec: durationSec, CicdScopeId: jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Options.JobFullName), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, jenkinsBuild.FullName), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, jenkinsBuild.FullName), + } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + jenkinsPipeline.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, jenkinsBuild.FullName) + jenkinsPipeline.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, jenkinsBuild.FullName) } jenkinsPipeline.RawDataOrigin = jenkinsBuild.RawDataOrigin results = append(results, jenkinsPipeline) @@ -151,10 +153,12 @@ func ConvertBuildsToCicdTasks(taskCtx plugin.SubTaskContext) (err errors.Error) FinishedDate: jenkinsPipelineFinishedDate, }, CicdScopeId: jobIdGen.Generate(jenkinsBuild.ConnectionId, data.Options.JobFullName), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, jenkinsBuild.FullName), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, jenkinsBuild.FullName), PipelineId: buildIdGen.Generate(jenkinsBuild.ConnectionId, jenkinsBuild.FullName), } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + jenkinsTask.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, jenkinsBuild.FullName) + jenkinsTask.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, jenkinsBuild.FullName) + } // if the task is not executed, set the result to default, so that it will not be calculated in the dora if jenkinsTask.OriginalStatus == "NOT_EXECUTED" { jenkinsTask.Result = devops.RESULT_DEFAULT diff --git a/backend/plugins/jenkins/tasks/build_collector.go b/backend/plugins/jenkins/tasks/build_collector.go index 0d792c61454..c0b47f95f79 100644 --- a/backend/plugins/jenkins/tasks/build_collector.go +++ b/backend/plugins/jenkins/tasks/build_collector.go @@ -90,7 +90,7 @@ func collectSingleJobApiBuilds(taskCtx plugin.SubTaskContext) errors.Error { Query: func(reqData *helper.RequestData, createdAfter *time.Time) (url.Values, errors.Error) { query := url.Values{} treeValue := fmt.Sprintf( - "allBuilds[timestamp,number,duration,building,estimatedDuration,fullDisplayName,result,actions[lastBuiltRevision[SHA1,branch[name]],remoteUrls,mercurialRevisionNumber,causes[*]],changeSet[kind,revisions[revision]]]{%d,%d}", + "allBuilds[timestamp,number,duration,building,estimatedDuration,fullDisplayName,result,url,actions[lastBuiltRevision[SHA1,branch[name]],remoteUrls,mercurialRevisionNumber,causes[*]],changeSet[kind,revisions[revision]]]{%d,%d}", reqData.Pager.Skip, reqData.Pager.Skip+reqData.Pager.Size) query.Set("tree", treeValue) return query, nil diff --git a/backend/plugins/jenkins/tasks/build_extractor.go b/backend/plugins/jenkins/tasks/build_extractor.go index d039034ab5a..842c46d2cde 100644 --- a/backend/plugins/jenkins/tasks/build_extractor.go +++ b/backend/plugins/jenkins/tasks/build_extractor.go @@ -81,6 +81,7 @@ func ExtractApiBuilds(taskCtx plugin.SubTaskContext) errors.Error { EstimatedDuration: body.EstimatedDuration, Number: body.Number, Result: body.Result, + Url: body.Url, Timestamp: body.Timestamp, Class: class, Building: body.Building, diff --git a/backend/plugins/jenkins/tasks/stage_convertor.go b/backend/plugins/jenkins/tasks/stage_convertor.go index 35c31fade1c..83a053ecf94 100644 --- a/backend/plugins/jenkins/tasks/stage_convertor.go +++ b/backend/plugins/jenkins/tasks/stage_convertor.go @@ -152,8 +152,10 @@ func ConvertStages(taskCtx plugin.SubTaskContext) (err errors.Error) { OriginalResult: body.Result, OriginalStatus: body.Status, CicdScopeId: jobIdGen.Generate(body.ConnectionId, data.Options.JobFullName), - Type: data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.Name), - Environment: data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, body.Name), + } + if data.Options.ScopeConfig.DeploymentPattern != nil || data.Options.ScopeConfig.ProductionPattern != nil { + jenkinsTask.Type = data.RegexEnricher.ReturnNameIfMatched(devops.DEPLOYMENT, body.Name) + jenkinsTask.Environment = data.RegexEnricher.ReturnNameIfOmittedOrMatched(devops.PRODUCTION, body.Name) } // if the task is not executed, set the result to default, so that it will not be calculated in the dora if jenkinsTask.OriginalStatus == "NOT_EXECUTED" { diff --git a/backend/server/services/remote/plugin/connection_api.go b/backend/server/services/remote/plugin/connection_api.go index 38c832ee7ce..dff9073049a 100644 --- a/backend/server/services/remote/plugin/connection_api.go +++ b/backend/server/services/remote/plugin/connection_api.go @@ -20,13 +20,16 @@ package plugin import ( "encoding/json" "fmt" + "github.com/spf13/cast" + "net/http" + "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/plugin" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/server/api/shared" "github.com/apache/incubator-devlake/server/services/remote/bridge" - "net/http" ) type TestConnectionResult struct { @@ -181,3 +184,87 @@ func (pa *pluginAPI) PatchConnection(input *plugin.ApiResourceInput) (*plugin.Ap func (pa *pluginAPI) DeleteConnection(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { return pa.connhelper.Delete(pa.connType.New(), input) } + +func (pa *pluginAPI) GetConnectionTransformToDeployments(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) { + db := basicRes.GetDal() + connectionId := input.Params["connectionId"] + deploymentPattern := input.Body["deploymentPattern"] + productionPattern := input.Body["productionPattern"] + page, err := api.ParsePageParam(input.Body, "page", 1) + if err != nil { + return nil, errors.Default.New("invalid page value") + } + pageSize, err := api.ParsePageParam(input.Body, "pageSize", 10) + if err != nil { + return nil, errors.Default.New("invalid pageSize value") + } + + cursor, err := db.RawCursor(` + SELECT DISTINCT id, name, url, start_time + FROM( + SELECT id, name, url, start_time + FROM _tool_azuredevops_builds + WHERE connection_id = ? + AND (name REGEXP ?) + AND (? = '' OR name REGEXP ?) + UNION + SELECT b.id, b.name, b.url, b.start_time + FROM _tool_azuredevops_jobs j + LEFT JOIN _tool_azuredevops_builds b on CONCAT('azuredevops:Build:', b.connection_id, ':', b.id) = j.build_id + WHERE j.connection_id = ? + AND (j.name REGEXP ?) + AND (? = '' OR j.name REGEXP ?) + ) AS t + ORDER BY start_time DESC + `, connectionId, deploymentPattern, productionPattern, productionPattern, connectionId, deploymentPattern, productionPattern, productionPattern) + if err != nil { + return nil, errors.Default.Wrap(err, "error on get") + } + defer cursor.Close() + + type selectFileds struct { + Id int + Name string + URL string + } + type transformedFields struct { + Name string `json:"name"` + URL string `json:"url"` + } + var allRuns []transformedFields + for cursor.Next() { + sf := &selectFileds{} + err = db.Fetch(cursor, sf) + if err != nil { + return nil, errors.Default.Wrap(err, "error on fetch") + } + // Directly transform and append to allRuns + transformed := transformedFields{ + Name: fmt.Sprintf("#%d - %s", sf.Id, sf.Name), + URL: sf.URL, + } + allRuns = append(allRuns, transformed) + } + // Calculate total count + totalCount := len(allRuns) + + // Paginate in memory + start := (page - 1) * pageSize + end := start + pageSize + if start > totalCount { + start = totalCount + } + if end > totalCount { + end = totalCount + } + pagedRuns := allRuns[start:end] + + // Return result containing paged runs and total count + result := map[string]interface{}{ + "total": totalCount, + "data": pagedRuns, + } + return &plugin.ApiResourceOutput{ + Body: result, + }, nil +} diff --git a/backend/server/services/remote/plugin/default_api.go b/backend/server/services/remote/plugin/default_api.go index 83ead132798..963fe1cc0cc 100644 --- a/backend/server/services/remote/plugin/default_api.go +++ b/backend/server/services/remote/plugin/default_api.go @@ -82,6 +82,9 @@ func GetDefaultAPI( "POST": papi.PostScopeConfigs, "GET": papi.ListScopeConfigs, }, + "connections/:connectionId/transform-to-deployments": { + "POST": papi.GetConnectionTransformToDeployments, + }, "connections/:connectionId/scope-configs/:id": { "GET": papi.GetScopeConfig, "PATCH": papi.PatchScopeConfig, diff --git a/config-ui/package.json b/config-ui/package.json index 262107be7c3..6bf07198852 100644 --- a/config-ui/package.json +++ b/config-ui/package.json @@ -22,15 +22,15 @@ ] }, "dependencies": { - "@ant-design/icons": "^5.3.0", + "@ant-design/icons": "^5.4.0", "@fontsource/roboto": "^5.0.14", "@mints/hooks": "^1.0.0-beta.2", - "@mints/miller-columns": "^2.0.0-beta.1", + "@mints/miller-columns": "^2.0.0-beta.5", "@mui/icons-material": "^5.16.7", "@mui/material": "^5.16.7", "@mui/styled-engine-sc": "^6.0.0-alpha.18", "@reduxjs/toolkit": "^2.2.1", - "antd": "^5.14.2", + "antd": "^5.20.6", "axios": "^1.6.7", "classnames": "^2.5.1", "cron-parser": "^4.9.0", diff --git a/config-ui/src/api/scope-config/index.ts b/config-ui/src/api/scope-config/index.ts index 41547d9c058..2bb23d422fb 100644 --- a/config-ui/src/api/scope-config/index.ts +++ b/config-ui/src/api/scope-config/index.ts @@ -18,7 +18,7 @@ import { request } from '@/utils'; -import { ICheck } from './types'; +import { ICheck, ITransform2deployments } from './types'; export const list = (plugin: string, connectionId: ID) => request(`/plugins/${plugin}/connections/${connectionId}/scope-configs`); @@ -40,3 +40,19 @@ export const update = (plugin: string, connectionId: ID, id: ID, data: any) => export const check = (plugin: string, id: ID): Promise => request(`/plugins/${plugin}/scope-config/${id}/projects`); + +export const deployments = (plugin: string, connectionId: ID): Promise => + request(`/plugins/${plugin}/connections/${connectionId}/deployments`); + +export const transform2deployments = ( + plugin: string, + connectionId: ID, + data: { + deploymentPattern: string; + productionPattern: string; + } & Pagination, +): Promise<{ total: number; data: ITransform2deployments[] | null }> => + request(`/plugins/${plugin}/connections/${connectionId}/transform-to-deployments`, { + method: 'post', + data, + }); diff --git a/config-ui/src/api/scope-config/types.ts b/config-ui/src/api/scope-config/types.ts index 4c779c6589b..e61992aca1b 100644 --- a/config-ui/src/api/scope-config/types.ts +++ b/config-ui/src/api/scope-config/types.ts @@ -22,3 +22,8 @@ export type ICheck = { name: string; }>; }; + +export type ITransform2deployments = { + name: string; + url: string; +}; diff --git a/config-ui/src/components/action/icon-button/index.tsx b/config-ui/src/components/action/icon-button/index.tsx index f7bc8b1d94a..22900edb137 100644 --- a/config-ui/src/components/action/icon-button/index.tsx +++ b/config-ui/src/components/action/icon-button/index.tsx @@ -28,7 +28,7 @@ interface Props helptip: string; } -export const IconButton = forwardRef(function ({ helptip, ...props }: Props, ref?: Ref) { +export const IconButton = forwardRef(function ({ helptip, ...props }: Props, ref?: Ref) { return ( + + {show && children} + + ); +}; diff --git a/config-ui/src/plugins/components/check-matched-items/index.tsx b/config-ui/src/plugins/components/check-matched-items/index.tsx new file mode 100644 index 00000000000..c3537827df6 --- /dev/null +++ b/config-ui/src/plugins/components/check-matched-items/index.tsx @@ -0,0 +1,115 @@ +/* + * 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. + * + */ + +import { useState, useReducer, useEffect } from 'react'; +import { SearchOutlined, PlusOutlined } from '@ant-design/icons'; +import { Flex, Button, Tag } from 'antd'; + +import API from '@/api'; +import type { ITransform2deployments } from '@/api/scope-config/types'; +import { ExternalLink } from '@/components'; +import { operator } from '@/utils'; + +const reducer = (state: ITransform2deployments[], action: { type: string; payload?: ITransform2deployments[] }) => { + switch (action.type) { + case 'RESET': + return []; + case 'APPEND': + return [...state, ...(action.payload ?? [])]; + default: + return state; + } +}; + +interface Props { + plugin: string; + connectionId: ID; + transformation: any; +} + +export const CheckMatchedItems = ({ plugin, connectionId, transformation }: Props) => { + const [inital, setInitial] = useState(false); + const [page, setPage] = useState(1); + const [total, setTotal] = useState(0); + const [loading, setLoading] = useState(false); + + const [state, dispatch] = useReducer(reducer, []); + + useEffect(() => { + dispatch({ type: 'RESET' }); + setInitial(false); + setPage(1); + setTotal(0); + }, [transformation.deploymentPattern, transformation.productionPattern]); + + const handleLoadItems = async () => { + const [success, res] = await operator( + () => + API.scopeConfig.transform2deployments(plugin, connectionId, { + deploymentPattern: transformation.deploymentPattern, + productionPattern: transformation.productionPattern, + page, + pageSize: 10, + }), + { + setOperating: setLoading, + hideToast: true, + }, + ); + + if (success) { + dispatch({ type: 'APPEND', payload: res.data ?? [] }); + setInitial(true); + setPage(page + 1); + setTotal(res.total); + } + }; + + return ( + +
+ +
+ {inital ? ( + total === 0 ? ( +

No item found

+ ) : ( + +

Matched Items

+ + {state.map((it) => ( + + {it.name} + + ))} + + {total && total > state.length && ( +
+ +
+ )} +
+ ) + ) : null} +
+ ); +}; diff --git a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx index 7319c121385..67b8f4a7f16 100644 --- a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx +++ b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx @@ -31,13 +31,9 @@ import * as S from './styled'; type StateType = { status: string; scope: any[]; - originData: any[]; }; -const reducer = ( - state: StateType, - action: { type: string; payload?: Pick, 'scope' | 'originData'> }, -) => { +const reducer = (state: StateType, action: { type: string; payload?: Pick, 'scope'> }) => { switch (action.type) { case 'LOADING': return { @@ -48,7 +44,6 @@ const reducer = ( return { ...state, scope: [...state.scope, ...(action.payload?.scope ?? [])], - originData: [...state.originData, ...(action.payload?.originData ?? [])], }; case 'DONE': return { @@ -74,50 +69,49 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, const [open, setOpen] = useState(false); const [search, setSearch] = useState(''); - const [{ status, scope, originData }, dispatch] = useReducer(reducer, { + const [{ status, scope }, dispatch] = useReducer(reducer, { status: 'idle', scope: [], - originData: [], }); const searchDebounce = useDebounce(search, { wait: 500 }); const request = useCallback( async (groupId?: string | number, params?: any) => { - if (scope.length) { - return { - data: searchDebounce - ? scope - .filter((it) => it.title.includes(searchDebounce) && !it.canExpand) - .map((it) => ({ ...it, parentId: null })) - : scope.filter((it) => it.parentId === (groupId ?? null)), - hasMore: status === 'loading' ? true : false, - originData, - }; - } - const res = await API.scope.remote(plugin, connectionId, { groupId: groupId ?? null, pageToken: params?.nextPageToken, }); - const data = res.children.map((it) => ({ - parentId: it.parentId, - id: it.id, - title: it.name ?? it.fullName, - canExpand: it.type === 'group', - })); - return { - data, + data: res.children.map((it) => ({ + parentId: it.parentId, + id: it.id, + title: it.name ?? it.fullName, + canExpand: it.type === 'group', + original: it, + })), hasMore: !!res.nextPageToken, params: { nextPageToken: res.nextPageToken, }, - originData: res.children, }; }, - [plugin, connectionId, scope, status, searchDebounce], + [plugin, connectionId, scope, searchDebounce], + ); + + const requestAll = useCallback( + async (groupId?: string | number) => { + return { + data: searchDebounce + ? scope + .filter((it) => it.title.includes(searchDebounce) && !it.canExpand) + .map((it) => ({ ...it, parentId: null })) + : scope.filter((it) => it.parentId === (groupId ?? null)), + hasMore: false, + }; + }, + [scope, searchDebounce], ); const handleRequestAll = async () => { @@ -135,9 +129,9 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, id: it.id, title: it.name ?? it.fullName, canExpand: it.type === 'group', + original: it, })); - - dispatch({ type: 'APPEND', payload: { scope: data, originData: res.children } }); + dispatch({ type: 'APPEND', payload: { scope: data } }); if (res.nextPageToken) { await getData(groupId, res.nextPageToken); @@ -172,17 +166,17 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, - {(status === 'loading' || status === 'cancel') && ( + {status === 'loading' && ( - Loading: {scope.length} scopes found + Loading: {scope.filter((sc) => !sc.canExpand).length} scopes found )} {status === 'done' && ( - {scope.length} scopes found + {scope.filter((sc) => !sc.canExpand).length} scopes found )} @@ -195,32 +189,59 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, )} + {status === 'idle' && ( + + !id && + config.millerColumn?.firstColumnTitle && ( + {config.millerColumn.firstColumnTitle} + ) + } + renderLoading={() => } + renderError={() => Something Error} + selectable + disabledIds={(disabledScope ?? []).map((it) => it.id)} + selectedIds={selectedScope.map((it) => it.id)} + onSelectedIds={(_, data) => onChange(data ?? [])} + /> + )} {status === 'done' && ( - } value={search} onChange={(e) => setSearch(e.target.value)} /> + <> + } value={search} onChange={(e) => setSearch(e.target.value)} /> + + !id && + config.millerColumn?.firstColumnTitle && ( + {config.millerColumn.firstColumnTitle} + ) + } + renderLoading={() => } + renderError={() => Something Error} + selectable + disabledIds={(disabledScope ?? []).map((it) => it.id)} + selectedIds={selectedScope.map((it) => it.id)} + onSelectedIds={(_, data) => onChange(data ?? [])} + /> + )} - - !id && - config.millerColumn?.firstColumnTitle && ( - {config.millerColumn.firstColumnTitle} - ) - } - renderLoading={() => } - renderError={() => Something Error} - selectable - disabledIds={(disabledScope ?? []).map((it) => it.id)} - selectedIds={selectedScope.map((it) => it.id)} - onSelectedIds={(ids, data) => onChange((data ?? []).filter((it) => ids.includes(it.id)))} - /> setOpen(false)}> diff --git a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx index b87cc55fdb5..0510ad29a88 100644 --- a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx +++ b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx @@ -48,7 +48,6 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope let data = []; let hasMore = false; let newParams = {}; - let originData = []; if (!searchDebounce) { const res = await API.scope.remote(plugin, connectionId, { @@ -61,13 +60,13 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope id: it.id, title: it.name ?? it.fullName, canExpand: it.type === 'group', + original: it, })); hasMore = !!res.nextPageToken; newParams = { pageToken: res.nextPageToken, }; - originData = res.children; } else { const res = await API.scope.searchRemote(plugin, connectionId, { search: searchDebounce, @@ -80,6 +79,7 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope id: it.id, title: it.fullName ?? it.name, canExpand: it.type === 'group', + original: it, })); hasMore = res.children.length === res.pageSize; @@ -87,14 +87,12 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope page: (params?.page ?? 0) + 1, count: (params?.count ?? 0) + res.children.length, }; - originData = res.children; } return { data, hasMore, params: newParams, - originData, }; }, [plugin, connectionId, searchDebounce], @@ -147,7 +145,7 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope selectable disabledIds={disabledScope.map((it) => it.id)} selectedIds={selectedScope.map((it) => it.id)} - onSelectedIds={(ids, data) => onChange((data ?? []).filter((it) => ids.includes(it.id)))} + onSelectedIds={(_, data) => onChange(data ?? [])} /> diff --git a/config-ui/src/plugins/components/data-scope-select/index.tsx b/config-ui/src/plugins/components/data-scope-select/index.tsx index 9ac0bfe18f4..d6913cee0a8 100644 --- a/config-ui/src/plugins/components/data-scope-select/index.tsx +++ b/config-ui/src/plugins/components/data-scope-select/index.tsx @@ -73,20 +73,18 @@ export const DataScopeSelect = ({ searchTerm: searchDebounce, }); - const data = res.scopes.map((it) => ({ - parentId: null, - id: getPluginScopeId(plugin, it.scope), - title: it.scope.fullName ?? it.scope.name, - canExpand: false, - })); - return { - data, + data: res.scopes.map((it) => ({ + parentId: null, + id: getPluginScopeId(plugin, it.scope), + title: it.scope.fullName ?? it.scope.name, + canExpand: false, + original: it, + })), hasMore: res.count > (params?.page ?? 1) * 20, params: { page: (params?.page ?? 1) + 1, }, - originData: res.scopes, }; }, [plugin, connectionId, searchDebounce, version], @@ -168,12 +166,10 @@ export const DataScopeSelect = ({ onSelectedIds={(ids, data) => { setSelectedIds(ids); setSelectedScope( - data - ?.filter((it) => ids.includes(getPluginScopeId(plugin, it.scope))) - .map((it) => ({ - id: getPluginScopeId(plugin, it.scope), - name: it.scope.fullName ?? it.scope.name, - })) ?? [], + (data ?? []).map((it) => ({ + id: it.scope.id, + name: it.scope.name, + })), ); }} /> diff --git a/config-ui/src/plugins/components/deployments/index.tsx b/config-ui/src/plugins/components/deployments/index.tsx new file mode 100644 index 00000000000..d813a5f2f27 --- /dev/null +++ b/config-ui/src/plugins/components/deployments/index.tsx @@ -0,0 +1,109 @@ +/* + * 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. + * + */ + +import { useState, useEffect } from 'react'; +import { Space, Select, Input } from 'antd'; +import { useRequest } from '@mints/hooks'; + +import API from '@/api'; +import { Loading } from '@/components'; + +interface Props { + style?: React.CSSProperties; + plugin: string; + connectionId: ID; + transformation: any; + setTransformation: React.Dispatch>; +} + +export const Deployments = ({ style, plugin, connectionId, transformation, setTransformation }: Props) => { + const [type, setType] = useState('select'); + + const { loading, data } = useRequest(() => API.scopeConfig.deployments(plugin, connectionId), [plugin, connectionId]); + + useEffect(() => { + if (transformation.envNamePattern) { + setType('regex'); + } + }, [transformation]); + + const handleChangeType = (t: string) => { + if (t === 'regex') { + setTransformation({ + ...transformation, + envNameList: [], + }); + } + + if (t === 'select') { + setTransformation({ + ...transformation, + envNamePattern: '', + }); + } + + setType(t); + }; + + const handleChangeRegex = (e: React.ChangeEvent) => { + const envNamePattern = e.target.value; + setTransformation({ + ...transformation, + envNamePattern, + envNameList: [], + }); + }; + + const handleChangeSelect = (value: string[]) => { + setTransformation({ + ...transformation, + envNamePattern: '', + envNameList: value, + }); + }; + + if (loading || !data) { + return ; + } + + return ( + + + {type === 'regex' ? ( + + ) : ( + + )} + + ); +}; diff --git a/config-ui/src/plugins/components/index.ts b/config-ui/src/plugins/components/index.ts index 337e446fecd..4cbfa01e5d7 100644 --- a/config-ui/src/plugins/components/index.ts +++ b/config-ui/src/plugins/components/index.ts @@ -16,12 +16,14 @@ * */ +export * from './check-matched-items'; export * from './connection-form'; export * from './connection-list'; export * from './connection-select'; export * from './connection-status'; export * from './data-scope-remote'; export * from './data-scope-select'; +export * from './deployments'; export * from './plugin-name'; export * from './scope-config'; export * from './scope-config-form'; diff --git a/config-ui/src/plugins/components/scope-config-form/index.tsx b/config-ui/src/plugins/components/scope-config-form/index.tsx index ab2aabef78f..d4f4c04f49e 100644 --- a/config-ui/src/plugins/components/scope-config-form/index.tsx +++ b/config-ui/src/plugins/components/scope-config-form/index.tsx @@ -193,16 +193,10 @@ export const ScopeConfigForm = ({ )}
- {plugin === 'azuredevops' && ( - - )} - - {plugin === 'azuredevops_go' && ( + {(plugin === 'azuredevops' || plugin === 'azuredevops_go') && ( w7TkMKMIp#29-WTY24;NKDoDjNDLBxDRk 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%0Dk>xzcOrNoMrJTYAkZ>`{WwoydA({j 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

gDRwLWGEji6#GWeMdL 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 } -export const AzureTransformation = ({ entities, transformation, setTransformation }: Props) => { +export const AzureTransformation = ({ plugin, connectionId, entities, transformation, setTransformation }: Props) => { const { token } = theme.useToken(); const panelStyle: React.CSSProperties = { @@ -46,6 +51,8 @@ export const AzureTransformation = ({ entities, transformation, setTransformatio style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -56,11 +63,15 @@ export const AzureTransformation = ({ entities, transformation, setTransformatio }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, onChangeTransformation, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -79,10 +90,12 @@ const renderCollapseItems = ({ DORA -

- Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '} - Learn more -

+ Use Regular Expression to define Deployments to measure DORA metrics.

} + btnText="See how to configure" + > + +
Convert a Azure Pipeline Run as a DevLake Deployment when:
@@ -90,7 +103,7 @@ const renderCollapseItems = ({ onChangeTransformation({ @@ -107,7 +120,7 @@ const renderCollapseItems = ({ If the name also matches onChangeTransformation({ @@ -119,6 +132,7 @@ const renderCollapseItems = ({ , this Deployment is a ‘Production Deployment’
+ ), }, diff --git a/config-ui/src/plugins/register/azure/workflow-run.tsx b/config-ui/src/plugins/register/azure/workflow-run.tsx new file mode 100644 index 00000000000..088ba53bb85 --- /dev/null +++ b/config-ui/src/plugins/register/azure/workflow-run.tsx @@ -0,0 +1,98 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
Example - Convert all runs of Azure pipeline ‘build-and-push-image’ to production deployments
+
    +
  1. Go to your Azure Pipelines page.
  2. +
  3. + Navigate to ‘Runs’ (See the blue text), where you will see all runs of all + pipelines (including ‘build-and-push-image’) in this repository. + +
  4. +
  5. +
    + In the first input field, enter the following regex to identify deployments (highlighted in the{' '} + yellow rectangle and text). +
    +
    + The name of the Azure pipeline or one of its jobs matches + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify the production deployments (as shown in the{' '} + red rectangle). If left empty, all deployments in the{' '} + yellow rectangle will be regarded as Production Deployments. +
    +
    + If the name also matches{' '} + , this deployment + will be classified as a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/bamboo/assets/workflow-run.jpeg b/config-ui/src/plugins/register/bamboo/assets/workflow-run.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..d7d98e6759b0138fbeaf3efe60c30f3b76e5e9ef GIT binary patch literal 113157 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 Xpx$n@u{YYL9pO!P2BiK){r{T)DTwId literal 0 HcmV?d00001 diff --git a/config-ui/src/plugins/register/bamboo/config.tsx b/config-ui/src/plugins/register/bamboo/config.tsx index cd7f8f775bf..c41e71d27d4 100644 --- a/config-ui/src/plugins/register/bamboo/config.tsx +++ b/config-ui/src/plugins/register/bamboo/config.tsx @@ -49,10 +49,6 @@ export const BambooConfig: IPluginConfig = { }, scopeConfig: { entities: ['CICD', 'CROSS'], - transformation: { - envNamePattern: '(?i)prod(.*)', - deploymentPattern: '', - productionPattern: '', - }, + transformation: {}, }, }; diff --git a/config-ui/src/plugins/register/bamboo/transformation.tsx b/config-ui/src/plugins/register/bamboo/transformation.tsx index 07c1fb35aeb..f33c0cb3a3f 100644 --- a/config-ui/src/plugins/register/bamboo/transformation.tsx +++ b/config-ui/src/plugins/register/bamboo/transformation.tsx @@ -20,16 +20,21 @@ import { useState, useEffect } from 'react'; import { CaretRightOutlined } from '@ant-design/icons'; import { theme, Collapse, Tag, Input, Checkbox } from 'antd'; -import { ExternalLink, HelpTooltip } from '@/components'; +import { ShowMore, ExternalLink, HelpTooltip } from '@/components'; +import { Deployments, CheckMatchedItems } from '@/plugins'; import { DOC_URL } from '@/release'; +import { WorkflowRun } from './workflow-run'; + interface Props { + plugin: string; + connectionId: ID; entities: string[]; transformation: any; setTransformation: React.Dispatch>; } -export const BambooTransformation = ({ entities, transformation, setTransformation }: Props) => { +export const BambooTransformation = ({ plugin, connectionId, entities, transformation, setTransformation }: Props) => { const [useCustom, setUseCustom] = useState(false); useEffect(() => { @@ -38,12 +43,18 @@ export const BambooTransformation = ({ entities, transformation, setTransformati } else { setUseCustom(false); } - }, [transformation]); + }, []); const handleChangeUseCustom = (e: React.FormEvent) => { const checked = (e.target as HTMLInputElement).checked; if (!checked) { + setTransformation({ + ...transformation, + deploymentPattern: undefined, + productionPattern: undefined, + }); + } else { setTransformation({ ...transformation, deploymentPattern: '', @@ -71,6 +82,8 @@ export const BambooTransformation = ({ entities, transformation, setTransformati style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -83,6 +96,8 @@ export const BambooTransformation = ({ entities, transformation, setTransformati }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -90,6 +105,8 @@ const renderCollapseItems = ({ useCustom, onChangeUseCustom, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -118,56 +135,63 @@ const renderCollapseItems = ({ Convert a Bamboo Deployment to a DevLake Deployment

- If its environment name matches - - onChangeTransformation({ - ...transformation, - envNamePattern: e.target.value, - }) - } + If the environment + , this deployment is a ‘Production Deployment’
- Convert a Bamboo Plan Build to a DevLake Deployment when its name or one of its job builds’ names + Convert a Bamboo Plan Build to a DevLake Deployment when: -
- matches - - onChangeTransformation({ - ...transformation, - deploymentPattern: e.target.value, - productionPattern: !e.target.value ? '' : transformation.productionPattern, - }) - } - /> - . - -
-
- If the name also matches - - onChangeTransformation({ - ...transformation, - productionPattern: e.target.value, - }) - } - /> - , this Deployment is a ‘Production Deployment’ - -
+ {useCustom && ( +
+ Select this option only if you are not enabling Bamboo Deployments

} + btnText="See how to configure" + > + +
+
+ The name of the plan or one of its jobs matches + + onChangeTransformation({ + ...transformation, + deploymentPattern: e.target.value, + productionPattern: !e.target.value ? '' : transformation.productionPattern, + }) + } + /> + . + +
+
+ If the name also matches + + onChangeTransformation({ + ...transformation, + productionPattern: e.target.value, + }) + } + /> + , this deployment will be regarded as a ‘Production Deployment’ + +
+ +
+ )} ), }, diff --git a/config-ui/src/plugins/register/bamboo/workflow-run.tsx b/config-ui/src/plugins/register/bamboo/workflow-run.tsx new file mode 100644 index 00000000000..e52d33497f7 --- /dev/null +++ b/config-ui/src/plugins/register/bamboo/workflow-run.tsx @@ -0,0 +1,94 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
Example - Convert all builds of Bamboo plan ‘p1’ to production deployments
+
    +
  1. Go to your Bamboo plan list.
  2. +
  3. + Locate the Bamboo plan ‘p1’. All 4 builds of this plan will be converted to production deployments with the + following steps. + +
  4. +
  5. +
    In the first input field, enter the following regex to identify deployments:
    +
    + The name of the plan or one of its jobs matches{' '} + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify the production deployments in the{' '} + red rectangle. If you leave it empty, all deployments in the yellow rectangle + will be regarded as Production Deployments. +
    +
    + If the name also matches , this + deployment will be classified as a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/bitbucket/assets/workflow-run-1.jpeg b/config-ui/src/plugins/register/bitbucket/assets/workflow-run-1.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..4d8edae8e39f873958faf2fa82c94aab006eaa05 GIT binary patch literal 71873 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
-
- If the name also matches - - onChangeTransformation({ - ...transformation, - productionPattern: e.target.value, - }) - } - /> - , this Deployment is a ‘Production Deployment’ - -
+ {useCustom && ( +
+ Select this option only if you are not enabling Bitbucket deployments.

} + btnText="See how to configure" + > + +
+
+ Its branch or one of its steps matches + + onChangeTransformation({ + ...transformation, + deploymentPattern: e.target.value, + productionPattern: !e.target.value ? '' : transformation.productionPattern, + }) + } + /> + . + * + +
+
+ If the branch or the step also matches + + onChangeTransformation({ + ...transformation, + productionPattern: e.target.value, + }) + } + /> + , this deployment will be regarded as a ‘Production Deployment’. + +
+ +
+ )} ), }, diff --git a/config-ui/src/plugins/register/bitbucket/workflow-run.tsx b/config-ui/src/plugins/register/bitbucket/workflow-run.tsx new file mode 100644 index 00000000000..84ae27eddf0 --- /dev/null +++ b/config-ui/src/plugins/register/bitbucket/workflow-run.tsx @@ -0,0 +1,104 @@ +/* + * 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. + * + */ + +import { Flex, Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture1 from './assets/workflow-run-1.jpeg'; +import Picture2 from './assets/workflow-run-2.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
+ Example - Convert Bitbucket pipelines that have executed the step ‘Deploy-to-prod’ to production deployments +
+
    +
  1. Go to your Bitbucket Pipelines page (as shown in the first picture).
  2. +
  3. + Locate a successful pipeline that have executed the step ‘Deploy-to-prod’, you will see all steps executed in + this pipeline (as shown in the second picture). + + + + +
  4. +
  5. +
    + In the first input field, enter the following regex to identify this pipeline as a deployment (as + highlighted in the yellow rectangle). +
    +
    + Its branch or one of its steps matches + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify the production deployments (highlighted in + the red rectangle). If left empty, all pipelines containing the job in the{' '} + yellow rectangle will be regarded as Production Deployments. +
    +
    + If the branch or the step also matches{' '} + , this deployment will be regarded as + a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/circleci/assets/workflow-run.jpeg b/config-ui/src/plugins/register/circleci/assets/workflow-run.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..5f401517f2a89a033d7c4f2d0ce44ddde1b15f86 GIT binary patch literal 197685 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 UmAe(& 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

&;#nZ&nJtDy*PPxW?_TFD< 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 } -export const CircleCITransformation = ({ entities, transformation, setTransformation }: Props) => { +export const CircleCITransformation = ({ + plugin, + connectionId, + entities, + transformation, + setTransformation, +}: Props) => { const { token } = theme.useToken(); const panelStyle: React.CSSProperties = { @@ -46,6 +57,8 @@ export const CircleCITransformation = ({ entities, transformation, setTransforma style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -56,11 +69,15 @@ export const CircleCITransformation = ({ entities, transformation, setTransforma }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, onChangeTransformation, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -79,10 +96,12 @@ const renderCollapseItems = ({ DORA -

- Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '} - Learn more -

+ Use Regular Expression to define Deployments to measure DORA metrics.

} + btnText="See how to configure" + > + +
Convert a CircleCI Workflow Run as a DevLake Deployment when:
@@ -90,7 +109,7 @@ const renderCollapseItems = ({ onChangeTransformation({ @@ -104,10 +123,11 @@ const renderCollapseItems = ({
- If the name also matches + If the name or its branch matches onChangeTransformation({ @@ -116,9 +136,10 @@ const renderCollapseItems = ({ }) } /> - , this Deployment is a ‘Production Deployment’ + , this deployment will be regarded as a ‘Production Deployment’
+ ), }, diff --git a/config-ui/src/plugins/register/circleci/workflow-run.tsx b/config-ui/src/plugins/register/circleci/workflow-run.tsx new file mode 100644 index 00000000000..4eefc108f69 --- /dev/null +++ b/config-ui/src/plugins/register/circleci/workflow-run.tsx @@ -0,0 +1,97 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
Example - Convert all runs of CircleCI workflow ‘test-build-and-deploy’ to production deployments
+
    +
  1. Go to your CircleCI Pipelines page.
  2. +
  3. + Locate the workflows executed in each pipeline (see the ‘Workflow’ column). You will see some pipeline run + includes the workflow ‘test-build-and-deploy’. + +
  4. +
  5. +
    + In the first input field, enter the following regex to define which workflow run is a deployment (see + ‘test-build-and-deploy’ in the yellow rectangle) +
    +
    + The name of the CircleCI workflow or one of its jobs matches + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify the production deployments (as shown in the{' '} + red rectangle). If left empty, all deployments in the{' '} + yellow rectangle will be regarded as Production Deployments. +
    +
    + If the name or its branch matches , this + deployment will be classified as a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/github/assets/workflow-run.jpeg b/config-ui/src/plugins/register/github/assets/workflow-run.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..468f28f648480487ccd1678b83f09bc05d11dd28 GIT binary patch literal 189484 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 z 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 z%0D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 CQmE>; setHasError: React.Dispatch>; } -export const GitHubTransformation = ({ entities, transformation, setTransformation, setHasError }: Props) => { +export const GitHubTransformation = ({ + plugin, + connectionId, + entities, + transformation, + setTransformation, + setHasError, +}: Props) => { const [useCustom, setUseCustom] = useState(false); useEffect(() => { @@ -40,7 +52,7 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati } else { setUseCustom(false); } - }, [transformation]); + }, []); useEffect(() => { setHasError(useCustom && !transformation.deploymentPattern); @@ -50,6 +62,12 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati const checked = (e.target as HTMLInputElement).checked; if (!checked) { + setTransformation({ + ...transformation, + deploymentPattern: undefined, + productionPattern: undefined, + }); + } else { setTransformation({ ...transformation, deploymentPattern: '', @@ -77,6 +95,8 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -89,6 +109,8 @@ export const GitHubTransformation = ({ entities, transformation, setTransformati }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -96,6 +118,8 @@ const renderCollapseItems = ({ useCustom, onChangeUseCustom, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -244,58 +268,65 @@ const renderCollapseItems = ({ Convert a GitHub Deployment to a DevLake Deployment
- If its environment name matches - - onChangeTransformation({ - ...transformation, - envNamePattern: e.target.value, - }) - } + If its environment name + , this deployment is a ‘Production Deployment’
Convert a GitHub workflow run as a DevLake Deployment when: -
- - The name of the GitHub workflow run or one of its jobs matches - - - onChangeTransformation({ - ...transformation, - deploymentPattern: e.target.value, - productionPattern: !e.target.value ? '' : transformation.productionPattern, - }) - } - /> - * - -
-
- If the name or its branch’s name also matches - - onChangeTransformation({ - ...transformation, - productionPattern: e.target.value, - }) - } - /> - , this deployment is a ‘Production Deployment’ - -
+ {useCustom && ( +
+ Select this option only if you are not enabling GitHub Deployments.

} + btnText="See how to configure" + > + +
+
+ + The name of the GitHub workflow run or one of its jobs matches + + + onChangeTransformation({ + ...transformation, + deploymentPattern: e.target.value, + productionPattern: !e.target.value ? '' : transformation.productionPattern, + }) + } + /> + * + +
+
+ If the name or its branch’s name also matches + + onChangeTransformation({ + ...transformation, + productionPattern: e.target.value, + }) + } + /> + , this deployment is a ‘Production Deployment’ + +
+ +
+ )} ), }, diff --git a/config-ui/src/plugins/register/github/workflow-run.tsx b/config-ui/src/plugins/register/github/workflow-run.tsx new file mode 100644 index 00000000000..2a22be541c2 --- /dev/null +++ b/config-ui/src/plugins/register/github/workflow-run.tsx @@ -0,0 +1,103 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
+ Example - Convert workflow runs of ‘Build-Images-Push-Docker’ on the ‘release’ branch to production deployments +
+
    +
  1. + Go to your GitHub Actions page. Select the ‘Build-Images-Push-Docker’ workflow on the left menu (as shown in + the blue rectangle.). +
  2. +
  3. + Locate the workflow run names in the list (highlighted by the yellow text). + They are usually the same as the workflow name. The branch name are shown in the second column in the label + format. + +
  4. +
  5. +
    + In the first input field, enter the following regex to identify deployments (highlighted by the{' '} + yellow rectangle): +
    +
    + The name of the GitHub workflow run or one of its jobs matches{' '} + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify production deployments (highlighted by the{' '} + red rectangle). If left empty, all deployments in the{' '} + yellow rectangle will be regarded as Production Deployments. +
    +
    + If the name or branch matches , + this deployment will be regarded as ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/gitlab/assets/workflow-run.jpeg b/config-ui/src/plugins/register/gitlab/assets/workflow-run.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..17ecf7362aaba629123c6bb12ca2fb11854eec00 GIT binary patch literal 193279 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
AGpCgJUPh6Ih&<~bd04wDnS4<09 z!J7{Ul-v3Vg|DLTO=D8NO^v2ocK=+N-yP(kgr@vBG*L=!pE6o{Jb8#L=)Wi*zZ8Fe zB(_Aqot?-s?)#&zWHiEBw2J<4rZg#)1(JT=@G`&kBwYctc0K6iHg!um! zpUv{G;!po9s?>ja<){!~+f3VXyhcmMU*_tLK0-^n4M}#UJ5r|V0v}>>1W`TBGd1fH zf{v@rS!Bo*+mb(cb+YUCWx4GSR1|J@d8=s~d8TvzNseWCvSp#_2h4cN;aoFjh-t_m zB$3zU9tDpAB*h!clfzE-s$bY|1ybPT{P~9IV%y;6Mvp&dRju^w(ta?uMn80Go}FSH zsq92u2^$oK-rryE;6r-^zt$ME@WeDDHpw}2xkW{;eXmeIs8Qj|pMtnU^P`dy3Rg?B zM9^P0;7`LddAIW1E~2@|Dv|*LJa~Epx7Xh6v3dnBEIY^RZZwVfVCp{Nx)yh@a~S%U zJAT-hJ)?7qZR*LUmB(a@!H(PiZcy9g0-nK@H4|ijMG<%?H=tXPQ0Y+%;^Q-l&$KPA zQ>ykml%E=t+>8vbk&Z?>qB)hF-kjg5d$!k*aW~Z!-v+=eYc8sZQhe*+;yybZAG9@j z{l+`=E-CRu|F)ZqAk7ki(h{DFF6nVh8PLGE z&t)+w$!`R1pHkftwbCk}owCJ`r0sI6zZmv)v^%j5Bpv{l=FZxZ60$XCi3>sDkQzmy zjeIFpebb{Rw`jY}S1XWzyFaskiM+R2vE&ro>CmDW2k|AFxzl4RDTEhpT$!O)WqVcY z3p*Y4ScGp{=1U{^AJJft8Z#yOptlj7QYINSZqG?$Ff%N{+aep`gr*JU6Ky7Zu#%tW zPKS3r(B}UrN-v*M5L=r^2kY8sq!GGdRUTf_2Q-tjB%E^;iC}2Ig^=mR>a=87hMOkw zOnnXkk!OQMC#p;O$su1}nmR?td_e*Iqfqu>!5` z;+rUsy;!^7MybLGvh!Xz8H+*FR76KP9JalRK>6^RIbZ;c&#VKtU}EB0E>(8(a@ z8v`EY$U;#Sm&WsihgD#nxK2{RQh5FN@N%B)`svkN_2Eg*GU8KnWy95s^{^hH2T>y) zmt*k~6tZt1TPmkUXM!IOm~fJCX8G0|A#Q}kJM^ zEKrhUT~%j(5dLKtKLYLS%QtcPu`0IsAL7VF&k!kyq;hZvW{Dx|i zo=ActrIG*_$ffZ|Bu#uQvpo`vtAE{b&CL$LD+Q2jp&^lw#ZP9|`$u}RK1uXMN!-`B zlRg8s7fb>ju#PU=V^>3;0kJQF>wZ)4-5q?INjMzWpWPd&dMF8a25c%BSU#XU#XM~* zTaeULR{V2^tV;FE4qWkVmyDg)U`j`GzBlH40Djeao7E=qJ>O~DS#Gw1UAU$bJ0nfE zeW6B7BIbAeeu8w#XhF#nyS{G;E=~JAAMb;<)bvi1?xd=`f_z*pQJ`IUi!_iGrw;6Z|uEgRNc$6FA4!dg1fsr zOf*1ncXuYiZQ?E=xVyW%`@{pm-CctRnGig|a@ptZwNKW%cb#|Nc<+39Z+~J8#(#EI zS65Y6cUS$Y(Es++(T>`3v?D!fE>|FxZnzu3K&Qy8A?y}o__(um?X+4$ftUp!UDMe#$ZV)95Tbs;Owi6*xtQASTF6>)#_Qs@yuNQEi3;CYeo2{K z3wh1Bf7TfBkM{`&jjk>Y3bElJ5`p{_%0~zrT(7w;cY%#{Vsc|LN=gd*xtVP5*(VqjuT& z&;~nreRRFJ3OSmPEip)T;EJx~TfEvkh5XU4Sf+Jl>C#SE1!(~iOJm3_+{8y4 z0d*cAwKr}v<>YMfTP20BD(-wYp)5*OG zG{3dF;SUAib9umZZKL}k8H22bkSylysH^mU-goqofF(oXm*g$Lf+IPpb&I{V?iC!h zEsUN)3QQZl=obnDqc7$7)nRYi49(&IKn9bys+efml+cdaKdKLrVUu68-&N20nTMO0 zK>TT3PLa0f)G9@&FzN5dFt!+EG^MYgxGniRG-X znWa>_R{5(He?bW^opE+lOKw@aYArScS&p@p&#kuT#+Ytp@LuYWMraFxgQiX^^$@|l z`XQ{kWndqYrpg!OjV$LO#G~62ko|k>p`>*z^`wNEai|^19w^S}7={PD>K8DBMx)|Q z(Y_${J&DiuSwMebiXAHn*%dYCPtG;Qeq}EG(A<4X{we^heo%WB_10F&Ez%POU||*N zyLeb>hs3)d7s?a*v{ZQ&1=Kpb7B-phV1saE-08E;w0PxV$9Vth$5}S7$?J7fN|A4i zX}Zg`*T$&F`FYDgElV8&#Cz?GmYBfe;;}K828EJFDNfOA-7!Y4{uBs5M+U{Jtt_Hj z2(%S!O+LXbp>#nfpnAGfdprz>y^^nz5wA5OPm+iXQNvD<(Q`nUCvV80xlx;220M|_ z+9?9V=S}}2CPji7eLJ;N!YlQ+&j&}?7_L68qfQPWqK#914QYz?)eL!li`Rt~81`la z6_*kt_*s>F+7ix$CEEt^J=v5lPy_O?J<8}Qe{42BiYx6wd=?Uv=%Q(%ba9ku9vbq*A3r#p)FbmTGQ5K8&)>sNcW@J{{k;L+HlHK;e`* z_u4z*)a|aqr7uC0POb_d-L}dQk$-*E214259ll2y&NRt>It2fws;=Ceksv`qC7RBs z99!k%eW+1k)W@p6Jt8sPjr5MNmgxJYN17gJ^hdD&uoz%%FHzpP36|RB z64|=o_KN!xV=zb4GBv3@_G?DEFs9cw5hG*`L$JZFn)H+N0S#wFSrY6BRw-j&7V|*z z9|_@bX1QVwDsv|N;qw@4$Qa5f@?(qu_tb~u>wYiUd{9vACgpPLi9dp$@DKE8e`LCO z^_g;J!-Keh&cOD@70^>Q8?w`-EvA&M6IJYowv|Xw8f8MSf;fF_B>S+D|6a%@p+}L& zZ=!~3V6LaKPPZgm<4@3t2ujsy5wj@R-e@9idMLN z+MpTGHR1YDAXb&ph~hV`+LM4DAG5RQ5bn301TP5$&`JpNJH>K#TG06F7L4oI*_~&8 z8dK6(F(g?sCOf&b#4p5glHUZlIjWc;z0GYL7Q(<%_oCImJG_k%v7Fi9+-R?ugfP>YsMZVb=HrZF$=sQtI2J zn^IoBwr+dY2u{i5N2zvm(>bH<@Z^-+kdjWpTeQ_uZ24MwCihLj5thBl9Tj6tljXK% ze>;Hioned1EOS#ED{|+jEK2Es4JqW_dV1LNuBaF~NmHbV0qg4CFLtt6CK(#sht;_n zU)(q0($f+EG~}xt%E#BxRQ)Op1AGxoqBj_Cl1Jv>;g#c+r!prLNq2DP@MoSf2k+zb z>==)*a&e1xebQp&*6%ljqx4rtJDv=5S+9tdct!DAU8;Cy^XZ=scIc0}d7DkUjjSwx zPFby4+OkslQlfL@Wl-3Z+LG}pu=I#;F}+sj=w71APXf8!;M@Jjk8=6$9x0kTql{(M zE7Lo2P4__w;r#?IT5zQap4;^iyfp`{;FqkB8Y+@TehEhobW#)!#&jTl4@K4c1*aH_ z77&Jxl`wdqZb0@6-dyk7f|aPw%$rCmLvs@z?comT^5j>1WM%O5N%X=<{7ObzBi8d> zL(z4bm}zf@aeP2+L5W6-gKmP;0!}hDEy5cj_l0hD<_`w(GE;H3ivJA7|E0RAM$qf9$8*^_+^L^l$@y#;f}rxI>9IJi7GjK!y*tPn0^w;KfWBT~z^pPXoL5xNlb z(Nr5nrzDZ*AIK0BZKP#WhZ$EwieTyR2;N3)G~`v#z)6>g0i&1IP%VnjAJ{SQX3-QW zjPlAG4YNMV4Gb$Q8X2@1o)~bUvBl*z?Bq|<;KGt)%6Ihr(+u(ca8PQXY4E7_F{-qEG;NAr&_&j_0tM?DKUQq!dIb4&b0>r zF>9FaU|cgyNMRVCk`9X6!?-}SdN}+QM4nmkwAU4jP!IOF3l0$zAvu7nR|Qa2m`<} z)4pX9Pmn6JF?qola3`yuG!q{{I{=~nbz9`juonT69C28xtsE`U(@a9ltHEAY-X#th zll9n5Jg@XimzeV8h&gpu_chm#QeZi}_zr1&$`;Nrj;PZSHmz>&O}|RMwyjRjM)-Q) zP@iDOlq5-8qW0Qu@ibwqv1Ey2d1h$hDh#yNv}|wH`GXcP z{K5)ghT&cRIHLU#kPW1Ytf7`}Sf!>MRfIQXcG29!U+*YPq zXyoVRRVA0$;p=M4wK+TksbnRkrQ|rYCmwk9@uejA_hJ$xkEI>xf7Yb=IWIQ43RHfw z$5!YBa;>T_A66~;GNO_R;$_77pU0VeIK^P|TNaU8v7)pj`3m})d|3UgH==L-u+W~a4}m6Sv=h01RXL8P&G1`y z=~ddL>nAZQW+PjJJ4;;if+f4%744f1S$dPt3z$-(6?6JcSNZ~-jU$FFPF?eER=g-o zQ#G6VE0Hn<4e`O9nmHMZ@tId382S(xCnwQCbabGGIe=ks7K^aC7@Vyzz8}%-o2OT) zlFBfnZo42m-125cdLPL-(&DwahH~ME)|;#nvSd@OZ^@dY6cSGC7_WA%8!`HtYq%uq zqm8J@SLZ7dCEqL=U|C)yma3XLd_5{_!*DahI4I16Q?)ck0E$GEJpSSE{y6@p*n5$# z=s^lPR^QsW{wSDl1~GeUu8i55A0VeJ+)M}(dN8{JrKIJVmdKfzkuIucRt-jMky61+ zC`HXG5V%J-$CcnF6C?~>y-k58TOWH6N8^Y+@|S}$oxKg?YAR7FbZNhxiYB15!;EpR z%2BF-({owFEL>P>YT|K;QTk`VxN%Z=W+lY{HcB~ES+{(Qd_j1GRay~ixdQhhJB+sI z7hUT!tO`BNCLM#%DGK$uHQ&Z1oY@qx*00AiLMKWQL^b03?RTBiu*OZKf$@T!kT^pzLI>}#-%`36i%osOq zlyqWi80}7zX(Q_GmY1b3F(2V$4<%!OaM0w@sFmzO)X7qFv<3gV1JBt?iFZ(faXK`t zs>Qsiyp03{oh!P!*7PQjCnu_8il<8DBfHI*tk86Ti1-?NYQb*s2tyy{U5=Qjz#d6Q zV{R$iJ19}9Md`Cz&_q34#o*UnA(@qGI%*I!lwm3`Xb{kbY z5t)_56BJ^vXfy}2(TD&R%%d0d7~WApJ$cJ1$9FrHmI?*)*Vs$eZnK$e)SiZXlH_3< z=LXyA9T>fevS_1md14F(!!*3|3U_}sE+zvPkw#p;kws>E?nrT+IWYw_>1o%oYFdfK z!AU7BKAzDO&5l~~rskHGM!`sdyw=75Mo>PdG)_hAhc3Afk_r6$)qO68tsTuVJIBkL z7)wNNO^1o3EaDt76h?qWv5u14ex?Vt0RazI# z=gC`Bq^V;LdheON)f?KH6EH|7cY}z5I4VkGOM?fuM~g36Axs5zZBk)rt9Ur`qQm(M z3ECNxo9gk}#^NJzGP;#fc+PgSk9Go?KNRGp8})e^f@?DIa6+BjP`T$ z{I)_aSSxB}!olI&I-XM*iu^SV2YE~v-KK?P{ydvCdb8Rsi5b36?U7B%jo3w z>RXX~c(ZVTczDbWXe_>uPSjT*-FsN3TG1U5+nF6Whsbe_21|LY3&`(IdT!l{6Ox| zva4!sU}sxtY<=u7_?orvIN z^pwx4)4!nfby+Q*`KJ1w?E80D8Q$676XgyFZQTAOx^D3=d7n&u!16hg4iI!wW zk?=W`_Co2-=d+Xmdy@JN15E>9wwx(`xI(sQV#k`Qz#Il$d{VuqpBD+rn5f`2y&o(r zER>UR|K){UR$QYlR)f;ASr$w=Z@H?pK*FcJH{$;8O1R{UI?4*1Ba1{kcHsy_k0P1; zf1XWA&NGrVSdASvW zfBedO^MAa&iT~wVuxN)Dpt29jVtKxCW~4QIAN5KNo=qA)K7!&E$+TY>YMAqG&m4(t z!WHfZiOkafQo4fwiyG1Q`A+XW(?6fL3?II0!61@ktst@zLQY3^yTp#R6BUSQDI8K7 zSu&v>d*Ay?_eXEu>J#IeMg4F=Sq91RBR_^fr$|SIMkiW>K?=(rWlqyPf5aIwL|S7w zR_VcSNpP&qFMoN+_J}E8a3s(tW}cya%}yQ@n1o`Gksq{&{w#auA@9Z+dxz!?1c6(Y zNB$11Ew_y^Fl2huWOaz@zK!cWFTY9RkLsr_`}iq&92%Pf6(*Z<@c;@HMjk_I^xOV| zx1r)van5M_Q)h=m{s&^Kk%_1;h*Yk3VsS5s39RiTtl$1GIAD2M@8{MggQ-W?+|c{2 z@S!GkhplT~p$OlOmq)ZCdl-4t7HldZ=U-6dt`MK|A50zuCL^i_#wXtzUlLXRVqkxn z>!>d2NuLRt5qzujAvwR!9U)2i{4g@p|in&(HKiETEkqc zlMH|lL37%E6sAd7>f{4lP^ENuu(CvbxuV@YtfyVR2@;_fU-G*__>T&w@DD7sY-x{V z6Ip$bv^9H?w7w?_er<8zxm2TtCcGjPw?HWy3n*(G(0C2s#F+af9)##&omWWAcc*3I zL-)Bc>N69|>+T;eOIw*ReEdn?%X5ob*{nTMZ|^hBdnz@Tbx-6M=$WT`=Ek_*jgQQGZk; z*`GYw9~MoTEC7YkyffMP=gi&9GcwnW#vlDD{){%MuD12V@E6oP>w`ktM2b(aYMX#% zGGGi}KO`|bo?QZ_OcTJA`suWvE?jsBmavQ(8t_t^%mL+$Hj?v#1qT0|@4IR<_ptUO zZaw#*V%hhJ5|EBKPIs%?-GJf!W#>(YnC?l6Wt$AwoE1-tjr{%^x+?USw>0%$c5b{K z{cYE{GD-c3PGu^v8x9IXk#UHk6tj6EO@dAUt}@ge>3qv5&tDjV&+%C}5Lcg6vO zVKcmb{n8?Bp_(8Qm$lLH#O`gApIjy&W}sLl*_;A0nFYSKs3gW$Q4LQHaM zoQuE_GRbSv;qrK0Q*&2p^N2h1(z_s%^^}$PHwjKUH|}JLb|;oea4sXK2wXO!+Et9g zVizTcOEbcGE`X6u^wk5Y6$Kuv%@W%N*_;yPOZBC=fuoKE;xXhg^}9kLBkxA6H2Kl{ zlE||bb>ErGau2*6I@v%^bycBu1AB$raQCig3y+QVGHOMp$;#qKG%_nzDVKadHnSVQe~@|>Wa_T#Jj}KTx21GySghcZ8^w8BY3oKY_Xb_r&BBp3v`&gY zB>jABxHY;QsuFWY}0G3CXt?k_n~p9EFU{{#t9Cw=0QQp-1S=F^&pY2^)cQbY$ z;D&x9+SXnleYGwqB)}+p`}gb;9=3k`TsZ%$s<-F!5;_QHF@)vIxKMpaYw- zfUj`h2(ynsrP5$R#Wh4=?o2b#Y2QyCoC!GQx_OTBgA-ML58KPWY-VsoW{1 zo+=8U8Thx$4eYZ3zC7=zd|qP5PJ=yBn9==W)z&Ctzb7V9sED z8wW!c5j{^1)_N)WLNscENNF^*hJLtKU{NS)1iEszPKK5ruhEun9_ubf7H@JL%W>x; z@wq;7pF7%uN;fxF6>P11IU`_nB2Alh@&m*{VpJz)^i3SOasgY)8F;pK7O^23Ms7Jc z4zW}-QWPUpvZY+$j^7;PxUTs_)5(?V>UA}%8aSo7YQK}va4mJff3+GKUB3i~LYgE} zhuK6uJgF{Sg6TvTOTHgW?y|!tni4W*DVyOiQl}`_Q7~5JLyonNQMJJg=+CV-@b}rLkHhw~}wS%1NGrg&|#njScU`FW$VjLvUi153k9{*6A+> z%wiA?&>>uP78#e)D2!E;_+wKNT!2UW4R>GY5ZeX;@PNX9_iHWeg^NTaDzb zw13@zz}ydB!nvBVc)zHo$HBO_cA8bmk64+h7wMv)Nx!Agu9LI)JS5-oIbwD96BEmW z-W6RfVS#KUL+kLm&u>QXr@d?O^!y>xNHDHPG{znp`jJxA0W$v8a1c;x3E!tmQ)AY0#`2#0VjKz(t zJ!%iXa-poj)Il9v!5}b54LNvdCwdvAP4eu+4>Fl4CP@5te`P7+5?vH1(I(ARnT@br zE8c=;<=}Y3n9|YGVC6E#xYj|{p^ea7vH-nZI^3xo z8poAI@2}@*@1zY*GP?fm&i@n%j5UCf)_p>C)sI*RkcwwDc$A2$mSaXY8^UN9TNz}- zrBxgxG&QKbgbhy_XoxWxUJ+DueB9!HC3-zrc3U&jtm^t;x+yJ%S?i#_=#+@(@^+!h zKc>J|v7jbJsYorGJzag+@UUfx&vB)i(6V?1j{!@{j#!A_Nw< zH#H^S@N1;#F;m>m9-P)mZ*vrxi*EPsuG&o8ETnaVG7mC%qJdeKn)_;;!A8NK`DR6hJ;!)O zIxedcG~sW)ma>(^>Q)vjAHlPS>I}<6I|^Z;jLR|SIPsU*^^v)E=ng44m-PZV{x!L9ww_iP6OzJ zCY}gW=0u~y+gId_l|McRMS7eRasi}T5)CfXlrY9tPmyz3o0n0aR0d!vh*}zv4?Bh7 zmA(|Cs6a!b5!JfOEu1|Rvy_d|BNLO$*3m+HTPHfFU5*qpR;sOP$}Xx)oKeacW1uW2YAj@=j1Z%Pel zyAhjXA7l>_AIVjL--({yUvR}I6<#V>K}7azTGQdWYlyZpNdT&8%+|O(MDx#%&*0Tw zAI!|u>Fu|&=A|3gg%FF{q%NN{1;F8IMwd-gjuls@#YdolZ1sLucyuOcN3!nE%P(vx}y9d4U-rm7jg6$SnKJWaY`j| zF5^ek7!IGR)f;*b>uh3{^=v~j1q(sNC%XK)TXLoA%b;6C6K|}GFZNC(9LNJ3$uDRo zcW#$oykB;ol~LkCogdQ^SRc>wjcBsjMXy%Z-%{u#=*h^}vvcqnwIuKw#~W~KMOYTb zJK)vqQgZ)SF}$nZf5iDc|BmASzi_w-Lj?=X3LQ>G{Uo*VExq?WdT9F@kv{(@V^3;o z5>?FE&(#(cQooBEVo|yUI!`~|Fwp{)+0quvnh_rnc(o*ZppBltK5Xa(1mz`|fsnev%}lFp^iHvJ5v)xnC{ z451>b^7{-o3XNM$N8HBofRd7A(PmngF>m!P4ZE9F^CynJ;TJ%)Drj}SHH{UyTc!eU zNeT@=Y)?_gjP2?co&5-EXtM~zhY%?Pg8JCd_o&oFW@q-Hn$V}Tby2P;pFhS3X|+yG zQ0uK=?2LL<*Hn1phWTLU8=BwppvRrH_9g@`5)!;NXH}iEPO;{q&)b78dL5@X?esE({rQ1Cacb5xXkw_gfw zl)E9^R!@*eX*;E-1skE~__T?hyJtM18^q^1b8@HZmNs=;E_hJIN^waCkG{(`8nn*q zE5{lWEe$rFFvSc-d1JpYXEdk-l4Vm?veFgV<@8bJwd#yB0j(xi{v-D|q+11+6=`Q) zl0bK*?de7dfiP8>ObbKv8e(?FdWQfOVPzHZQ3+vb8l=xw(&yqBGMM!Xs_-&Yb1Fag ztLsZV^53YI?U{_gQ%D-u_Y9rxe>^RBX(wyz;XNQLR=lqW)sV$W1IyZ#)vH~mMuB*v7`ObQ ztb#pq@{RPW_>E)y)rV_U2P5&J+BKJIN%t}!S6q_tC4faX0|naHb*b&H){o%BKJwg+ zJ@Hi6N2u9fP;_>=m7WHAsVrwN_lBukv80m^$>X-ZB|L-WKE`L8vrD(P9WchyrybYT zJN|T|j-KgY2XuCoo0J7caeYpCG3kseb@Iedn;Mt0gvC_15~9Sek6408$Jabucg%Ji z39oBU8FG5XYYKPg;8Cqz#wGwwP6csc$(1E7sj(XBxt~k66JV9@nl&bi+y!sG!^l16 zw|}bM{f$$S7Iy>q71YNU!69g2b$@AAe=FbuIT%Qh?|(J*i>;wd4HM?xYPJ)kR3TIS+VgJ zv&lgdu~R|{8QsfN5n00}KsK)eGN-S`_X3&5Ko^G>q``rQflbf5iU&`bf2VE zsFfZ_$BX|J3AvQ z1Xb34L1|oU+wSiHRW4(;?rW1A*7`Qz3;Oz>72AC@Px}tOyksf+DP{kpH5A;E8t*DK z%I|yp`JL_dISHvy&z)+EAcwq%o~I|S`p3eS=gQsQwXxy$!hPcIn-4_X-|u2kbH93* z>*fAE!5Bgh@1fAC?*jAHQ&DpyIGY9%3#4=}?dU3g{7xLXQ((96@CV7U=HZ}KETTOt z#c^zs+e`i1$KR=kY?54TUp=C_GCJ>a{?729rrT$a>hb;OGkkk;+eL=SZyf)L`gTib zr^m-%P%s;^>pvy{zscxNiEwJzD5f(M6%-ok@)gj5T)!*MZ(8g4;9Wn`;!Rs=)6_C+l}qmh8*hy^ zKs>ezv}#XIskQ)s<9Fr4X3s`ZIA2S*)?H9y3`)B$AMpiR=>~V*_cwm`$j>*Yql&RK z4UpJUmc=BhZtvkfF+8io;|nmbmaS}Dwp--Nq}r!A*R+|Gc?}5Qm>$cEP?&>9A5t%t z_mpZicEe|M<~nxe!!~yuTPC=LzpT|yc7#%BLuogE zRdu0(ME_0)gU3!WV*u!s2TcDvHM}b0!|EW&Qg8>mYw>eFSlP~U7dEPVTjW0R1_NZ^ zuJ7JfWTu}%T;#IdSW{vmDARYcGF|6&*RgH;APjhKVilrUCDZOXwFVEg07q3N*ph*+ zCf-TSCe|!Yd8M^qP+*Wu!Vn<-Vl%Z1Wdr7$(-w0Ht{CeT3`b*>Oe-eDuo&d?dX*aG z2=!_(bm9vq2Q1Sv&x<3xa0B*_?ZG@~iqhEqr47A9Eec&6%%qC zMJatOrNmSqn()MeSV?}eczw**f*T4bu4PAG%`~Xm zuYhe7$0bk-pnpNVaZwZL-G{tp&iYMJ#}%(I+iSUaD+<8`ZIPZSM`VTITSVhX@&#Uz z85HsPN`KVxZ&)StLA*(Wd&aTkC{iCD6;i@UR=2)s5h(PpR+p?F>vE@ZkJwazEDTn& zN!0`R@ox{#R&IO~$mU&XGX~La6IW5NFpgDqzVz}VDl{f#vlBM8ink=ngzUJ^+fURM zSl!`Fnkmpz;cUiD_uy#uhm&u*2AkO)FMNLpu}Ud15~JyC{@At$*g zwE)p&_9t@$5`HC)cE^Eikfd8a#I%TS44 zKqX#5r>fBo$J^s)0{u~#a`?Rt*KewlsUVamAg4NaEyF!#bIzq8CpGORBr$8GK&#Lk zDqc6u9cjT`ayzQooSv%H)!ngjLd@r*lL3bl&l$hU88yCqWvkCN=G1PNj@^mN!xud; zMi{;aDz9a#WuizH59GcOBR-v@g5qW8K9OmMB9Ki4rA@~`Tuy+33#?c>p5xhex{Wwl zk?zGFln<*BO#Ar=3`LR$^w1hwGRiuXc?My4bGk36b&C4*4|bZnI3A%L3bQeV#@Sf? zt|XG89mA!dIIl#sy?BkbSp{Pn$Jb;PBS|rQFinrYZPQmsUH$f%MP#CR2Z7o!{4(yS zc@UiWoOd?rsWO^0$_u{D5)Rr(Ch!0lDn&CkXXs&rz=N4n=IZ^0X5`kDjl?;(nk5r% z1P_;NstQ|;=*?tTvvOP5%LZ#1P|>m0y<0BzJkHBM&MqU%fb_;J2Z*+z1(rb-(ES)gB@51Gsg8GsJ6GFNeB5$c*^8KNX|+6 zdGM5_KysewUYptDMK=G4vTnfG3;-sjXM2@F6|lL;nFRWA+1bVCFg~TzYN=)0f7Xv{ z!&s8W66PO4Rsm#3mF6WJ#J??Ex&?o(<*M!xv3?$0KCY?^b@R5K`oOQ>W48HTJDF3B z?>Gz#zEXxNOcb4Sj{J>k2=F(xNcSPQW^``2w~$c}-zapm_2=eKBu=~yUyNn*k6gZZuToql@?a{BTbB)PHGR&daObBSN1kxz%@SiO2P9 z-Dk_2V=3vK43vAB>>*_d!WS_4e790mM^(p|+w!8q4@1fOkhPG2pP3*_2wl%{HLj+|HWTCPeUJI##AaQ)JF#-n(Y!-W#tw&2eAECC55(24kZuo(NtM-0Nn?-{6La(22_2mh069QM}+cCMnU(B!|s1GLj&a zD6Xnl`%lJ!Pxxjqum$6j$WRQc2RtWuU=xY$?pFt)wXJVvTX=DfIuk4#W8`rY0wu7K z3jIY?U9D=;;%8}r)Noi468)KSzb)YJ;pWd^i)p3|>k*Q4uoidy#%WAxgKorFzLooP zBHZS}$r{kiDSk^vpn$phc6vi+OGkfobL}|8$$@Z&%9*W=WdSju#D|*~NjHihh`&W` zp!MSD*2|?nC5$OF96L!>ib4kS3s2QMKf8>Znw@yTrD|!b`;D`5RRtas7t!U!BJ%qf z|6yi=z|;hWcTN<_6-yl`fiv|@~awjT*ignqVaWMw4CaK#~Jbg6i39N6rjBe5)2OjbUu{Pk* z%gH+}HHHzY0J+LGY}3{xd;~`J=;dV0oFm%*B9y0`5 zu;S?bsfJbW^;;zhWZ%8q=TrSe2*t?SA*O_eNkc0Ew59csP{g*3f7Bl$PihjO5-Te_ z3&$jnadxu^94?|u>l?1_mx>pbih~Nf+=HUrnJD?L63}Ccbl+p@`oq-Jq7t73TX*n` zz3h}Dsv-sdY!6k?BsJP|L)9uaKcz;XT$4mAi%;b$3|ASTNS^9d8OX1(Gh^MvPfbjB zI_TmKFFZ#4C8{lkAuN+i0~C_2q_w)n;lvf{L+iNO%oqH+H|w!5J!9RLAWrHTrgWha zrGL8l_#1DcH`y&$qOi>F{&+)H1e`oK&k8|?&@U*D$6Ur^-fy6f6#`BhnK}l|W5u!& zZ*TD_To&G4(tBBRP?#M)zX0}xZlLvkfI|s)%ai3H)^xn-0g}4-ZGsKntr1s6t}|>m zwZV9-PQHrT>mx&edVke144n)8VFc)0tL0~_t{bkPTQlO|G6}9WMwiBkk#(liLM}iV zHksDP0>mIvtw%tQn?SdP#V7=OK~WPZ1Q7|#*BKY-;X6c|W7zCsV-08@)P5nE--rlE z5OoV@kUYdn#H67Ry-YeuBzaJ-xtA<+PYAEe<`NH@w^x z@WTi^HOKm|^9#lnbidqn7E*S44=4blO#borrHcm5-`stwHlKg(dG6-;x&5rLNA3NC zO{jMK*~2%{vmz0a@M)qu%jyMXNaAnWa1{J!e&?k{`8AP#LQltHZ$q(sIkbOYQQM0q z`E_Aw$_EY)v0Y(Yhvt&MbWTMjbtMznv48J-qT}!m3dz;!VM{5e*rz_%;8@tZf79a^ z)MEXHG^$7D6zTn<5}G@ypi<(<2OEo}_BfIYo*bc@DtA?wO`5Br=jIr)Gr^C!vpc3`p4E-*!_2=cs9N7mG!LE6~yYSA7Ur^O1|03cD z?|8NM^L_H|ppSPs^f{*I?n{sQp?^`?LD@YVx%6a&MBU&0i=F?RKtJ)&RN~&H)*AlJ zzxW~kPby*jvAMJ(d$nMWlYdQ>|39hxd(!`2>3^&Df1^#0qZsco*SL(X_`Cn$_p z%}ml@i1#!rhz1-UkH136={(MCB7a^gT&!>kmo-Rg?ra*>a8ey(UmmHCv@wfP_Ijvt zs1JIxQ2@RAdBvSEEvy6zW_aj`@CC^gnXzv{8*HwrkZEpCalb`Zph5=|YNilHSP&luC9+Tz^oUoTH(a_~n&Dz_+WgA~9FW85SgBGC$l#cgCR6e-IO}w+9 zlW>i|H+!pydx7Ss>8a#)=QSp#DYM+w2f3x?bFRe35Dt({!Q_G-1B)wvF(U^3@FtGK z1*;iUj$>~W!l?D||K7dbp!`qYnG*AF=lL%W{eQS)3^IM_Iq$wvec1dVcka=>u=B7| zN+ooOo4cU@3+fVUqTW$MoH4<=gbV?#y1&5i2p-_E4l9l%D1;UZe*g2w&#TcBMh-IR z5zK(F@Q5$lkrS`Npd(h)u*6~e#-W6HLpM-y*+$RyrH7Go98Hm&Pbi54x!UK9ttf9~ zqoz8>bGnuv{P!p8MIS_-pr6NcD}4_+U+Q+EU$Ac;#WJ8;=%2%VeL)cTUr^3U=e{SV zPrCa;o7$vXtG}QSxPL*NS^a{F5_-mQX4@1s5AyoSJ_!Gk%YO|2bK|h%+bN67NpMT6 zu}SY2Mk2r@tc|Bvm(PaA^h;NWf6)5L`baMHWd92)l=GXug*eRJLC&=A9aXoYkCIES zJfDP49_l(te`@3^YWH1`@7f(l(-wSXZR7Ug87b1w{KIqjb&=|$s2SqN2Ja45Hn~HK zYuOuPK0h_4u~c$WOe{a&Ei8f0z8+F%W(`HolsgO{&t1-`kB40=wdsZT98Bd((qnvX zk#hx36dPP`7xKh|kj!8U$7LX)tgS-sLvh`v0^Q!(jC_ND)T94>bH-#wgJ&evlPjSd z(!EVlt?odW`^Txn(4RaR<$^1;r)xh4U&5rMzw0*kAHCoApm)(pEn&`MIEY$H7}ag1 z1L>{EHCx`LNeMGWS}pAqnG^)lX`$$I+HLAA2^R30Z8S^JMo<*gppna$tJhWmXS3g3 z>I&kl=%)HY@oC>C8$nh@ab4Cz!w>adx$ISqT)tzP~SdPJyQ1`A<97j z{UwRp-O4YB%}wuc)*)+W;;mMzA6Xr3YpdA6_gyKhlJ*@si;k78F%6qrb?!JjZg~q& zDWWV4q6)lA^a}KJJNx!5wC|d0>=g0y-r00J<~%1WlE8!d3Hvox_6$~+G7&}>NnMsp zPmtezV)S$esMryS8!+?J8fn-xwTa_*R`-I%hdX4qV{<9Dmd0MXL2%><`$xGu7k_G- zQ{j@El@X;=287Yb@AC@pvBm8lsGuF8?PH{M{!HqjMuUb%dN|xW4+d?1|JpuPlF*{l zI@NSyiSqsjr1U~eJ+yjI13d|&Zvhxu)zE}43IZF7qPQ&m)w zh<=c_ty#^FRsn4WU!8jib*GPv9rX^ zHmTm#Ove!rh64N4cMt;^V~J95XO>2ZRxB%{3=o+&ciXrKU$$p?y}MWbKE@ zwD=^xfDX@)3Bn@RiK*yvx1Dpl@8zv06D&k#=K`Lj@?SN7LD@DyvH?s>Akb&FPZJZQ zXR8M3RrEC#=Sj=i2;d*oq`( z3$4{liCb}(rl4dkLy-x^6HKw<8g~wfO!unBf-wPSCmi2q;6qoxLAv8^7pF% zJi{FEO9;$RE?`XHX})#|F5pn9yx?M@WJ$N0CnnU#D9+#uKQ2-v-kZtTpi&Y>ilcgh zzM<=pwW1{eKIai`6HBf%?^IqpN}R-)S%Sk#uT0HGF9NzLu88rgaHfdz@I(!2HGpD9 z5FpG64@m_h4CNCC81@e5GUJ9gya9K`+wMr{)cb+5y-~?V{rY)4J~hjk)T2hnHQ0JJ zxmIKTf3WwKL2-5K)@WnF3GNWwA-F@(#tGKA(`e%^L4pMucW8n)?(QVGyVF1tEI7dv z2zf92)IIy`@0@qv`l@c-AGhxP(N%M;?zMVNsX5mi&ojm-n0VHZvZgL412@f|ocXes zK+nZ;Kg>$dZ5-#7Cml|=v$h~yW|(8m;g9sxVh$bLgjWq~T~10Ls_#;&3#?U?hw`DN zQOXs$#^arCPL9$arDRVWS;iUCvd(d`%Xu0vFHlgjLPMnYId2K#e{TliBO=yO*G%P9 z8HY65@b;(Dbcht7B+qr*qGT6aIBSXna29dU3kFL6C8)2z2 z*=8KR(aNgNVnG8qGm0Ve?r6m96IygXdKtW9o2AH|PjfX|MFdRNFsCz``dy@^R$+1L z+vdh=zy>8cs9K{fm$rr&bVW?n;~hRda zh^@Y@#&-_#sz&l!gCVs2^O;XWCzJyR#yrwSJpoZfn90cvqHpZY#?s67ng~>?s=br` zym1zPH|9ybdeDn8(T+xdM4QbtK`T`g)qgkncj=SCJLEqCTdhbcS;Ex-&Dl8&B^>xX1k8SqyX%=?Lf^% z>Sime;mzI#a|a}o{6#SENMEHa4K+H1cGv6iMW*s9R^fBY2b-Cq{e$K@`yZ=00Dwe5 zKq~{F^UKWe%Zwk>3RZiexmFp!Wl){Y@3oecuN&ri z_B~to8t&a=TxU|F-T&O=Glm)@k*s1a!#KBxl7kmwtk>WOTPfWVnYH$cFncWb4_lRF z9$n!fyQ8$QbRu74iR=O`6qJdsw6BdBPJioj0(qKq6OSJrO2jDj*q!ueQpl-CkfoFi zDN!54QW`|dmR5OqI3QtyNrj5kr2iDb~oE{0~ZbK zdTzudM1GB6=_9`h2N9-zo77HTbKA;bw`k@LOKqd|?MlKL!JRkz_!ybR$mg}^R54S?Cn>nE0@&HwlB2+27-zExi-#W=isVu7){p1>%3} zorb)AO71u(t8U-=-YGi%9IJn0(`;{co0khZ{;u4yCaJI27X9UYidrn6N6luvK}_rl ze&B+c$cn>R5DtvLsmjXGY@u-sojAfo{?sv$Sn1H_k z1;aak0Sw|U>_?pQF-rSWc}KnR0?29n_kiNl7SIF#7YxaT+h0DToOXI0ymY?@x#LlC zgaK%28-9M8r8*WnP5ib}Px6>mm%WSoY>+4Gy4M<)HNpN=fktD#|Hl0 zHC@gQx`sj9EkthGnew+UqJ2mdR=2PzDypK~x*T;ZMQPk-3VQKoy!vI4AlK?19*8Mh}Uj>jhCEUR%>(3j4r zyB{7;kZ^;^0Z0f7|4-FVc)=QVyLi-5*M9+SutTpy{}4Q`XGIPvkHM&!8KVv1Xd0w1 zb8%vI2}xwMrrw(`pb}4k06WQKh1LZH3Nl`g0wE)cjP?^Wgyz{31BEu6WEf zSvrJqGArKX>h5#M4$^&uFe$&IA*;Jh@5B9HfX!f1^?{X*0j{nwo^LihIXb-D%QrHm zBI>B(sBG5+m;OWYS)1bvJmFPbsSu{(+ITrpWhnkJoevSic#1W#!Z`U6o1(Jrdxi0j z9{_~esG)T-TH+rHqyu2jbDPG08&CgvSPJ>l|Nbe&{(A6t?wIPoq{?1{SP@K5xuK#9 z*(3bW=R2_f-M%U1d@seWkg1rEBU>5$NH9L+k{5{&3gBpUt+I3{jEP14?2g193Bb{Q z_4mn2=@9$IJbI^;% zcWn6M#3Eoi5X)w%Q5ClL>e(m@>C7hC3u%vfaN|`M^;4h4Vsal17Kl>Nk(s>?z?yh`6Ku9ZyR9b|3Cj91L6Mz?O+sU z?x(?O4qtO-&CysK$OC$e4N7vZs<2oxK;bV{#~WC3BC%{Z_IZh3D)iDL0hSYs#HO){YJt;=Ieze%`l2tJ?LzLv{P%RoA0o0LRH;huaGE z^~*>38`eLm!fsCoZof$S9uhVRmeelpAWz5JCY&bo_h>J+s@p(5d2R3Cg@+oo>x1!* zgawjyV&eQR>(asBs+$=0i7@f(&b9Rb0V#4xN&MMsE4-IA42)C+aAy;i#wkkH1!4q0 zINZg!o$lkPXbLf*21D$W4W{a|{!Kv4%G<5r8p#Zw8&i=Jyf;2~4OgJmdG{|hqR*V_ zH*%pzjCOwkwx2&KZ!5McpA`E30@!`puGSrsG=B|w2D?OVZ2oQ4LN{I&y}3zg4!sZv z9V=gQUHVgO5!!5V0jk`ieM8p%98W8F@W?Q^w}8B4HVY=heHcvo*Jn9)FSK=&qlnO=o>n&o#|fS45&Tb<>P|*@b$_PHxuE|NhVMaEAV^gzAkgooc=Of!82oFI<_K!kf#E~ zFlQL@zdY{#uq4ioT#ofvICrhta?u8CSe5kiT|9S4(nLU`eML;&T^ z1E{raI=hy_S7up(SkNwnFmHuwLYf|!KMvl5iWLjCQtGzeVIF^$O>#RF+Hhl^M+^%=*-mP z2Sz!uHctP(Ykj`leK>sk#N_zj(KFQ==I%l{Wwz4`Y8LJ(IeR?5Xa z9Y~QgEa2bl`Oj6+=+NYK8`bN! zt{|sw*1DsvKLykm5bl{=&n!&b365@)nZj7QY{pT#M6i+rJW=t5h`u=FN&GK>dhYx! zw#w-N2ep!yEc;_ud(W_S(9KbGK)yHC^a z0r-1#$glk0S^fPgTW$CB)h`N8kMAGl6Hn|5ZJ<|ly=85%i^ zh+q}jrW-4_LLiP^zsx&4_ZkbUvtH;d2-+=3RqJz6wu8sxz(!4W^Tdc&yZJ5!#cuuD zd3HkAEmU0%CT-`6MK|9s7e&wtQc;V1i>Z=nB=pVvy_ zBY50le154@dPL!{plXZBrlq>W5s0%Jt=tgCai8<4>T-0gcT+nJ_$s<=1L=EyguX4z3Ed90Rg@)$h6nUF7ZFup zJry_>>w}K%#tJFTO6H%UV^5sK= zX1>7gok?$2MSB}?tB_Wnm4IPbqLt)`M3cs*kxDtwf$5bhsbc6nEkEy@Ly!9a-=7N| z-6)M6CA#1dm$yxJL&4Am-CHE z2+MYu!KAXE!-dpLJ=8{8YFVDdB${em4&?IG{XP{^3{051_6Wa8-A=DsnP}8I!EjXl zZOeX!ZanU6fHBWSl=U1GsODQWEQBQ`BqwJ)v3~zdT(p4CE~73vMF*gv-$R=E@-6^? zo>UM6kgBmvTr8lqX_o%&cQroDnN2&Yc60Dr(s@eJIj(P~{L|LMkCwd3cTkKY2ppS- z_SS}krrkRd*D><9vqBRg=zvu8XC#$+Yplv)%`Xsf$Vmmo4*(i~T?POU`wyFdpl6tZ z4)EAtAodS3+kX#Io@5`rxU5&BV)&NUVyK+cY2VNze zpsuXLyj9{;^}xT|C9dVJ{dj>%;RiiE5HkL)&WR!?;%K3_plVvC+{MA^qvE5EwOW+n zq*)r}Vd?ox1kaq}B#oe1fW6BjUg!VjrXv0)!87)P4*(Dl5bOb-gDM2C@B!#;qNVS4 z+3E>;e4OfNbKwUF>$q^Iqk(D0%y)6?>=aQ5?;x$A{^1mZ87g5S;;Jsbz(OLT0vXNh zS7?i-K}+}7WEZVIRqdAKMe0nuOVE^rENjrGubEyXblrY%*P_0;IwT^-6;E|Nlo(!pN9SdJb^k! z^g{pntI_qY@8?>5)}QKj_aSeeEOuUA1oZ!y+>d+nTn_zHwQ0i{W$)JsI@YL}LJ%~4 z=Lqh6Ppoc&`5~DGOss7VlVPCYqyN13S^!C7vRGKKjD12k`Li{3p*49ivM%xG=a2l* zKSa>zckpQga?qwkIE-0l@W=_GY1Yvj?r2M93mA>s?zOhq9ZV$PFLW?$XZ2-Ir6R%9 zwC}3V;%#29DE@Z|xb$tmL^GO~ZE(S2!fLfIhNjhmuU_zjQiF?UZR*#Z&0;?I?gLcV zGH>@N#>G9B>6ES;9m~9mo;@iuB6f5xL|nS(R0i$FTzudl&bHNLV3%V#*n4J?=Yfaj zL$sl@2(L$K-F$3Trege11ln?ZBFG!++S$O}>jGQZO|Z=$+9)wbY!~%*v^KuB_nc=E z@u=PVA%GywCkaRv^q|mEAMfD=IAwAT6NYeNg2Q4MV8QDpII~3LHpyJM75iGrGbGR# z{nhsIC0_5mKu)mNmadN>t$i}|Nown`MM)eg#=& zjL?vZ@4PqWgsOzHUMec@5!ZU3>j1%z02;dbgaxlCL5j|as+1#WRBvBNc9DMCwNU^|nn1iloh z4&nDmWfDf+W}B##FDFg%x7|TG0$d)K#=JIB?`>YylfQD&QaAZZ*|s+E8foNM*te1% zrRc6^xMl&N*mSGBu3`O60rKEvN88@O9b>rECsH*rth8RHRSTrY=3{uU_Gn(2*5bg` z_ce;R?3DFn$_*>E;0jz3%WMenUO!a2A2oN3$;lMbb z_RH=Zf^^c)Okl!iyVhNylf3HsT!u64R{4U)jqG_nb~6BAvy?(8l*|-Op;t>;S@7Ms z-M58f_1yGCj`s=*Lb#!E+~C{DmeR@vZ-)+5*RGB?S()k3)DL>O+*6Or>N1W~R>V>t zD9nhg3Q3*8ovZE%*xmOCcl`*$XN>;zi+~LC?#xxcVBpgW?bUWP$248!9>Z?uVHlyU3|RMF6;^*ln5IQD7AJYCU@)kTwM9ev zSgqSpL11GPd)$k<6dXK=YE{Zb%1$v*w26Uu?5Maw$WnVz#bi?G^>{W%#wL?c4FCrK zY89p_y(!(WCedlsEaH#Sul19==v%8MS9VU7^|r?7x=Yh9sM^>k1fUS=G~Mwr(IDbV zX2YBaR<_=_qj4c^I~BH0Y3GkR?w48#^;3p-w;Vh?%jOr(*tfQ-%|=+Wy!7^})jB-- zm(Uuzd34uDam`nu9r*l7q5k8PJWXacl$vE=M@r^+Lo+f*ZPa?oia7tVloUofs)|Et zUlrSXq~aSruQDTMt$pZg%d|02^|8C6SX401VG(5?R)&BTwOnHbLE>!4JKJHK(}bpS ztWf3n29RfRZ5$=KXOLtjM61~7ZlP{|(<~3iLj>?)a zICMP^&{YHg*Yp7(tcDgR9}KAP}ymM)ajQ;;yXDVl0=`vvHshSi1;XB zyy<31kUP`PK!1MPEk74(w{@y}f3_(Il*>WZ+lDK8r^E`4Ol zTyaTVuHDcp0Q%=+2k?|DK}q~AqmQ`Y0qJ>%(9Ir?b5SF_EAh(s52CTvYhwf@JxWGQ z$|W2#@?)12%UZj*+39Tt93rZzo0Nn3UU*S(MX|OpBxwx z6oihgS^wsRS}l$d?nmCywmIKGz<#^ z<&o)Gmf;u?DMnoe1~$)`=tB$EzF$CSwhds8m3ecn6NVYBjX=SM@uT+%g*(7#%hM_c z@#*k{U2mCw$=wcA0`|xez0n?)9Y(gWM7~WXr7n0}?mw&Z&z|E1j_zoT)JMlR8hZcv zY}}J)%z^MNNK9Kj9#}A(9A_uq78u}h#ic@=DtgM8&fV;)vz4Hkh`KgS^nllAZ$gK0 zU7~KCiYg5qiV@djoLTWilGN(R%NoJITfWLvoIr&pHYts~W`O1MIqwU>%F_ls7_FN!M=3B1 zeYLhZ4wnw#hl@lTeS`|n7CFsz5aEMnyn5C;o@K99@Gg8Oj)RDRFd@@vKPQF5HM5&% z%&7rg;3(My9+Z3aR=5C1nNqKvX`1T@pTJbo_ntMBG_A*dGrQDVR~164V z%lCMu*Ml%JzOmfPi;-a()qRTeT@K~`nzeGHokWK`7`rx8La*)i^Q5+BS;G&<$3U;9 z)4%zjlNKyEiy)9+(FDeImmq5cS-W3YW%Sn;oQr_Q`8yo3Gk>ho5%C<5R)|gvJcHKd zwkGcl`(PXnD|kfyY@RzW_n8jiIgOv}Es+v3uBjy*KAzTrg@fb1*Vs)}vAxD=fbTaj zC?$+}kqo%%ai|Bnj@!%^J-vSQ$b61|-Mc0|1)4tieH}EL-+x~H@^4ys$%2rQ!AbfH zCq>KAd5MFD>ci&GCR>df0hA6SnA@_EHH#7#ssFmKgOoK7tnQMrRnew{tvtW?O%L1S zF!tmFcJuh)d|g>dM;2a~V0wyXwSFtlH>kCxHkmpFP5-`Y(A>|8iI( z6WsXy?3y<8=S#AO=3SJtq^-XIZ@xVHV!v5?H6M>iEIK8Ah8keH6f-VqqeJHDYZ4Rf zp_QL<6Utm&WXpxBIZ9wllJPg&WAn~!C#h>SCdkV=aCsjkpaWlCro`#c<2`8M*CNVYlC)sHkX!$-j#ZM#VSs5W3M zwhOeX%D0IBSErc>3B~pI4R(Vd3WbB<p`>qmB&tdkcfk*dq>ZS2arPZ_AV zC3^`v#@`_Xr*9N*Jr4zcUal4n*7JLLO~nyeMU^D3lbk2 zmdW*-TJjskn*^pI6HK{LRR-Xdy6RJv=KGQxB9Qlj|0W6Q$1>PNGBkOg;R72|w8`J` zZwx-i5TlMfqe-X=3ePByRO3G&kl=ahaGgbC~xZrCJ>k1?d~Q#Gi|2vwdemz|Xo}$kg*^L62!({NtBk4;zomUDS;!i)5pqxcYH@Tt>+AU@ z0{7Z}y~Qt!9YMliJ&)b!y1cFfsnqveKDbQDBvTm}$=GGB*A1P)nEK2#w5Mt*rrN3^ ze6GXh(^0a(uJMOYCUk}R3LgA>&oW}RCFn@!_TMm*>i##FNjbPSoDl})&_y`UG%lNd zp?NUR9G3xVpkz-lPlMWIR#HK0n&{nAPc+qpK{Z``Vq*%lH2SJ(FJYgNu?B3zIApL} zAMZrNb27@Dj~x>nYq`|*5Ey})U;PP{p&1l2E}U`bA+9^U$WZqiQ2Jg%Tt_Kd(Fhez zt%TL9Ym=w-N0P03)zj2t-bU2Cc4qV#$}H^L?c6>k8d9@8=DfjTNNrw=t65}YHR3d~ z!_@HOG>4y)?e2`oh?zFS7W+Z>iz%5?!p#x|;zZ~X1zAjc*MEKGeDQ}@Y23V#e{6PZ za#kG4?_fvD8ZFV63L10l%H+~DU!96d8S{pnHnu49mw%1H->P;;n47e?x7uyla;c~LB%<}&E<01s?O4V~#xtbWmBiI=Zyt=WgSN)*5GbVa zBxmSrEQ|ZfFVFTuYDfR8IJH~0wU>eumX;PSc8{mdEB-qm->1WcO((1(%QnASr$chhXI*!>9$S;J zQ0a#JdlF}zYo*qjT6>X#DP7TS{Qi(xf?<2pxy@tH9cIff9hAp_SJfW>QoM3Gko~51 zdg~s56fs+!WhX}M6TkE>C3teFAS(v&P}SF7KU-ZOX_*Y@7gF*ELvthNV0|28BX+_8 zdA7v+?g5z39QC5b5!{y54ax<>4k>2R6jJ%Rk5-OLb=c)Oi;@Bej+mmz<= zNv%HQHgqpJvf4E%^w!>@P0264b&_jYiLhm&uD662R8>nPb10{`Tcf>5!yNCY0cR|s zs`6i%V9YhHuJFZGGIH4&UWb%zBb;=O9D_XF1g|Rj4m^lQxm8Phd0zVv0VKLC01MxjWEnRQtbV^cb!)UjJvaJ z&aAs`Q6oy9`gqzK2&6SLT*tJlr7jLY z$6`P1aIbADsJE|O6_!-nVA-ucf!3X6bn{8nMpqFFrpG2{mUY&R%Io8@yH(~;UVqJs zk$p}mo67))kMPG|O+O{WrM}MYzP`S^lS{sjcoY9=b}Hts-a;W-xC`nNZW3E^6KCRR zs^;Z|c0IO0-jS&PuuZjucUpWPbyZU{v4Q|LSnny!XBo~%dQL=mvgM;`6}8I z$0Ad5bRBD~zg1)K?wC);>GwXQEbPo{c+| ztV*Xwz9iJ6XwHdQ+7XS3r2ENracW`GWnv2^8a`BsquMGDU;j+4(8TjAFP4y(V-+K% zy9m{Fj4_@=ZAOb?+|w+!ma03_ekJflapCdE#yVTDjbSFdc+{$`jd6KMO+isH-|XW) zr7DZhZkoT4qH~6$5^J4#kVk?j*tFSoZ)0NhG^Co36Ijg~pkSgetA9%pXl*Q8n=b(- zX{#_RDJJN7M|8JjqLwpCaD?-2ctC3RSOpA!hYZVuaZ#DSZ6f~AL-E`8Pl)t?*78>x zq)kG}o|sQIsEa zl{~^=xa3P8&ylj;MS;bOYZyq`cY)c~MmiW4pyET*VCTJVHo9gs+381NS~xNbT-Qqw zV5AEtHBiWKEp=HacOOP6>v*F87(!YJdX#s0+#XDCKM|X@o{(OLvw8<-)IJCYUyty$ z8I@Y}G|Kr?OGsqlP*yOhQv6zQWZ65SnJlYpVyAJN{hJEax33COK`PwvO$6sQ6u~%c zmt#q8xV^nKoD2kA2coq_SVL}Z^wugiA7i~w0*d^ppp8A#Vwjxlgp#SM`-Waxvz&W) zhIBXp4mkUO=2BdKQoVj%i_Nicx0{hm>$K!Ruo<-Efm`QA*%d~jF*zO1^fBn5DOR~A zXRBg=G8)RX#Zb0OXXx(I#&J+QvBC{I+g$0ZJMzGz>82E)}mns$8Aj)j+ z+uq1Rs&d6l;U9k5f@lM|ft!n_SnW1xsNi=(7-UO@f+d|PH~AUuVh%&An6;Y`f%Ak*unQ;9$w#4rb^Y zNGrF2mEi%;!ls+iB0k8>%-Cq&3K^5xOO2T-7^BtQX|U#o4l@Kl(RC&V$x2thSXN-+ zf>4&u%0r3RouE{JZK;$aJGh)BAyG^aZpUc9n-*inn+D|ivGBolc~qUfZSdQmzhkY; zUjXHK#yn^27jyIT;%$qJG&Oak6AQD&F84;{@9Q=x$IE6iy*D<=ehk*8!wBNjG}vRx zn^G}(`pw(_brKA{co9nBR**|0;VKmOS}D=6=KQQMb;Lp`6=P0=C5N&u-`+f9xMHHwvYMb64@dl9&hV`_>v^wtd2aRS z6rDWt{-FGkUOA}0V8r74?r9YLKb|qP;Ny99wG-u3=E9e;rrz2nV+EP5hYf)~LuBBi zWc-XCN7_oE5pdvv4EA;Kgtv({yeOZjVWat;%p=IW*tj@8|Tlnuj3mQ zx^u|*Sn=?rf(|+je_1ih8(uMGn=4*w1yoclX6}ck{%g|#$Q~2y;XN@JpGxJ zpV8C^TRn|=%S1IBvCMa;z?zEtz5h6S)Ab_e*O3V)MQzAfW;p-v(^i%pX#qCk5xMA_bpxyfvQy~c z9d#?hlq5qUgi5JK^Sr!uaPB#&CgZR>+_$ zVD>;Y;O!w|cYp)L!wvjj;D*bhqlRIeQJ|;P)0jl9SIv~n!A{%lby7D5tqj^o>O#z} z$I(ie7UgV*3p18i?N@|UrZy4nbBBG-dJFXN_SPI9pSbKT+#wPbZIoG9!gp&t3^1pl zT4DOuuPw358^&iV`!2^b6D1^awdF$O@sn8sGe~>yZMUW?LKdDJZZn+4bEJ9waNaow ziKrjniMb>{T$Z)${bo{wLsqz#HP&j5`R)`$w~`1c6Utg`fM0=_eeP+(H`rEG&kV0d zYI=*{Og;bbO_6QV4#h=k1tb3;^O=RS?mM5<1Xh=FW8qqe32n2waAiWSTJnWE9@`k<=V z?l4YSfRPpKSNF(m)CO(XF24&-vN3}^5>^U0tYSr__KYtG)JHih#S4v=^Z5h+g94&9VTLW>>Z`2? zGg6w*NWie$*L%A$r#zQZYv;haL9I&dZ(lJb{Oe{izt`2(?7iZ-w?3{kR6+x>j*m(@ z4lY>J9Wu2XRlG8o_HJ88<k6&M&DTON*~5`cjp9Qd}?q+}$S&?KOU?X)J|ghMWzMDO+MV@Xs) zm_!R-qo!7|O_|T#BwW?35{C=(G@;`B_dYAvDZE7;XT6O1S zMc1m#3i>MRIq#pqQ%4RQ@#JRZqKKg%xL@JOI_yk(ZcVt1V=5VOE2$fl9vOpb-AftF z*&r&u#9EO`I(N>Ri?yH_Z`rO4Kd2RoysaVrf6~v06-JwYADiL|e;Ycq+4m_zaOF z&n!W>L)KJE>*(|n-9)a%DlNT5XO^9_gL{>|jZMw`yADL7jOihn*Tb;>X8N`I_{ zky@?6hjl(aaPO#HkDSgGO2a%Nf)JaP{pBI`MbUXbKw@3#5kIUJh4P^CohWd!|YXf)4X0I3Cj#J=*5#Lv&)E`AJu`Q8OI zd3VW^^hv0$;2FdVl=@TGVtnjVFmXQmXK5uA*X((%3v%&X`d_!)&v*T2kk$Gb7`{pR zBWZM5!1!EBd}p^6_@N>A_#ccDj+`@1%p)qrmF*Chq?XEh5tq6mr*6_7@d+o2`O1y0 z{5pGpkXb^_1xUr|&y0UO% zoW8E!u(QJid+6bo*Kf9+w-Al9~ST&_Qzm`Go5+_qQ#!(HBOB&t982^Up(H0 zw9LIuXUpJP?*eL4c6h^S@QHtQ*V6TdPA#ZygPrG_(C`a;tEILeQo*JXNJS1(aI<2`Pk)OZCO=4sw7mf*|~$l4G1?6Fv|Jbl-__D+p&fC)*yWlGN*5(rg*)3xzH zMyIMri|nm-;qLAR%Q=bu!>^tj)5ClpipCJH3fBl5a+>XT?^TC{ZW)M-=GmWliS`He z^G-iNjy3TanLK$9S{@*tLfZP9jW?w^h zt8!+=4ihX&PPS;OS||}^Ip!mPSkYC61$7C4ghGs}?3w;-c8gTjAjxP@CF~ey=4T|^ zlArUVk#?NvS4m`)*t(p?453(hBrJh`E;n0+T?Ndru2jzOiz!b^1C&Z17uuM)A!L)5 z{MP)XMLXR>)ppyQb5$KR)LlCxyS=$d*of`t_7rRS$4p=Qh1Uiz%8iiouA8yy-mZAz z(}p`H_tGZ70ejRD8!z!~D0Jv#-{%Jhl&Y@&m%Ku9#(!bC2TgC=R33%@c$D(R+x}gB z|IYvgr><*md@WCA+M1F^3A4S6UY7~Q>eSdD@wV2Pc@h(B)Cff~*R<$M+Z6tz;->M! z?$1u)1MF;`399omthY0}F)Ipdk8+Cyuf@6v8bHEnF|l!sMjfLKZ5Y*??@o;K0w!)^ z{bPxf6Ox>K=)P{Nw#LWvvHSi{yyN58+=uVHLJ`TS zK;4~|n(FS2;B{Ii;<9IDh~k&Y$$YDJn=HjeqikKGWcT22qK4K=qmrl1e` z%9-pN48;SJ*;t%bOM2-*Q@Gx-(-dE_?LiMgl<)Tfh*sD5mc+gf7W8Gng$)QEb)d)h zeo$CK9+1(>RRi*>%pfvBBs?1uEamuVU^^?talJN?W=s{7qpZf#0!@bKo#Rj{DK%xu z)e-Vml97F z6JlJNSDdt;FKX>~A)GE)|1vEX9jwtWxSDFh6F<~|5FQ)oCT}g~m(sT*8k}C&Ng%67 zl&!E$n*&p2zZq9j^3CEa4oXjb+@dUi=NNDD5;&H*vC?MrF$u`<_U|S+=HdOH+#C1-bYp zkna32!W35jwx z7O*o$K-i;i=2MDfBdK))LpA{&O``ZhW=`@Pg%>#VI1%qw}E zFfC}R$`@ZLUNPimCCSuLR~3InAGzA2*)CQ&K9J~^RQkZBQ+W#sIr~5jl-Fb092+xm z?&ew51X4u#wr`ROI!s`#bYM%mG@@y^>i-NN%>yMOYYf!vGUj8seq+%8A^%JIgB{L7 zQmqX)#C&bZ;qpEb*;&W$UsV5ejPU<= zx}a(EZeq!6v8v5Y`g&4Ir-$ezghLkulk1qKcR;)yf%c@MvCE>vLlqh4hfZGJ8+%M} zjoIY?4R!=)QKSCq+RIVb-r&kE(V97>Nmu()_@hRkr^nv4S8_zuWIvop&` zW`t0&otS4qmjJr#j&*V4va^P=urJgZyxVdp9ux5N3ELCXde$AlCLf#wF)OHgW|!@G zFVTHyLq?|f>ZqQciTOpPKssLbcWRXjb0q_NlLlKLqpZ&yRTDS31p`cYxtew=MdKhUFYJ zBo5O+)eLzklmu9QMCVyi6kqgtJcj&$h#Yl*v0$D+i?>7DF5Fv&7Uk6aB-PiTULPwL$)lkl@!ut+yDXH_M?*PKPH_n=iA2$^!2)f-no0G|( zCX=i)r;cNIeZ>MXu7)F1aOW6R;dJSsA#|cmdG|*XOX0&>o)NeHT%Ez~4+Qrgh^uue zjkVO4IeAlRosrlrI*ik@0(~gQH8je?-CaQr%k$JR{6`)>J8;nPUX=jHm7;nRCrJcy z)$dBrW9Y368_m4V9*rRn2a*`N0!pUU<15)=m+TR(tO|->qQJyQ_Kk0b@@)Z$iS_l6RI?#> zeO15ad(DOEXGM`^8y@JJdQjE%Ws_n;Xj7gM69e~ad;LUbA0arCf*kG3WSw;m#m!=b z_!=TEhKWgtTR*9;vZZ@w#KImr7o@80e3s%STUGLgIM;|K80FT-yd*(5E zRda>UFg_Ljt~!~jUfr^ml2tW#DXf%T_$aa(f!0{9zNHR!GwiMeaN4KK z!gt6p4v0%1R^u3cNXUD`1hRagTwRr$tY)1mny2kQU}F)s@E|Il&1!eN7`l=^v%}fMXHG{ zeVU4XQB2V%5c2Ujr>D2j*N65~)PzC31V_q zW`&hvX48A|EaNpZ;mTx_p>cZM=QS0^6=i6WpZh%wh5PRwMj2q_pE7o*&?Uq)(^67`KnPClTR}J(pj0q>DuoPew|(^ zb-M&!7j5K`5Dryq$TSy}Y?X1&2?`Og;Y zg)ch_du2UvtArHNo;1YNy8Cr8ju&%Ofo3~h zznJ%l(mVS(=Fp_PLJ?W#yB8Ysz=k5q%-Idl_A9~L)Ik4v!7ek+YL15-+YKe(A4xk5 z8A0wkcRgG?HR&#FC0IruMFMB5R7SP>MmDpY_Be2`j?#4bzoQ>J{fOQqdSgC}=-23giCr;nq$-zLP7K z#mgqD!Y7KUaJ47kZU10NlkQ&O~P*+9HB%Mu-FSXq-&1P1)NyV$w8ou@S8koVp z;k5+M_97;RVDNcPDoi~KRw<@J#5yFj)A68F3g%tlE8`4&Q~f;e=k+X#2+;^{%4%Q7em|_{?(-~z*Aw>Wn<4^*m8{PMn3cq58ZG&3W=Z1| z+0^5LQE|8mYMk$ECuT_qO=GfNvBMWs%yPN%fs^-hFN^WKPH>)?mo}Itj9Tl4cKD`k z_LXnB=hf8RZ4qLf?|$VI2o+2&6-+j#zufu6X?!8*aNL>epGqQXypXYW_(V!itWtN1 zUd9ig2FBo>Om$DI)G?rFU2lJG8~KR(I!lwC0h17up z5>r)*dBHL^gr+fD4gSyPu&W{Mf@D1@{R;3*hMXyfZlR8NC3Q(8t$?Xs_nI@W#1;kmb^ zepluT2}a13%sIxx7v*c!I>goDoyE;4cf~(UaOGLr#7M7rJssk%@2i(RVT)~2a~o2x z_k?_$?-??{HPFeJEA)JrV|K76o_jZ@C?W;7ifVotqZF21lydH8(4{8n!1$0+A_&1j*> z73-BTw=KkB6zo6Nr+udDLS;5vr#~LKom#XK!lH%+YT}hT#{m2OmWkddIGK+{eTFmu zdf4`6u4q{&RFvI9k{dtWiBRkn9roH9zBr*GKhpF*`mF}xSa4?00=H1K>!-m#Xuq}g zubmiL-)0;GrDf!CQ@SPB)&R9&b=o2rLvhV6tSOWje?qZu_Lf@Y78Mh)sa{Y#sBUwrVB zWPHq~3$40--u6Z-JwHWmZn3smGzDmz!VxYgX*}Cre>L@07AyMR&aWV2OJvhEZfUX* ztZtsP>=%f<%L(x7y2Mbj`;{44r(qO{cxg)!LVnuiYAl*yo%6KHqxF5{AGF9?e4y;> z2lvO>m*s=E?+b}+C(*eH7ZvK+bU&Bl~8S9m<>Sf zDpcW76B@jq-}D{i0|654-6L%@6>&BO`oi;x)Q2slRN$+FVhb>L((Q3PL$*o%q@YdH zahs!2!XgNZ-TAbeHh^|9U|==P{i_t=fpcZmJ7u2-U*;5pId~Q;pVwJPt^Ade=Jr%u zp#OHd_3G}`B51-IRh{OE;f2$Yf5?i4&uni+n&iw)WdGU7(KwvY9V` z5ZbitXSUZo{ebfa&Cur$+T>)n!0k{-?3gc|1P95RyxM|LCTYT!ZA*?=oX}XRZ1vP1 zF*)|~IVawKqnU6%7zzGK@Q*BW{|&kA{zm!YE^BDQEK_OYSN(OsXP%hvym3VW^A5WX z%I^nd6=mm+X%BBqPH(5b+Bm+&R)=&8Oeo4!1SIiDe{3*s8-jZIs!Z_k_?`sOCm8TV zjng1SeAkmD>6Vfnd9&d~IJj%0U%S-m*#FGd?VRPQO#qyahqsV5sa2 z>M>4Ij8&rqC6Mr)iC>Ac&&N99=WiqVW76Kz(C3j>E3~>E>O~qA`kGQ1dC3m&b#KR< z*oa%D7FC@jvAaV~Yi=|(k#1EkAdj3pzBhQPh+Ro;UeW_fU_#e?ITGK&=-sTsI)Azq z1IxVS;5k`k#Uj+X^@6Yy@I)`7YkFvXqe3gI!2m|MneaMA_))G~HQQ0Gg8|pEXS1;35Eq}zHZ1P39i~R9ou=d2 zTwb&|S|tg;Pw>WQciq{}&RI1RvHXJr39FW`^F~U@{r$?hBm;F$3_%?+iPs_?kDVJ# z`uXFL)g?~f?Cwm=O^tEMqMYL3{$=7h90A8b|MvH>v-P|`^WhRmNdz@HoEFWDaI1Ql)`AaC1K7D z%me@~uIALoHQs1Eavv~u?~W+I>`$zwlz_t9%!LwVLgDZy-cd73WWFY~yn$#ZKBPSW= zjU2~X{NV7=sTL&q<**;(Fev*s#pdBVV;_Jt5h+V8>ozt8+ zcmh+f&g*gyvZJBCCw@>Cg)oS^O?3D}X5lB!r@WdaP0j*YgCw|7>FT|A2FX6rXj6=i-{opY-j6_Cr9@sh{u zC%EP_2W%e`pL9n~(y=n{FSixvr$EG=cjQ0E#PS~Ms{2V;XZ3dS_H~pui=gzpB~zll z$<&EX(W zPtNjn);;H{S!3c`>ETGx=Q};+p1M5Q==!LNQ_!IbyTlF1oC>nAUw14Jg*z(ZlueZB z!!$eOj8b(-PF6ZFRx(q5-&dnS7eck<=N~m2fx3E3^j=KGoLXz3- z`lQ<5IF^3on4{IX-z!yx*S<-M(w;ZNnfHhvRD*#46!jNN-xu~4t95a{+#!qF2)*8Q z;|@N~=e{B0)?jFfYZUeF;)DCB8E^r~k!Ut)QzB{58TG39=Q`eWO|=NC`SG z>hE*yh3^$%{7LPqGn*Zm`R<`Y?E}qD%z}>*R&$0a*3>fgH`H^32Qm2(Q)b4zs?r zzr&0xHHFuM)%l4wUcv|ww>*Pq9MnI|VsRaomP8}H(f85p4;o`hQQ61L`D1MIUy|T@ zSI7D8_}Gz6c8tO-kv^x93E8)J+sq4>qHd2Kfhm-fXwqxM+CH~Cr`yIAG%605CQ9s> zdwm~Jny5ZH&Y(Q3Ge=897Y1 zbwve*sx+V;WE8elD_dU48W;4`CNE&~5y?o1PIv93l3#FSURm$_;)p|y_F|Rz5z&{Y z)DF^DL_}YmaW$L2!S<4-y0&k>`m}v)N>2I~*}eQD&?Z8OcoJYuU7jd~ua0$+Bf?Q| zy7=nLQJ43j&lS@H3ji=3^S84L1muBpr;Oj&S_15MEZOP$Qfn$#W^@S3r*(v)kX~fUf>V&2 zLZ@$|M!zsguWM?uI@4RHqf4@zK*k!RxbR|+Z4q9z#ddyX#P4aIyTcxs_#>345e@sp zTMsktg2n8HFFH#a+;+gYGc$b>FxGyRNXqx`h z@Vi-I>0aOrvNo@z$-?u{I%9Jnd@k>*?Q0q>H@Ca`wHunPfV=K zQH|d~;{xp(>BfTaubnPxNBTU_t4d+Y>by(UtzZPE z+*>IQjn7hiVyPP}Qcow!(cz7VWFkM}P>xdMQwDwGB zA2d*5O5cQ0Aoj9Rb+Qry<)i0VH-~i*gn^{R^U?*j1+_Gdh>*YcjBGu^ngSHEof4}pP0+>jWFoNbP^9g98m=$%vEX|I?&&K!g%!k9;`F+(!dwr zlA?bTe-~$UVeH(@-1hL7k6CKVE==P@_zi@MR36)7XJg8cZgJksH`8-Pn7T37Tgm$) zZS7}69=&$3fG?)IhqILK!n$-sva**_^$k)-ip+ZoTTP>|=_FW9gg=y6*Y{TVP6>~C zSW9tG6jwknqTCa2f_I>KjX}i5aM@#$!KK|>(Tf@h%Ie|m=UAeeGiL=H7%s*^u9Bu9hf$;d)W0!*+2_u|>UC>`?UZBx>I+hCvM zIpJOO+u-S!LhP1Oz}-XNNj4)nj%taJI08(EWt@RQ!R89N!uqlI z{sWWzf~2}`dQj_fXZUd%f7_8u8+T#nM?AK}-5!iuEGge#82LKnaZ_tf-TZ6vLR#bW z^!-R&e9wDdW&S9)Wn8-ZjaT1Pk#ZpXa$Bk-wS$$4w=);b z8t0Q3n#0MD;=1>F`S6x?0T)fkY>t=22X@FVl*h@;B@Po>pYo|Xy=oR&Y~eTN=Bi2 zVRT572jG+8qN|xn2h|#3%)s1bRd5Z@z9ExVUaYpVv-+VF75*$Hg_65sdwL&qc@8k*bFknT}hBW@#@LaR**?Q+-2fxQ+-42;0`2XXealhoDE#ke{Yj4%mM* zJ3k|u%S!W_=K-Z9?QExN!~&QMo9j{U>PP4NmHkBR<#b|*pC~^Ak%DychLq{TrhVaL zJl&TRx(mGfP3f7h`1h_qKjue=;f~wwD#?!zq!N>2j-q~P_nXUcOT5Tym=iuG}^=6>&O`VI?RBXz0eT>uRt{DH~ZJ);A zWG&F6gH82$q2Pl|dYI%9@vbShh)K~9@k+J7Wc_g z-G(rh!N*lG7>Q|7-g=Dc4c0n>JV%)jrf=Xc)fF1pMrH2mu|%NoV~(;Yq|Uz7m?A_R zN7lFEf&2RtyYRHNGQkaqtbWmkAgAGgf}a~mcR{(CKnuDiPT73i(t+<6Hiuz)C= z;L0cqk)IEReAbq%ok%G4jUnBUkwBwqH_EiNg1mLQ~@f2gUG&%%@Xym~<31)+(>n@4z$KUt&eSIS&hHaaY=& z{1)i(DY*QDRyB2U{I$X-$sLy$npvB{V0>(p0;KF(6p9<+R8s%Yj*wnzx^s%CiO^Uo z5^7YSS-BCiX^9rtCMsfnyick4HDdQ8r^|EC_U2;6T~*O!E#ZW_b`)LjQ4N`G0|8bN#``EB9mY7F#wRPW+;536>_!_nNWwIs4q+ zM6q(E<-tUb&)#%4|G{bWTdSMV+qYAH(Du=YuF8Z8l zyX&fgvdi^~}gl-vsZb<}#p__bfaBM%zZb5qaDQ{Y;dqni z`|n4+;+XEko1gT*HhNRu8wVj}Wf}e|NJ~F{8*dT+w2a~3kL3Tqc;KJFL&OLv%NC{< z8XIXj!kHTH@k1eFKq^!LO*xy-`q6ivyT5@gPs!15(a`U6FXQtv8{T4JU;iwgCc5xo z=Khb5?kW9Z*Yq2=Upo&|8Tnt;Uw=0dD@*z?#lM3z_0|h8QG-uo+jqUl(9++PC=8CF zmCYTD1)D~!(qH-?rZE53bGZ~y%Nu!q^H*i9QYz-BX2aw#mkZ64zbd2dITug&MBWRM z*T8I_{Z(P;vKf1uvHENBZzTBMzbgMX-PTB7*EBrukPTt8L(28MTAuhOQq7Yz<=L0% zr{UH;xli{s`%kK3{iVVRyX?4gMfALlE3UMzK5g2My$Q75GiV zARX{)ynXf{yImuQ=px@DH+e%~R~G5^#vVMJeWfa!yeS*{UEjUoz+heKhR9DHn5L3S zrYJP4@&2oxN|Z*}Jtotm7x#~f71u<((F}NJJatn*nZD`zXm5Tzj^aoAgQleP_fGq( z$C2p#k{?nxf-nxGe;(I-7~vP#SUGDj`1`9c;>KUtzReZ6mAd$+p+o*a{ElNkUpx55 zc$BpG>*y}#0qXKUY&%M6F$?@H`RX_NhUWhPO>4+$1YKF|r|3ilBA|)kxImVtfr=n< z1=&gQ!!h%}x>3@1H1!V}XY0>gdDdiA;P*7u?|G?cM`$79e}f4BQ?Dy(YT7V|{M9Ds zbe{3Wugax;>rCOqsJ|*Uf3^BI4)I@=zYiRzp5edv`J9UX@7(x5d1bTo{_25DchugG za}yX!$U}bCi3pjmwH((q_e45kN^1u5XnYL+-Ic~;z~aRpw0XY3QO#m#;orPe_v8;$ z6PQcYibwmgY;RJ@F9u$dlYg-g+yw9cziioP`p=Fzy&~oU8Qr^gliQNb43Z%w@-nFS zjd!1DDq_>ipNF!JsXf0+nZ&M|Ugg+>{WaAb;(TBKtoQwccGo@o_1dp=Ne}khz+d*J zviXPe(Z5<51=n1%{vW%Ja=dQ(4ZSOP|K+ZDHe)SWy7SFKus0{F&JPql(CylViS>xK zP)p?cmFLG`H(_4287{#{-Cl9G_-asLUW$ti^SgN^;rY17@s6PcoExJPtla3#xpLWdPna zhR?DFby=rzlauQ26LcIg_8(+F^TRg${i&hbbZ4e$0*%b_+xJ1r?b?;9_BXT5%g+8Z zs-z1XZC&x3wvujYS)b0~Muj3uoj*w7g56va1)WxP1iMzYR;te!Bo^wsBMNk$HT^*w zwhOli?Cf3*)YBnk`)&?j>*lg1tY|_tAAei8q`<}dW!@abcc@UYQP^wsrdDYvu%&d@ z9>^$ayM?)E`)0{@p}_z3rYun>%157pQ0fr+O500*aO$S7UW7YF+Jc}Bw{d;EbYEu6 zR4d)I%RB>m*c;y-8vwW} zXty&N++sgvWeuw3C7pch2OIYTG!5BVY|=6$E;LnYj42fLKvp|8qbY>$TOMTa13vK0 zmCCJebH^P7u}o1%koL@Kg?_$Tmt1Xf%C92)Cgu>*`#du;XT06#Ni9ojAUFpmf{p38JDm9KPF*h3M!>UFBN}(s zB%!qy-NX83t%^$$>ztsmz)iX~%0*eY1gjCXSRdqVyjCjG?=NlOV9eU)KHc%cbt;bO z5c!dBw?zY0!aFXcE5hNd+9PMIWYQ7%{l=UAzUNn_c~;SwECGTTK?=PvA^25bck#kl zstmM{&wxU*j!+g;g*1+2TL4U?tG}R*^+={2cGal`X5%{*^UlKNPG=#@v+zZ;bS;=G zp45aoh0Go{gH64bfI#A$F0E0m2X&8fr7njY7*mB!RhJFHeh5U^>c=p7u@#k2o*Ih_+w>D+rZkS@G+jl3taXazMR&X=+V>kFlKAnSTj^{o_C0#UykED$Gi6{qZZRI z>^L?}6XAV`;?2~SXA&cW2_@d#PdiMjtptvMoc_Km{f~e)%Z&Rti!K?2f&fpXU3djY zx$V8b7s8b-=TcxeGTV;j3}>6x>al-EoKhXn;wp=^@4R)Rrkh&cvHJ4Se-e!gyp>-V{GB%I z=RCk`&?J_^4vOrl%dUmO^sw>JpinJVaDSIvE)@nuLX3#Od~C`ku639B=*EQCdxJK{ z&A7&fGVZ+(<6}&nE0^eKv$89bf+0XD$#cHY>KE}Wsqtauuiw5@k8lM(;}F}>Ef_n9 zn!qpcL5Bizs1Hm}@^va$R}iFMKN6lDWj@Nke3yoGevGGLEfBTO-4giGW2GZ2xng2u z>2&Q4WwR)Moayke)^cg-=6iPsrb#%RNMI>fZD=>+UYmyGs+l7Tyge}-~U1LNJqXgX}`yMNM-Es{piAmvz{nKMFRNh-DFD} z1SnSpxT$UT#}hrqhpsoiS_p290%YuoDB=wpa3A294s=XWO8Tsq(xEwa*+5p{ zG2aJiO}f`f$Z4fQzPj3NkPNYvuDtm7BP9{4 z8uoH?lM&;Q3qz~uT|(w-{B{xmdW^yAx$Y0~D0sd7nN94JAnsl(3kT5kC0=)r?OBS6 zx2R=sJp7v&Q+`e2er8HieTw$hz*ZaZ`kHU>^;f>3#D(jwjH}hwjW9iw8$)NyiBD%% zij6RXb`p>`%<5I00`eMzSrHK$g73)P?r%V5AdxY3xM3e>URZkQNJ|josj9kSp|m{j z5~whjOsC7T_M+GNe$gC(yKIrT_G6)3Z3|~aNz+RQX+UQyJnZ+v1Is+5&elV-1!vw^ z)5e7>+9?~_v*6}hW)l_CmbK2v+OsWz)oiKXn5LyO%xR8M5w4MrjEs7*NYK;VNW+a| zBr~G&9Ud)M{JoD?#E*aNA;Q|q-1@79<`GuL9Ig4N1FrGSLZga&nN6#3^#>JI0W1z> zPW}gtsdyExAQ(svRyG5rxqT<4lUr3xUV}Bxi3EN@893!H!m{aJv9jUfC6vhbf++=s z?U$mzt47^=;qm8$*{T@X66Oy!?3o4 zmVC-u-3HK}i|%G73e=6kN|lwDh_~RP|F_!>jvd&tr94~AHZ%ZZuVk>hTQgN~5-$uIL{s-&!6Dc(8#k=STUtT4{UoeV z-Q>m7<0+$nv@R@Kyl1DxmGccn;>*`< zavFUr$*shtzxbxzg&=u`yT1-K#EOkAbC8njF2iifYZpUS1Z)q)U^f)5enxqNNGW(P zr44AR0|v<*f(d23hMNcDlsmq~yXyJi>@<^PYc3>s5`N^UEfH53IQPMUyi9Lggw3J! zT$5rnL+f1BepL*3>-NIaV$FlU^f*1jG*TF;5~WvVOsg_98yjg%lE3?2BTSoaf8Cyt z*!Aki_7ski*~$}>mN;>oWmcxZN~40{CTcqn1&*ft!U=eQF6Tn$X&^luh%*~LDCR_| zf_!H3^_^+fV>qLr%Aqu3$Ia1LX~$f+;6=h~j<%*mc>}&&K~SuiVH^cmPjR(6OqVl} zO;tD&pY=;vsGx$P*CKo-s-9EUd>M3+a(p{{vfE2#p*1m|JAE4HKSy2-`ATUzJ?mu` z*lA;@J;P4bP-9sdue{jlGTwjl6x;kz@`st?U|T24qYvE+vB{R4rC_phSa6_T(FlXG<)sfVFf$INw7EBj#(Z0AD zig>!-#%6r-pLy%a`LX~B>EATBoWHXTmtG<^Jy35$=wAGgFm7EQafCB}=eiZODD!mC zX*9EaYJ4Ot_QUy?-niZ5*}TjMjc`Hf5N1CqhXly23z75DHq-jy17MDwy<^2_-I>ZC zB?3Knci&IO0esTmOjE*p*PW?IBejx)22vgN_L*X60Zj|K590}?i9Dpi8)xDG7JYsM zyrAgy%Al+pKK;FS!(Es>pUli5iSDc6LgmjLa-gm2IFe@V4eDjav=FpgSM3f=XL^~ph@k7Z8AyQuvHSNnE z14>4~vl%jrcEU!eXQ!(-=e5;rIdvOs^v5`ojB`1D_}idMduX`x8Ly`2UYC7GZ;JD2 zTIg?aAmQ*t6tPFzzYdWGK>xe2^ zQD2kZ%}hh`7F+4=s~zeuNVN8NvPwbRyms)Nl@X-$TgNn`tta>`wRVoD$P<7Hc)i2S zK6f}f$PEuZUtzF!z310TdS|0lZ>qurUqAVYPFYYwKFa<_J(PhfxJ@6)>3}?Yu4=G-Q>)|N*zcLll_yRu^ABV4BV4k`qOZCh_lZ3=_ zc1Mh^t%jZm)~^&dr)yE%y5ulc?h`x*h5!uhkJ&y49j|d0%3SP^9LX?Dm0y^A49g5x zCnNX!q^rLbBgJUe!4%dU9(ZOIzfJim-Vvp;hT#DSMS98sm=-HXz{}>({4h3Vu6(i9 zSLI(AuMCfi*U9Ko4$3N|_yD|X4GNWWFKbK~UQ_?{&9+ToQc_&!sWTMSt!)v|jA|G; z6`1JSwF@wJ{TbA$nXA2&zPRK`z~WGQXwJ0nz}?0UGe|QMHc}Ohe4{{flkt?vp0qqe zO?Z&-W1q-zz=P4UBjj!K+5{ZFh#Ju!k#hNBkS4-b`%zQ3w0 zg_3D>2@5pa+-^Z~5f5tgL+!Cu1a@0{UzyRd4deruLBFW^+hbDv8 ztNVYt%aLhs=cdQ}*=1ml#nJielONO22d|>?nfD*Gva`3!>r=wL0XNlKU16+<0L(6l z8dK~1g%uLyIDTuES-C>S95}w*C_{7TzEm?q{VT?R0DAW;#B&8C8kRr+dUXh=Nji;k zSugYq-wrNRtM7hUC7IUSXttntq1pljVDI_ijVE~rYdYYPGERsbd0{ZK(6cY8aQ!Vx z3rtHL-6K{Zkk@~6GT)TF&}y4JzchQtYvqVDW4`v;cx_SeX1vE*p>Cp2OXo$eGeV1& zxL)Cm1T0L#Ip!UEz&}5e#a7oFnw^wqzpAFoFj(DQzuEpALUI>d6T1j;EvF4i8_J1>sK~URhrUbUw!$e8~<))N4#PqbsO>2Wq*rM ze*bodw7&5g(v-Z|C94MBt(~1c*MPDNT9~uBB?^XQCIMr6Yro0@xSYlfUQ&5_Kk=zt zCbeAbAUg7}a*Ssi)m+tsCN3%d{P1;IHpxnW@aOY8wXQg*B4pH{c+D3HJfzmJd6Z}+ z;)0AJ%D|dsNQ<&+5DjxYoG_o#j)_uZZbls(6^R^K6=mk}LABrIX9Tkv31+{mQM24D zcyY3~z22-eD}=Q(7pEWR03F0O{A6#rPvO<~fJQjG?bmL|A8-0z_iAnw_|nz=p8u>| z-3u5tR7W;B+0btU+7g(MtP1gC2%2hb;Xy5}dN90i9FseCDwL|gn_1=Lpdy4t`?*3i z*Fhs0_SYxISP2r5xEyn(jsC5%4}x7Ga&@^W$I~75kTueNvs60*$A(X(ri|UbG4ax{ zr-qhA3y&gdRC7DopOj!BRk1mY*7_Csb=KmqoLx)GDPOI%|3R~4E5tL2VvqsP_~(~YP(EOaHo`vLdtBNHM-|1zvsqnKM@$k>hdDV!VFQ9Z z4N)jZKYk!`4u_!i|B@t5JDdLd6F1#FcKVh(S~`DyQnecbw=j`vPJt_~q8)uCVr2+o zc-6Tm%d~NEyXJj#dm?s(p7W7Vjt0Z>5`$Q!mSk{4Bsi?%dWsLZ06U>Lx(qxNi5m~J ztd`_DF3`o*5tw3O0^?x?`rsuKOetc+1e)t8u-pMh-*`5{!X^USA`L75puN(&R^(6J z^u^bDP4ehGG=}*++VZ+k);u&YF`|mlo}pbp-i|8Xn)Ky<3va0zGNHeCDSp4Eig(c0emsX-O*WbLs+K_{qw zR8Tvf7_UUP78L4PKqB=T)4{Hwe$LEN%(dE$9QD3V1gj^eV;WJkqSZi(GD}minR0;) z2ZLv%3l(A%4B3uY<4>(Wr;#T{`rvddkg_W_y^wLe)6X29*R_5_*fn)EKI$H(V=9p}P48FLDk;SR9bY@+sa&bNNr`87`SDs+;T`Oo4_E(KJ&{m>UTh~O zi(P)0#x_VL3BM-iy&R#AQGTlGz^lQ^9Q(7^0Vds_Zy{yUqiDvk=bvHyq)4O6wggfD zRy?OW@XZqsg%g9=L_mrU9uM;d?928fU%C1i!Ann@(`1Yq)y*g8}BtvQeX8mTR%NhgEWh3)5C9 z@J&MWXO5Jt;r@GTqdC~tS5fChu3?K(@C}#~d;Fv5a_Z{o_8Aj2qiN-_@gnWs8atl+ zOPS9C!OugYhUl-I6|x9U?S_l%Oqmfz>hoj1Q+?3yUHkSNo0*O~Qb_aI)7 zU*zYMrUh9SsREL>>=e@HnBw^-PtMB$UPB;$w%C_copb=O+Y&O$g zkFG_l917I1P8E7nuWWRsvv(p%xM{SUbxTosGioNJX5IODmKtyz0Qv~Ht@JSNaN>Q+ zU(g-x(?mKhW`A1z)s{<%pTkUCv_CypMFOU7w&d>EqBV+en{fIB;k+ciBeHr4OV4Wd zS6i#T+K%eA8&K_p4^_SxZSmiTxSsQ4>hFH{sqnfnA>^Ow zaDp|{9-^hExWk&bv7@LJOJCFJ+)0=aiO*Eal{#LnTTuFl^7ePLGvKqCQV$=oQi!^E z4h}D7BF?mMOXB&kYY9u-gi>;;pN`n}oEZq|wgcn|Xus?h`XUHi53nQ!<4r#ku^Xhg zU6GR2ZM;t!G;N!q^twqJ_x8~bdaB{(Tm6F(R&ExrRCI`akQ-?>WIbJ-!t>IE1-9kl zPRbmgXJ^Ti!NenQZp!+6_{1?k)SSHl#eJtX(fO_#`2sS3B6@5>gYt$ib^_=NTTf)Q zMtSyd3_xshk8E=~!ILhKDbkg{zk1-;`iM={pt`qZ11`6do^*z1bCN#fGvCTuTaq5H zD>Y7jW<_jom4GA79`orEv#3I3Au$>VC$V~5C-n0CQ=t8$ji3HJ>#+tKBmvy!pzAqbi4#DfQ?8zbirdeLMOJ5t&Yu5ex-zf}#pRrkMFIxyH%zsJnc#jT-n6SmA z`3H1tE1*Wijkk6)tAZ$sYZ+P-iO3*4!RySmmt=nGSXEA|VSO}aIKU`RWq&Bsh zL{x6w)TJ<}!vDd^*C&nsW)g0=JPzm;gV#1 zCxvBxiew$OU&^&>gO2H+E;wJOp-hZV+_eEyx$T!u=%C;M|(C~o3= zJ|*TXv1W3)3O?7f+hysi?7a3{sQ^^}*Ycjl_p^JIOV`m(yCyl?X-9@q za}LkF^t6czOiKtG<_pRK(l>CyoU$yHD%t$vXvH9^c3$KjPjSl<1q&CpZgWl;rHzZ+g{ykcw|v0J#K#DwAZ4|jfk>yaUE4@%c0%K11zjDmUg0>bc?oiIiZOZ zdevOp72giLy{LxQ&a!p9{`unj}Om$5B-I}2%!E6t-iyW9Y2*V(Og;OyL~+GB*~ z2FL828%jG$)27X|CTB!Zj?b@e>G)fe5g&7pN=a8dMt7Kz+ov-_`?P%-oXFk*b&Qu! zOlitu8|t1y1a@bxz5~lW&;^Gsgh2ct95B?{?KhL*idmLCwUVcnNpAh?QnBY%U(`jT zk9}|@laiv-8o;GkDbM3V2#7d=r0VUdZ3;_k#_T8sJ@=`uufSQZB)W1C&U=5fFT5xx zzJDH?{S@u@?-$)Q_e(t8-HpJs5Pc=f@`A=B5~Bn`!A{HvIO$4mocIl@(P)UdEm4se z7>SwlSdP9uHx>=;aYWZUw0CHj?(6nxe_v+Ck*5fwlV*Dla#dT?xbba8p~)8%g4I}@ z>5m_ztwCdQADG8pna1#|5##PntX)DB-RSL`bGlVPY5r4X_SWfk8Y!y%R5~wm3PMNj zPkq(2$$Y-VFf*D)DitA9Ulivc!enMX%^2aXVR*G(3Q$B3FCqJOz|q(icQ1fz&R8>~+HOh^PsepM$0|5o4N9K5OPLVMd# zW_hiMz}t@>gLay&va{sMxG-IKe%1{$C^nX#SfN<)!z1aBXuh`PAm{&*Owi&EZ|Pq4 z&gOU`P~#`if>&vduby*yP1-hA#@u@qK_J*gig{Xm2te6zH6+goprg;mo?mKA_g zk=MguCdMcGfT@Y0mVI+Si`g~@{$^O1DT=#Jhem% zAdOpNTOd}Kj{6*-Mq2&9*n7*MxVo)flmyq{!L@PM-~oa=jcW)_1C6@`cWvC=x}kB0 zBoN$!HV(m^1PC5E>~qfd?r*B;-0#P&I_ux8nscsNqsE+bjX9q2JX2`%v!EG4 z#Hf7-YGcCb#)lM@VQ|zt6NnqtXOl5KE2}b-MTXL^R_};p4EOmG28m~h#Qn>XpD@sk zm5b3+FX7GN(XukeGwExsOOhTpbafzyNma53DoY0m1k|>^z%0S}p5CFgh=`{4 zaz?;$EZ~06Ez26y=MPdtU|MU}A;gys0f^kmWCMu#h7Bo=t<;rkM>i#r(?!pe5%^Pd zeUi)it}ycq0ZeUCFHy$H7ZoU-BzJeJ2p*=3}kzroE3IC&@@Y+ zhx^$jByxtt^WE_@BxTw_sY+NH6=MEyR#y$7HcM`*wbhoF``X_zKhA`-A_1e!3|@^6 zz@i*d^sehT1-`JhD*gJro8AB>X7j?pa+xl`yiS?CSZOg=W3rDwnqZ+PS7u}QMO6_WJ0VU*~KXT|YsdGwW$dvXzG zI#<{id|awE?jOncy0GGi*MFvjOVk?*0bV0u!n_{8oQ{%d47`71b(m-=U#l+Y-M?7NT=H0mOp&cPG zOW$5`td5)#XSv0c0i(r!I$@>BWg*p5?d+Y|c;vj!=NF%Ud;`HGd%)s}zx-`Jz#QNZ zAagVEWGW~HfuXycQ_krj%f9cx@jR&tFahoy&%}Aw#D%YPSYy+eYXa+zACCpYt@$;@ zzl}Ur=QtrfF9+37KtrIZ&{8^GJuD>h3wbJnaz5@|x5Ne0W(%(?Tc&J?GUq@e0HO?7 zV9*R*;c%3MT1t&Pu+t0$C0(>w+vukt`mouWbCt`)_Tc>(MC*D^eWz|MvRF)olQ1Pix5>$;(qre+j5k3kpi2c*Gx~u24xO zw}^P8QzT1msD2zV&?eX@pw}$CHq1H zqeChXBA|_rAJgKXs1Zcguh>xEY&(PGn*VSt!K2S4-c-{5ANF zX6ql|bq77hm~T7C(H}p*d|!A(?tJ+-iWJ{0#m(GB%|A%py-%092F6@oVqf-rto|T@ z9A8JlYZ9y^+d4u2=9EkL9~{n&&u;!Z_V5qV*TDBDQ|6D%i9)lZuEDq9wOZqE#`12m zcA4V~pc98h9uD<|8Opi@$BcU7+r~Men{Sn7!-H5yQsBJSB1RfFEi)1lu?VT9KS-Lt zrJk7hTi#bm34nXwEJ}PC3alv`xNK zUe(J)GyYVd0A%nBOUz$|JrhkPnErl)oxkyz-EnMR*?J~vs$TJ+FlyE? zymb8HM!uk}$ct*qpiCDgmg&NFldg~~b%wpRx4@pw4_9?zN-MWA~-q-aLzkT1Q`C*#>#(8ma^}3LDcLP-Z zXkFCoazOF#ipu|!>$D`}r(Kdvg7&TqE>jxeoasw>&bj2Dqujm3Bzh~ErMB$s?`!b3 z1*gB`(TYfP1-*FAgitGx1$^4aiY(bWxyHRE(qF_FYl(Ae`|4vG74bpc^m^x^HFh57 z*K3DtgBHWGWfQ05&d(#Ff$5$LVM=YHBpBbdz38@&!M$a;)j~g7hd^u-m(tB5hIhhH z1v-b=oWXuEb|D`f9y0l6+q0Dc<(+o83IsP&CxeAO%sFF5>}^b)vOut+!CY%@?jgdP zLw!KhayDc+;^!*qw}NHL*Y6bbGPL8XZ!maWSM=p7RZQAA*NC0E8B*7+#H%tDrDhOr z%Ug@Pxq3d!2J87ldrdlvh?BLbpLX7B7hAQ!+`?4&ki*g>msRFsrePOhm3h;GBB|}e z{jOv|3&>qZ_`b$?8-h1ybjAFrsIoGh(`E|u|AXZHMeSHQR!mn?WzxN{;Vq{}rh}xj zb83%4wf>`AS(P(WNrsJKizH*yIByh$DU5`y((&1hjXnN4uiXmnbvU$lmTN67c4P_L zDP7mmKO@t!8LvOsn}OU?4Q8ozap5xPmL6ngW#-vUj>c(g`axd!yf~yjX6j>?QR`V~}=jlEP5Tb-~&_VQw_+kQvWB>(hwgSEA!FJV-iC z+M4GJUE!Bu&X`oym{`lG^QkN`9&yPciA&nfH|~3%c{`Y}K6VVfy7nMv64nHg)MkSQ zx0!_l9ttP3W+UmutbNi zjg(l$NU=Tr{V0aSdOBRzlFesdoBvvAq}d=Pwcl2dGmD^$8Nf88Xg8mS8e}+MiSq5? z9o4oO%^X?WcCOv?4&UhjW2LO}cB}o<0S*fixBS%OLb8?WA-Z1g=t8y-!rPBNBB$;`oQ8Bz$ zXb{z;pUWx*A{_gLb;ml#^&to5vqobXhriO6jT-Wn3Sr6iGS$oyoerRa#jEbAn`}krNflE_P|tAhtWZxQn1;u`Op`9^% z05W33g=TdRDW{TpHuI9~A`DEVrprb$o!h9xR!OgnMN`5Ad;JybswRxmni0p?f(;)- zT_^KFmkUbt&df8X0{~UM^;p7FT36fN4e>`G8d%cT$$%c8n{!D6mYCO<2Op^mHa%YB z1u0~VLd}1!wkUsKKJa!_UGE}|CvYmL$T6PiwS_(?Q?BiDF}{5>tZ|}JwtGf+x)72e zKY%)HW3X>b%qc}`(GrHMyRgcP9#=s3S#$c@wD;a}_{1nccrvXLXkx_R^k@kbus7%8 zCnUtyuh7U%dugAofKjZ7t1nKDIKz3rQ2@hA>@gcu#@WB8n1o);>8i`+!jsAV|pRH z=f1SPDJ=sQJe*bno;Iln0$;zAYnUTSN5q53pr5bHy}oy*Wm~UWpDH$U7sd~6pExQ? zB)t*b&Kwo>xS?x_*DpvOy*bu#CS++}&IKm?iiVdn5Z$yVmN9Cw+jV&n(q!HKt3B zovM_HwG|&$Yfh4!NMdH?bP0Uw)3V&W;{0JKYlibg5^@@!E)Ppv9A5%-x0}pxuuw+O z>5N65L`adElcZ?_{va_8|Mg*s*Ha4UuD>_nSL@4P9ZX|o+ds~Yl=g$j#BMFW_zGd)w&;0lYrs%M9PDXKn!%4aKvyjE8;p8=ZhwzaU^ zxqzs9!zw4Nd9FtEhbVdRd4K&W5+_ni0Uxc{D#ayLtW}>noSE|WP@p`W1c*b*oNV8J zr%m#&W#(%FTEy8<8WD6xS^n9Tn33Thsuo|vWYosU9QWEaj{$mmmJ7(!KQJBU=bB?+ zi`8LMAsR5>TE6uQ|H3HccYqSZ$Hc{x3^}9*{jl-+U zSND3|y-*uRkYQO{lY$Jtc2iq zBz`>Q^x$+jx^SaRWv_cOvVB_wGLPS=W1_NIU3olTPJKNe+x2i%NB6~o#(O=;hpT$r z*mFW-wvB&cG-y#DT6(q`=Ot=;X`k`CvlI8k!ohjGlkLQifoS`+gR~B$`O|`(bDMD$ zPAeN~jq|=0OlZc%);F=B%tSte@C|I$%Fu}xyA%jrcsDha_}p4rT0as0=^@F&$EU>) z32E7-qu<7-b&-m79MvUKC&nd?W5cg0hp2GoI#fzOPl>Hm2m#_(JP844Jx@n^diYV| zx0V;itHZxZ^kz#AV{K7EDRWPngv?5P-Y!{y50bYUdoh*j{2G^e;qr^O5!)tA6T}eB zbojCUoN;S|_!3EXPSS&IH_J;yttox$_2+hLG`MrdW?Wb8V(l43Rf7)gLo6GMBF9p0|yKT_Tx@at2yr5w)28Woq$oq4SH))sAb^ zG=}^nLy^bqVII4+y|gt4V>DX3{z(n~5NA|>(9w^KAubkoPe)E`Syf=ZuruA(TJzEm zL!o!Ly}P=grKRF9UqxL~(oFE9 zWc^7J%o%eb5488Oz{0i^(?iKLVjeOn#;%TIhss6lt25ytX&(eIx^+~pYnkGRYAg87 zP_-H+YH$4%>c5^#@W`%;rGrnUE-M>r(VLg=g41&2~m)}#s6yo6}1x42Gg zyVqnQnI2b`;8d+r^~A(Q5{5?jGftqWKGnM)qz3(EG?EbH>|^922`|6fTM7d{k?Vw{ zf(mU8Ac^W(+^W5wkQv;FouoIzy877QlA!jdKzrrR^-s^{d8bxV47izjbNNpOQgSBB zVKMu#E1p%$%+3!?UtiHovRkb?fjG12YWvz$$ zzUO1Kku2>cX>aIV&QaOvubaH4Ja2S&!|SlzUCVQPgV6hspc95_N!;?IZ(r z`R>?ci3O*gGTAvh=;fJ%YMbU7$4c;y(R)4+g6R7W8@HLrxp__NhEq~Sx((DaSQ`V^ z@+QaHq`y&W2C#%7Rw_#?2+QeNtJ?jypcajP&UmpDcC@7uUOONB_-PPdIcjys7x9n*i z>DaD(0`W7Qezi-1TQ(a};L4hBAqS;LD*uAR2Y+~ZYtLnk6Ov=n@x6u7Qur_uZ^+Cl zird&I4KShROpVYWzsVu^+^!KZ|5IkM#4*pjgxbzUzeR4t0Rl=lSz^77Au##WPT_Ro z2FP$9rc&h2V`8G{V&|c`{%JDXm5|~;IfP0yC?umer-g_cL^KMSmTQ4M)QuO*&uhiR z(aeJhnb`?J>9b(5{=;t;8r~oU)~ZOOZjLAi%$0U=qOG;2fUF!N;hEkj(rjgXto`}7@AEqCWf>4rqa%X#Ymv-`l8yDwHllzPN zQV1-JHA7<4sB}vtb?%1EPe~+?qn)2XGp9jR)1;~0nZYNsX%_1o^CTuB=gW|AOMWUL zVZ%vpa+2w;_DMQEpC0X&|29p09T(3@`zt)-Fy(ozcmS1T<(woNA6R2$E5XtgpJaF} zs9Pnl^eoH%;v$1sPkk0g4Oe~_oS)AluoxQVigd8ymQ1CKMErEPcs*O#H2FquYKQ%FCtbhk%W@6teuQ-{-rL$d72^NB7hb5?msYo!? zrPBo{#!ZrM8BfT1-{R@DRT%42KdLMgtkH@`7)~NqmAj`Cuq`p*~ zuZO8p3Zy3$qo*S}w-XHc1V|Ult&?RX$ z{KbTfL@-ki;P5RcY&(QvTv*)aI~=yWC}E%Lwm+GsZy|aj%_epzJ;ydoT5CWDU+vj6j^WK|)WtNE{Fmx+kg1;5yx|`7|A}RLIp7H+xGL8SSq4jb0fOh;hpr3YAsU2rn0Kyv8Iw|J+luBf~yDyiHRo@F$zW zH}c^FsnPT`q2-Lt_;hTY;nnbEsN8GlE^VeDjWq(@S1D3rbsEan#PC?UDu^DD9mp9MCX zqJKv`otVnET6rS{5^pX&Cbblu(-YT`CmWGSNR~8{zW%kMH!#GP_H<7>__x^kzc&SR z9M5tCoHPF*DQCuU>Xn&~7bBDy*Ai+eM`}D19(t~8n;a^0f!vH;%o$(vlUMcqD!#L5Gwxf}J%ojOy2>b5KfEl*>~+1^#t5jmxSS6a{C z+Zk_JsX%~J8Nn@1PxTY~vO+B93o1f6+N~m^D51%DZ5eOry{L~0Z;MvvRtOCUIP+77b$2*@U&mN2cu})rU!xla-UgFn){JPQtHNl*9Fs z*~ipxzO-e?G2cn|sEOn?v2?;Ne7a4|E*ovqtZHzKOEXm0g-g_3#|SHK6gaADI)1Qe z^DC=&HjTA=UK_;1aPr=?$=6PN#7N3_%<XIJlMGqi7gaP@mT;jHPT zc~Kf4DlD5Bjhn{1Vhdag4*D|$9XZq{c&pwDU8VYm9o6%vt9JUamksm0bQXA<0ajR- zcQ=WoPNZ+NVrACbrtlViW2rH^TJUCJbxZ`(dw6f=bhInc9UvI-xI3Sp%~-h*D?-X9 z-(cIt&B^ba66+ML?G|#1hQ{}$!TY)p{;_vKWme2bXW}ICobbj(*9{(%aOW&7;4C%C17>*#sy)ii#xee$v(fleF{Tq;=e&?;AwnDuz zJZ`L1=v_P7H6ntYP3g?)737G;U&dfkmwD1|6El9+?e`y#ertvC7J7)hj~YIXm+ zpJFFmya zhfHZ(&Dq9{ujV?;JlC-4gO^L;Iqdcu`El>(e;PUpTA!q9Y^+)>G?hKyYP#g*=cF7i zb58RiP?MPM5>p+b*|;cTWj-lc(FpH2;F+Y2z=9?J2j zwzy=57o#t^eJ;F)FEx+dz?DqUZ%&is2sCvCP6bkTw)uQjeS%Cofr%C7Oy`9gt+Hsy zSEV}o#MHSL1W8i(?z-m_0l-==Nw2TO8w zLgIwD;r`p#_z6(%uUV}e*4}k+qX8T5Uc)3G&fNq11!Z*0aI|5~x>GeBu@g_R<(EM; zb!m2vvG}<4l`YkuKI?M?B|d@*RA|IVvd5p40a|EU672JYYpN~F*YpfW%inak>JrGw zDHcl~J%3lz{tc&cnc#5Y6zuH0McHj+;ik`NJTflep3<(@JYY+Auqyl(N|UC{tiH7L zjv7fkA}iUnzbStZcG|Z>-X5n&K4Pc;hAy5z=KH62=je#suXG01{ZX2R@D;s<59-Nj zjibA7p7qA`jj%8XoW#TvmNaSH=u&G@>700$J0z_r%P8FpjD7s8XRysb4v!dq0Rd(atc`Ho zm)-bUZ8GNbvwADotyWC9VuM$9BVLoU^3tdidSgu(@& zRi~n=iqeR&lU#fdy^RCU+c=m+NWNv_yK)Sf1S%?3x#{TW7=OK-Lg}|O%0J86*Wa{_ z4ViK_P005^Kbk(1WGZ=w97ce*EkzOdD^D@8D7Zz_rt({Khh_OMox`BiiEy5o7 zn3de~BzdB)D5UCH?uCQ-TiYK+Icqylu4dxclRDot_BR1M-Q^IJn9ez-#70%5mdrM% z@%c^t$iGjM@xfU(CV8oS)ZaZ+y(C{+X^3qjlq2#d!Ur+Nn6@glb2~@h>Lqw?>o?Nf zaFwazz&+1H!Jf}*$LLb;Qbcv?-(fU<&r9 zkzyvex>rWa3{dnaNtJ)1ptqkLp9uo%lg*slhfS0>+6Uicu$9^O-pDQSx;wUgO&bNaw%p8QZO2IvS zWv&`zw!Y&p^m3XA^~~1K29){?u-?wwmUGvoWyq2Rdp;zF@E2S8DUVW4nB*S#0C2iB z-2~n)38=iPsP~8u+z@rh+-;Ik{?wlRj+(d5-?6d$PMQ{l_<sn7R+8dkLsOd|2kwjj|!YDO4AAbL}01qgvnkVH*{DK%p}5Uf0#Zw zi>4lznnZQa+88m$UF>lY!rD16g8n;(4EfwH-?`iV41lgab@ON;&ZtKBZ1JQv#O^(T z*f%7STs=))1MTMRJI=y%N%fg|GWwMBv<|Yu+75tMwd~sD6K}&5T9@(v=5O_XRdoK3 z>VW^(h&ac|H2I+5C>wHWm+Z<88`k{TLIu94EJx-LLElN=*bZ@Qa#lb4Dioi^obJj} zPjg}Wv#uJ>P&scJf#s8IsP#wGYkvJSnA`?e>P#G>M(92hCQzq5yo?s^(PFkmk{|7b zN1#zkrEJETU;|ZdQGoxZ-m%|GP{z0^Hj@K{<++)8WfP>h6XB)Eb_Daz;31n@2E>oLriK@FxS-hOTAV$c?EV~wPP-)XK{A}_ z(NX5S%Y!y960;_!k-Fk@a|cY{92F-h-`QYtxSnwqZ9tMmZgJV0uHyox;8g8R8TX=E z>){%H`IA1g&4e)JedRCjT|Vxd9W1I;5SbDHnTn6U+jJOVAnKGCTjX*_hxAT))3n9T z+6EoTT9cZEaE{TOS2nFgX;xmE@~7YcBz`?5+OZu2iE;mXDoY|2N?heeleef&XsCkuXq8Wj&_;ZX46}h z{l2L+jWJeXq#a(SG$bR-yoaTZS9_OAG98FR074^sa7mDjVPFP{Eq>saN9QakWoA=j6Ooa{jMF~6LZZr{bqcC?IS+Vy zcyKGQ^9s4z@Ba6F1<05*VL@y~ieIWuHBy@1`ISkz_&u7vs_MXsFlXMqWBG(>OBfiy zSZHWA+Kb6##2uR7W@yaH3`Qz+uC*eD=CpTk&32crzw&6teIQiW!6qd%7N5w;o-Ngpb4Kq?AF)yV1H1WDN3ynfd)3$y2SkaiGQ)Aem zOT27&^?)375f#mqxKVFB4>F92FhGVr>S+7<>y(A49PK984QAHZz0Sva+`)pJ5B{XkD z>?J?oGMB$2JL~aRUn#Npfk>)7B0EBmoX`xkuvw-$($ljv*6XzU@uLKwSTQaQ!??d5 z$`3bN#}aYa-%Li1mHN0$ogK%C2=5Q^ir4&|Kjxq1hq@%ejc=iX?nB*#Q}oTtELSgd z?6ai5*w|1}&qu@$sxceQ4Ljy*Ku@Ym!?YMIER+RDjMl7(Ym9HdTfBdp^Yi;3B<4%P z-k)T&i~H{-UXS)HDBp~}w%wc(eBuEped4x_`v;8X@9($vXc~_zS<+2nkVM+Yn|6nm zRtb1U;KWD7pd9{?Mp9vZhK!LdEsZ=r-T2tUlKc944On@RQh-g{-S1cS2gz($cKG~z zq5U7EMK_haAz4q(;BT1w$-jK4|LQTw?m~|F*XX}G5ZClrv;1@LUmgDM^iS6NzsC88 zZ~fPM&c6WMIg9>sNB6pwajr+0P&T#FR?u4XFXfT&6no4Y$&va8`on@;&*?x9?wOG=Fprbp>TU1~)%0teC-17h5iwH(busMYO z;(ZkNA0)|H{?$E^ZL+44!0Dhmr7L#f1G99K(mlbkswjuR!B6a6QKDjIZ|T&OES~a5 zF|l%7c7NH~W1vgwC!*{9ul2**hprjN8pL~!ZrVp3qn|=vI=&+sk;&^@5;K30;5#K& zx4xQ!?@v0N}+?R9?&VN+5&j>H1zblN;?PPPNeF35va#c+-7;wpiz z7RXxXvOk(@%TN%!=Jmp&_=G0-*He^xTC!e;b7L|^A=Q_Hy7+K%TJ$z<8}-AeN8suL z8~XH2hS7>V8q_~mTkBR-`B3S&!H^r!JVx^w<;S&fLOEICn-*Sh;fKiR0Ki%zz+8T~ zE5$yWiU@T5Sx(P$omXpE3nT78n?H2IDpZA<5#x$r>or!_m5-bAKqN1@e*t=!}E)+=UV(2o{@b#1f!mL*f(WlE8Bl-2G+S^6{m=6X67qea@GVdW2&%Z9&i ztmp6CudV{Gb)0`X9;z_U<I-Ep+jUF+v0-jL!ICQb?1P_*z!*yb9;jYktl`k zO1jY+sPUzg*ZKI?PwVp4Q#LgI1%uxhF7!(N-DxCYwFmT(fVYgdovtN=p8aiH)?dsJ zSyjW}U|!)CsVVNED0vRS_xLM$4xe?3bLSEAY}K7)s_JK~F#gM^C;4`++z~k%z2<1U z#Dv0`)p6>zuHT|JzVikKHQlR*W;=CFshM(C6xvRFda7<`tXz6z98{BHHGx+6KkVWL zB7H&Yh@K-^W{(UO9%4%m&N*sJa0hxOWL;C?Y%b~nxhUTL}z zG_0z-8r8P2&&IYilUd+8&IjP7@ir@vmd{0J)f?t(d{Vx%DN`t!(LnY*`z+%Mt8JCM zd`?~Tg)dqQzbQzKdz#(^>Dv8|KK_T4m z?()|ACRgvn|1K9{7pEdx-s2ge7G`S{QO4r-MVlR3Y-21bqcEkzK0+-t!#AV5hpMeD zq(g92=}v`Z0qpIVJeKGlja?4~edq*#S{Tc5!b7S-9HW}OR90Zm^9b`uW9JM* zeQ%e>07=eku}z)GuIyX`=L7#wIV6AMAa7FVCKl9|3YO=66-p~ zL?ZM<;@5N~`E`;1VrO_++CX7NRjyW!&8CBW9g}J6Nt)#4Gt+o)jmFSDje%#o`Ds5w zV3qT6#kvF{oE*ee>P)U5@Pkq!@1l#iu)Y}w$o5FZo4Yra8O*9K)-^g!l)8K&^ZBaC zDr#HG5kmy`Ummj;ITTg*9;1`kIpd1y60RoSMfa(#=E?^jxTO;t70wg<*h6J)F+k&*W7j8~(sQqSd5Xarn;+0j3E`)6iQrwi|5fh!q zM7tc4yk1${p5P}G4U1jTpTnTJcycab=Tu`1drX3uf-K4iLj~FK=dl1j_b)?=O~XoI zu;P>^UnsZ#AcRG4Rx3o{ayB^R{Yui;_o8bar+sI;_kOQc?|yZ7Sr7()?l@QuUmdUN zmrL(YB{|D_ZxOFx00661R%HG3o8>O8Hth?<__M^mX! zmF?~I{Dom3%4u!=cCS8b1+_Gj@&;wy{MaWXMLR9VZWM|eE3%2Psi$D!U+@zG>B)C% zA2co$ZWZSXjw8NOfmMFD#;3kK2em1+hY6t4axgrY>%%BUbHlnYz6?lJ zGju`VX4I8O#iASf@k6&Ec=Xm(Pei|l#-*>KjrU_#WZ>g!*tQ)^6ye@BNq)G7wH=Xh zse<8NIJG^^m#?%12C~%=Yp327@37RXO_z)?Jx?U{g&?Z2>$Tr1!#0=)GwP;|fQ}K0 zp<@$1HhcgWair(PiT+%tsy!HtwKfSFBxU`SOYBD$6l@=>AZKetOiV6)8oBstoO}}c zYcrNygPL?T?sRl`CdujMk=kL>M7`hGJ2Kvo&LVa((nZf{D>CSnFbh|{Nd=CA2347P zdYlDhGQU0W)Jv*=hsRYY0ikn!A9LmP^R*+_6QN(cI@fGUM(L`v52l2AhMi|4^)#!x zm6dr%G9;Oy2@^(b+v&q>y|&{Hb^>w z$EID;maXmVTX`P4U^-L5uw#@UuDCE zzFp}E%Uv?jG%agpfAw-?+N7uiPcL^E zVzc|A^ZhHYL%ds)!A&Y)@s&P4?5M4)7;n+f#H5Cl@k9T_5JdVLS&q>syG+))+-*M; zJ%35d4Ldes13dYOwnFIVDZ{k)3sgb-%EWvMSgzIISd)Z!4D!e)+CV@w=sDU2iUV!XHwB4O%^fV^ehC2vOj6K0Q&AF`(! ztVic}ieAm|2puvweDx6697P-v`N>EU13w^vK@62NO*J+p_T-T~xCn}LWY2#G` z_a3m=yKdCvG;-H=i{cNGI^id#cbKnE04Fr5%X!AJ71fQcGbv88$32M z5E?;4d)L|%vT3l>aNL|J34rZ7)sd5j0;gt788EFOnfYnQcW1QipRahQatz@4C0IxtHEsBuWtW>b$h)4KVaE_l$2x(R*|t!9&`tRttgV_A|!AIH}`i zTRtmOs!>^MjJjZ(AVoO7;_*z_hWaQjFamRB5*$hSxPh{gHN?IPdSrZjrX!;1{_A!c z`;sY(`5F{6mJsZiIyK-Ve(Jexd)yJd8Nx>YtEu$qY>QhxF^7nCIzYI!svajczBaX` zWP#SpO4*$7tcN&tAW8aplvRfkkR01HncP4mcqLEZo!RXv+Bi&ccKrnAC5*+;N-2z( zT2502p)iH6MmW{&(CcNp(A_`4SF0}>MCX94TzE?ra#d2jO>P2Swa$48EikS8(^cZa zF+c5Exlxm?8m;eV#VrZk)4{G88Zg#F6LE%mLZsmQ_)iei;@mxJwsx1KJkc6uKaY3# zt&r{6eq0sj)p2bwmtA{n*EaTWhSS&}>Z}CBZ9qhkZ~-dep?(1*JMp}XMeq1%qp~YHM;|4IY=1N;aYbYx z;Rd4yceqrQ?cp0GHsg`5fp6jg>i_wBD_&}l>qf*tiUsqbBN*v9V2 z#f2PQZ6Ngxvn-Ny#aJPoIc=T63HhWx%_y~$>?APMMb^F4ov+Jgaw29qX?xJ{eK&)} zzJ-bOVk)eFBO(x)l1gV)w=|8UtT9QvO8er{vDqlw6DITk4~N;?u7TQsMtL0*ZCe{J zx9JEP-}OV(H-U!v=<8fmsUyW@FseLt*{PpO&MZb9oTO?T@DsvM$RA*Z_Qy&iIJM<_ zN;p>J)wN^)k23{1y3U(pn+CzpN8Y=ro9%zl_rVyIil#+2*8qgs|aA%*6QAT;o&j5$4 zBhf;2{cl+Pk~;BU>5&=}7WHjr%bogU+0MIc3p`-Qq`5Y^WoG76DYAf6%LMVFCWs=v zHoi?k>?bWvDd;Zu6W*{r_t?Fk6@TOrY7|2qSC+>of`$HsgQ*?zKsLKz=@rJogREdp zIWCEzuEvo2bJhYlvd7EQ>ueP)2lBL4%<=dl_K#4 zQ|0wnFYtZ3&ddk39qKB)06&LvExy+lj*U#}akI{wZ&U*94@e?zAV=V;DG zZE-hc`Us_zh~zVk=9{EflQ#61Xd2`X;l{gt5z3JToB^|H(`RG~EI8Q-304uB*jb+K zE2(#L~VAMfBIOa!_m(B;RAw~#G|xJfCv|^I?KSM&PZvAsLK_2mZvF?R6Yw`%vG*`T^ecX%~)wMP$h6D zH?r92Qi}DKbYHQF-3i;vbSMwwm+!Kb3kB==D!WFK`Wi|w-TL8MZ^78W;X9%=l>XZm zKl!;j-a3h9p?WYmb{ahYSiMynKxp;0OFlfvVi5GG(-J8Mp^J~_Dw(kwyY6x7=UnAp zW1P6q)Y#lGfp=F3Dcps(H7h5Eh1c#E_UT?9uCQyIrk#}m;DqgYZx$6&p(jIUv{>3- ztSA{7spP0T17Q`H*)?*I&$*{i1;`r)VyO-}p{wWLX%=onV3V!J)CUKJBbAiKU$^3L1y+fD*ww0(# z#Z&Gk4YB1qDaS~X5K}^ag4y2-`h!%RY_Dv<_hvYuo6yL`-S~ksx8dQVw24EIO^313 zn$fLOYZP^a+_sguYhOM{({fQoR{5odCgCjZK)AODOSVir`PN6D0k2)WKS%^BM+*E= zvm*0p%M&FG*BeE~lZ{2Hn=7LTv>OC-!z{KLq{YvKQ*v9SAuesALessrF%%5y0m7{} zq#PN_fdo(qllR{z1B+HDkbzF(D%JIt9kcHaDoMc0!uADMyYljp!Znx>uz6rOls*9% zgMk#|dkHD`x;#kmzPSnd(!H#*@gyX{_FoTYUAY-vx%oKr+oiXN{8EaK_K50k^3yTR z)X$#*K`noeo&FX|{j_3z+8JU-IH7Lvl zqYevY`5p-=f9i;Xps252Utxv3J{*;>#wWw~kD+^f!Kfu|p?l3s_lVI~KUPI1=D%Fy zThZ|C=nP{xCP*h3-UKzT(O8wzSLr$De@=rkt|$@D4ry&a;KY8}=*{fBsCs+P%z=bl z8kX{tb-_1un<(~<2GC}sZsrAV4P-pt=&7k7+wL?C2?NrokfJ53g!>FVRWiauIma*qky*S`|o0&kSEov%0f} z`h^_%Q<+CCPZ&T-jl>5gdwO;WtDG6mx;~K9Nq+ad(p`NGTA1Cy4y4YQJuEG=qJ|fmE;HyiLBhfsZ=x^Z{qm%M5#AI)y$1;*+DKW_Re>9*c-R8>&MhH zJq5qp_W4ovlGHMT@me(_lAJga&Vj4_`_E6mh08~4XXk~zbwp;7^n-f&1M@mYUN39} zcS4I?C@x^4)sb3nzw$#Oh=EdyeIUP42@H8d30CRBXZ;4b zyJ~*!T1U_P`&0a)8Dpi(CM1G+`^CaS_M|#Hdd#?Od5jb4jf<4RNBZXI)y!>Z3Brqb zX;#p(4bN< zX&a-c^LxPYoVxrjJyn@~LE<~6t?1O~=2g3u0fM{;31o?Dh_Gep*x|V_+E@hCeGZOy zKi@a&lB6vn)TWiEze_$kyl0?}d$(b3ixsl;S<#fzOM!Lt4oNx++r z($ghPU*vJLLTJZehd!Wfo~56&hf<|etS$P0LKvDnO^2B{^XxDkYek#Scw$#i>f z;d*FqR3Z3teTtNbq!rTe{EvI|6Z4v}eFG5@?V^U0Yng-9t+CE;Wvy$OZ3{oBo%TMH z8;Q*e7`~~;nzT(lUn8+m(@L_eNjK^SgE9muvk&;?*pz2^(fN)gErksIe+U|HKW}Ee z8Q~i73t`v&q|1td5fZAwpoLHHY;OWRi!&0gbPejTIBBM#o^DB`1geYO<}!(wQW_fqM)ebrdUp8S)H}Z6MeQVJoZ+{?eVu@spqXvd_J zmo2%s8~*6Hm`N!1q@t=JmL6O-Jm_uk98WD*QJp`fVs2H(f8iR`=;G3@=g3uy0P54l zprz}=tuxiviw3_K~CX_J#Bi4;Ex*%lI7cLh{zx}OY``5 z9{MdL&?^j5F^3X_vNcB8Kpx;%19W{%X;h(L%`wurQyCq^x^9_fz4(y!eSCAh9k=U-y|7zgBvG>+daXsDIAR#yecXxs& zxCMf{L*o$K-6bTrHqtbWTW}g0=*Bg{odl=R-~PJJy@lRkaeOfPYM z!rxFS&ZV$)Y(PQEZb9mb>)BCiHcy#kORX`H)AgW%gquknNZ+Evh2k;f^Sz>KYeK44 zw;(PqjZS=VSN+0Ci|G%tl0398mm?k5Qz8PI9pqIvQ*5kLY}uGxb*dZ(VgLhrF;&%~ zCmOe=+8@`#_-sYo-{Goh3A<(vBvrHUGXoXmT3lUKNO$e?eaX+gDucBs8u80m|8F zY7Ovums28V%mu9yr~RO4Fs!Qx5Z6H&?T`7XWY+6xpIpd-FkM+6H)BKe6%g`GnzB!J z*E+MN@dnK%uqUcPkVu-JOF0bK=%4*>Q}u(SX6Hf%bF)b6`or{Fg|a+FAH8hkYXluh z)c03*^i%#Gkd}Sq$c0=6x-p# zurEK1oxPYMX#Vo6Li#mQ^!Y5$hp`-foe4W+yHiO*1V|!*QcqXT=lSBrdVBxoYuMZV z!G_hV>cmt92UopEuQ6I3LGP?%n0#N24a9 z=@sioW!9h`U3W@s!<-k9TtFC<$DVeE)zR*=zGN1skmh9OyO)YN+zatl3an;bwa7hV zs>VL91iYO(EV(vCHf-2yVZmMJmoNRV+Wx-z7r7~wLPIJdYHH#o@KiVCIKf%o-v0vQ$X;as@{Q(+grPVrAM{15#0c_j0%DNLPB{+xzD@ude1j|+&T#Du>H{-k zU0(9K$pM9dS*Ral1ZUdmv?+X(^#X32dI^mIZ;RL1K(%C* z94z{?zaGCAe>$n%&$Z)*`BkPrkKCTh`*A)gRh(!6&Mn7;_QSKEnFoL=6x1Sc(+~I+ zw|N`RZxrLy1)adiA|p!7LJ5TGuwech!I-wYhzfJpC+)4x0|f{x@VA5^Fj>;h{0yM! zg*l#YPW6*!{r6QHy&#Y(<)r%4+RJ-mc(u zQj2k81|4cwRqViXZ%!qn_{QZ%p_Qr`X(pfxA22XEr?@R+F#fNhwGTR}UUgyfWwG_@ zZO`&ps_D+wg|hpc`z<$l0F1nH&;zvqs-1q}Yc@w!xvHdNwB^*S3&PH=-?I=@>Xf+LMggYkv4H3orbcoA|VqU)f8K9AGJ$Ck5DqjyvDrxStVyl;z^)5*mtBsBw` z)z-~5EqHkA%}m&pEmQrtHVkYY)aK*GSN6scB%}3w`Ik3sFjojiCQV&WpP?>jfgV#i zwp3i0j4RC_VEc^IMVHll<0|Vd1?WXVyxz_G=(-`_t+u13NvJV!EjkO|o7mr#>itEdlRb4^6$SJ}U*Z_JnqFY&I=RLqHsc2P!fdIAjo3~gBhKvS>22xL* zL^_fN)We;EEy=nXEqPp$uzrB8xLIxYGTp{r4;U99^&guB!7z31DP6#B^LHwhAXpMg!oMjkvBMGIxorzBXnHy{L` zxqJ^9wS)$>O2wMDq$4`ook|t@g5~5Gd9H?Qm$~+66Wwk zXuFP?*$SswkRF@Zh~nc=KPz%6yUTx&k2MmTB#87=S$6&P;D7)XPV%W0!3?)|lC^G6JVGTEN&l3r;M|K4Fw|6eyo261!?!!o)j!SzWms(^y z_GN`ea+S{6rRYIGzX@v+EbO=;6x!RMTi=nC>!lYJ^*5To;vQk6T}jj?vIjI|(B#~w zdV?mf{A@e9l@R)<$8e%kb7jUmg9*YD?IhZ1JxE~RWc_{ll8C0RN8H)CAIZI&*Gm8P zrCzPH0Mz_jfv>q}YH-6%m|X0P$@J1-M>~?+Kj1=JC9O8V`)Eqs20W~wfNtCBVNcE_ z!-b6!&QfUDB{N%OED%e(n59WBCeu(FM%ju&m~rxNdH!3We=trl8&Ag1w2D2?d-0Pu)+m>dfok|O)L*Ij`H zK^;aEbKS3ZyLJH%PxU;X?&Z%Uz)Q*ihjZWrDvYoe2jQBLjJ1eeLO%y~RRtph!4;-V zV|x>(Ocgte&j^JmdPB&Ufq4DQW9-8uir17RF0SblG9r}4Rd-e6o3-GDyR zu={&|I3FqV+S!w@g`jCd5lU4$84;5**DI&$bd%iCNvV2e)=A2%0uy^%=JJdaym&#b zL7|XvKD?24s8#Qa-8+^$h7u$xO; zK1tFzQGD}x`pDd>L_htdjmF@@`dCl<0{Ji2Ak4b6yYbczh88y!3)kmOWpnOoHG`aT z`TK?iUj<#+(6+9&k}2LO8wj`ZzYx3)xCBaEba|}_3uYP3+wkcdyw_H74jPiI3Afu; zv4fQ3G75OJIRx@{nIwsi+Gz1)W?DZMF7J$wJbjGk=%@6Kkk8;WT87lNT82)>@cU+x zM<~q?lQFmCSN%7iL8}X~fC76#S47i$3z(pP8-}kTrbIW8Z|ZB*Li7Hy{id7VwExoR z0{Gx6U%e-ll%Ztzfz*Yee*uWo+LBSV2@u#tJ8#RuiZr zLo&DmBj{m?n^D^Rs|*%2a%w!c%M1IOn;Rw^uM9R{ZRl9QW|X>(d~Q{oRB^cjJ&7~? zdZAog%JmWa>Mi0&*4tvrv;1i-K`er;YKWFOv!gF;j-HvwtdlA%DelV|rX7Z{+EaSO zwbg;DQUic^q?LZ^_^=F}(``Xue;%X#uDs9!Gw{#k+GO4~`u9wvbr%&9Wr1%I z4r~`5MR#f|b@Dgace^s_3=gPpDKg#8xkq#8E>99ltMZ;VpXc%>lFeJ^N1O8`b4`n@ zr#lmHAu-Z*y6ZZw6B7qsc+5Yfkk@MxQ#JbQqGc)y<3>+?1()sTDJs?Az9hq>)2;hd zu*kj0t?=Z{xF(eJ%ZCS?h;DlF3X+mv(UJH4y#~2OzfrweyMDp$altB<{vvh!JL>bCk z*ocnanK3J4prH||#4eGA9|CzQ8RpwL1xe_dcOg9@=5u6UW zRI_d#3TozaJauMnP1BuT6H(Ojd?0w{sNvYyE_(lQWeRcF+`Xx7G}01_S$`v+6GWAe zP<3RpB5_#W&gMp#Tm$z0`B|u~hv!8;H@lnpAhTaCmXOCz0_f0cUplH!3xf6Vmil^m zY->|BulahEocx|eupC!0%QPhOyZJk2BMt7`6m17`^?sx_Z8c13I0CCZtIkU z<(69_JN}MwyzW}*3mprS@DfjnU!GRN?(Q#+L-TNli9pmnlTUAhNkdsDFj}7_4q3#;OQxNY z>ZAOah?;cT6DE^DLy1PSxXgx+1B=C5`|fqN>!y39CB_1ojV}^_?zp6f{mjS?ZT9>j zc|m6q`mXdTfIa1WBgU{M6r0s_R;rf)?*>+};$$lHs|5}nL);Kc7fIGt%`_d{j#@-; zBPv=Ri^a`fkF9?bcgjtFD`>5;8_d4D5?8O)_zkyR?|JCQbm<#O-@;`8LDG%<_lS1S zoB576?^K^y6NGJEB)cT!)lyMG2-hS!E#1U}uL4-QMF^bMeE)l z+EaJDPRF}?Nb75SGi>zT)>ltKwmE5MJ zAfA`(s%`UwuGyw9#ClmxQFF3(0Q8P%B}bE_%;5%21er6t-0{lUNY4X^F#;|IFuY3GhUZQ3w=??0d;vGkcf#(>N=21$4=DD4$aJ> zIJ0j%@yZ}AW5TGB1!kNM4iu`!&|&IOsB*$j3;C`-ec_fGgo(?4#H`LUd}eKaN1Otv9CADOuDr zjz(i`$EJ393?fPE3WLm~x@BGpfTR7E7D90cGySC`IDuvTF%Uz=SuoU>W|f*iiNc0| zWpGxas?(A`SNFX0dBF8|sg zpKy)u<1CK?!TA!Yto!$MYW=)G%A0U@k9VZF(rbQhArf^JCw43UK7tE&8 zZ&DDuh(sdKZ1`a&D6D`YvZ0T!;`#UpK$nB;DL1 z(4)G#l`jl9@o9U=yk0CJY)}?U^0sbSSdw&Sy=|OoKHZ0T;~a*DnKq4&HEH^1kb=LD zh<_P<5K~xb-#YYPq0NKV(oEVcn;%#9dluUYB4lR+QF1pmdn2;A9NB3+7Y!b4%db9Z7{HO9+qmX`^$4@KsZFI{wpz^MrwJdA1Z);gqu zkT^dD9F5!$QpQ%NlOHrj^uk0r$fzuH&^p~p**3Adz=Mh`DU(TCfhMC=_m0?Rj1|nT zi>?Zj0mH^`30@MB$j8@eYt%5&ehyKo+N0mVxMLHblX;UDlm3`}vou;iGIVgg&S63G z&^r%Rw#+|;xiBe{bU(2*r+Gq#!&&J)8lt8+BLnPmSUvVaQxGB)U*a|ka2D3JDYH+( zqWf`sxqh^#ox1Un%TT%RL~)Hk{lnb4Y#R(us>qprjA-1RsvtwK02UC2irs2}vg5Qx zG#6UI{u?EvhHV8Z%a5;1^Efxq-s3I>S~;-JbG~r-VXSm{qRie@bv)YvE#B09_J|oD z>l61E0jtQ8O>9LPX+gwy@fu};$H+$Pz`=?lM=KtIy4rq9|NWfuK&|?xF4Qx^A>1cP z*2!|?^HKgq3JbQ2x?`MWR#b$PWm+{iXGHE=*rUDT92*O7esWFN3Rko&&v%zBTdOD; zsszq|bIYBOHM6o@*f)+Y3n8AypHF$Mqhma-)ULWh!I{6K)9r#2skI{Rk@+y${&SJ> zk6ba|;Y4@C6}Q8Ca{;pG+C?l1%$6fL$b=d8Q}+bak|}PIG=!j%7F!vZ!ht@*o=l7L z0*9A|%PS>dN1k?5641V2n$9*@*!r2SK1^)w8~3ml^ZLY601q6+p@MBqE}=x-omC|BSFlLfaM^%!p{LIN>VkAbf`REO)*Xn#S5%nI@wvJV8{V zFb5tjir7?}2Slk1A?8#F__Jwi{}O>%%H0Y*dd+L8@XPo!7^0D`_d$a)ujm)Bpp>ED zlw~-3Uw0_!%J?@*%6loF*cyU?isGy-hjmlUlHSdrakY-owUkc<>2d+Lk`3&*stz;k zI6v(YebrNva+3VI`tLBB^Xp~dSeQKQIu12g=X8^OmPhV43=a|Rn=HUX_+TL-4U)W6 zQAO|ZRpm+gPiLgl*M>nL__p(?!+f@tPseAYiHotLc(8E`+@$F=vB8RqfVTuCbeHG0 zsP@VK#9?FfA-KbQnY8@c+*7$vqykUk?U|&D`|{OoXc&Eus&v+!_$~@O>;uqlN)(mf zEgVBsW=aM#D`6Kvt|OZC^wmdVlyBEYBxX(?&&{Q_EP^>D`qKNr2)rQ_z; zEpX)fVOm|wJ@LuUh)-!&0=RWN3J*|WRda)&W`>)~72taYSrpFgMhLB~GPJ&AFszc_qn5cn))Ava+Ke2esOq zkh9fELV790UI!IZAHq`J@28IbM)`L9cd0T_+?TeC;7#zo3e|5En5H+~dc;=1q-({P zMKS%@gt3{|R`9)#Aa#E2p|f-HK5s)&YxlLPXhXe?Qf|-iE7(&bEpFB5bUTfUC_N?F3%UW4X`OL67NKnq&zu8 z5HE0MJ50}`tdL*-VFa$>dhc}U`jof%D$}zAm|rE!o<6ue8o6$_ zq%B^U5g-4VdIL59Wr=qJNOj2JQ4~Ez`Q*L4_cPJ^}*L{dv#uXMu}2 zBE>c{l)zKMh@zq?cH@-^fZotwdgFn}9=m!Nf^pVb*NrfCZOO54T7G0^kQ%z@E-X$> z+6`kHeQ8ERo8P`oVd)Q)@U*BV%e z9RdQB;HG{{_v{58Nk}jMbUug4*sg9hqVeV;3IC@=u)FRXiQg!NFFAgrY{37iI7nwg zzZKefxwbRYR?kr_mPp4yWK?@Zmq5S+>*;Ckp&slows1?T9e>3&UbmXlB2#GEVzC8x*)DYmrmEf7U=uP=tF*$0wSUzCh=7!%nRYm0t6>YP~cZgR2B#?QW?_ufKG<*i=E;Tj};-K@LF;2ML3FhYHPYl z$}ns0|J||wr6FhD^WbhB7mz^4Q{oA!Fh^@LQAXiB^c@%fL1VQSZyj-XRj=F&*PrCW zZK;E*R59vuE4hNp@j6v1pU~dRP>G$@*|Z=xOGqI~{wh`T95jN4;$5Rl%|bOn*AVnf z8(=~@g|i^Q1_Cgxfa~b$MaD7aqxgudXhC0DG0b~3FNFepG>9<2g5f7+rTIA>qwQ|h zD-xOty#aL~#aU%E)Vlc@PBD)XS62DV;t%Jq52%(lmZ0-r#JF0T=3Cj$gw47`*h@v9 zH5_M|_9BJ#tws$g!tIc|Qe&}7VSYQ?w4#~uV1-vr_M6YtrA4b7g}-wvI>ZDadV5mq zq#H&Qxs3!};zB%TnkdV5$V`Ko$I=|%v1xQx5n#7!iC0N$91;1c1h09VmZrc*t`h;J zQ43cRbNA!sbcWOtlT6rDW}(taa=F$MXj~s@2jy#+tEvvBC(Ko(yrL|dh`CNP4b-@3 zHFH`FCLIT_N!*bYM?y|iqq|!RDktWOss`ncuJi(l_3iD~1ykW-p=N4qy?yp7_gq9i zXP;%2r-5_@WNBL3Hr_Zr-Am&$>Cj1w!V&riBFnl(Dg`*m&|_!AY6SJvjie=3x6;bc z&k;?6BRN%)Oe5#sF2N!jXl&#C@kPh4w?!xhD42{WbRTSB7y@Zb!*s%GzDc2D!kLdq z2B&M&fUp3mKtrm-%szJ)({3wQ7Ew<}^6=Vbz7GSRTsv_e6^eQouo$XNlkwEN5&A-q zUZycXRD=V+0bt?Cv6xSqe$v>Kp5NJ=+maS#dn-=b~HW5{|KtL^O(H}5qBA>qn z_V0jiA{WQA1`OuMh78vp4P4X2`)Z|^%&*AHD;ZVBbE_>>d00?4WoOa z%eST2d^TK5MR~QQzIwtbpT2g-6aHq(g>%ryHMmPhTxOOPKw=T5uSrH`engspMf0rw zc+`vsk1a(&Q(tL`nZ;on*cD1@C`e`K^xlb^l^4j##k;8S5b6gKqbT zynOl_Wu7vm&Q@&FQakutZXLqo`_hjGwgv<1!?v^J)UlV>O7u05m+^F+&uUaFNh5>= zsx7`pEarB63TCG3wLNNyoz=3>l+p3qfR7d@VbqA4d^Anxtm1l#)T1pS!?g=#K2ma4 z&m4legoc^SRphmvrZ80S9rQ^>tXxYNl)Kk94xN8$+~&0K>+*j9ija{wQab8+T|Ry3 z_AVwP{Rx%S{<^b;`(Hgt`Kx#B6Zf77bWGWVbh+zFPoc>enue+jHmA%`G7LJfj~lc* zcTKxx{8&`vdC7Y+@xOR#@sKOH7lw3zq&$sNbRPJ z%V`xmLGeOK3I)_s+f~XJX{YAGWawnHN-EuU4Oz7wn+8CAT#l~$Np7dWq2XPIyHWzc z@N2g>y1!AN&#%pgyn%(6XF|1ke;ZcvPh;;10`0yP1((~cox^XHe^vF*dvDM%WV}5D zN*VFz+y2`{+5gpj0=NIo2qvO`xARxq6ONRlXVRByqyO5cL;rB8q2^!h(EZu8FV&Dh z=*O;^fAV&_lv&e+WTxBXQDnQ~NPZ-0lpioBF=vi*%#K(?c}PnR;|ogo_jZC*;dMLV zf1;^R(^3{(kkk(28Zvqx_4w|`$Njil(KN`}=MTT$3*K)2(%eHUas%JE|JZ(55E%PU zgf)K?<`{M$?|$4fx2+R3Bi?}6=w3c{h-+NPGol|?99t|SPIG{2oTLSaVX8j$8zh@f ziwnpB>nIfKXH-0~HQv0j6tr2q(HstNdy>U#>dLsxTaW^;WTcKLf``%q3STTPj}-|r z;+c-Bl0_LIT;Xn|-_+Tc$PBbIwW-8evRWGgE`(su3)5ri%2GasdGw4IivIxa1|)Nf zjLwtSIAqroS99A%*b!lWEW6&pE<*6Q-qXf-N9;M!5B9=ee`~75mh9JRM>P0SJTFg} z#qEGO?<*ywf)|HQJzGSk2_#vCnpf-Lns{Q=()nPMV&JzD@U5-d z_$WZWMzvEs^AWEjb0%KC@iZ4{TxYW3I6-e7>9*UdWgw*sp!$1ygx`=2086vz9t~-o zpPhZb{5I39RW}FE?H0e*Z8Y-$X9nulOq%l5Gt+5yx?@rTdC;8D(AYwlFrH645jEPh zCaU&Bw03_a#Ub!lJM>*`ss5ArPhsA@TTk6Jn1%Rs=;zNma)<$}lE6)B%rZU&A!IEh@4O^VOpDBiVb26+>g zHkTIiXV{%{lKb%c@R}n623N$;2L__+*>b5XU&4p2b^ZLtvQjYc{YO&l9+2>BT zRC?@*tQtbbqL~ByHmd`6-lC4q9LbuEUyW|4d%Hl}_#=T0fmGkJ8~W|!8F$)fS89%| zZ8_q(!-f;Sh~d!IO;W4JTLd$_B#aL0y&szG7se{MrVa}yFo-qbMssV7Ry+CWk6_Eh zR3T#uUE0V7aR`5hXwRA0<+DXX^R7~)G>cfDROJkU#YI4MgH1JwkZ z=~byPFE`U(k!udLHNG~yX|Kof;wjtN&2wcR?aF!$1eX9u=WL?pDs>wZ;kqtb^a6Nw zZcc2Hj6iM?EY-1$S1J`>dZ*rXX?z!i4ofAxrKzD&s=+F*rd^lz58$u9vU{c8q&OgN za#d2)oCpS|g`rK}i}EtkcABUd7-J8MB*EMQwrgTILgZ=Kb~t04N{#0)U+?CMlOc=P zSOqXutPGsk21KYA44`fFbzh&WAej(@-X17;W$2d8LwM=r`02FL9@yjPKJOc{>cnb> zkjtWAN7SZ%=fG!-3{8r2zO6$Jk?uL&#x*$MlY;G%I-C;2%>JZ`JdfXaDle~zxspP{ zcC+2|xt|9!)|L?J=scNrshMgqbYF4QU>@5q#$U9zR^k#Jud8%q1owsK-oHVtiw zbJ&xr)gTK_a{BIahx0g{c|I52ZMq}wh#bXZjhL|fX)Pk|Ae?r6DWz@YHBbNXV^Moy zOEv^mUL3bFA>z!skTGdTvGL$r;`8(*-DBUqNM6>`MU$W}N*mo$4)3HtiLZp&I!M3D zG|A-mP@)2jJi!w9`q^aNZvu3tV3GW>PD3+?UoPpATMH6Y>MtPa5u#+8Q4Man`TmgFIo8gE75b)FaKk9S5)m{S05&ns zPI#06GC8cGyZ06GGn~xu`1y9Hh&?NGV5C7L1RGP9G$R21-BoqisxA6;|8)EZoiH>*8L)Lc8?j)B);3y>>=1Q zM+skkH!Fioy(e%$62H}|s%VOm?v;d{)%gspy)?&;0h@@dv9JC~T}Vj)joPCh&2MK)x9;%RC~ovlwEt z8#Qd^VXni0{d_t`+fvJdWf52^<^8lQ5rA$gxzvd&Zvt4NXP)RSOSn7IcPPI7RFUhp zMd8mVCkDvHE85!M7GT1hj}N3i9S}tDS&B9*40p3auS@xR)Le%jQwH!K#uU}$#l5-u zEH^;f0GkV*rFamy;QKL*f3(C3$;v4aeanjQw}S*U-h@}rmLWC0p&23V0wfu{+56ef zBgM=+eYiMPsetVMIwGresbr9mDRbUPH5InfVN*UJp6^u8KU8vSjCIVvLtkT|q21ID z-iY0kA}90nU8e!?(b%fQ!br4Y0U=_aFBfRP>g9di|3!CbKug_0>>W*Fbc!}DL@Kty zIJ-aG`>?s@G}WBJh)57`IO0h1()Q!AvA%d6=LvLDCRZdM5|U$`qNnv(g@6~iuE(P1G+R9(6I#G_NNt9ki( zJhqz98i#!vp|FY3q34D{$4twGi{wKeN}py<rasV0~ zZdZo1r`|aj09YwfiiE2ZY?tdLYE)WaZfd*&V5~W6e(rtz%;O(xV(5I*t?-E|6d>iQ zKumj#p#cZG_^aK=d@?(B_&x^N3uIw)WyY>D;EwOsQPuJb9G zX*)|Z)4PrCEWwl^B^`$NmV;=!6IbRPb>jxD&y<^5y^Q-JY!`v>5;^|oeCM3T^RuBd z4#iI=3M{JBV4`O6VDH~38RD*^-n-)!2%IV;0Oj#AI;p}KO4x_z7zSL9c$1&YO(c_{ z%JUP`WfML==zf5yb%|kVk(`ACX7Hla^Rz-DuudiFg%_j2oGQb5-@)LpXncwz

yQB0zT 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 Z6u8++>l&V=ouph6PTHbTsLB6t0sv_RMx6iv literal 0 HcmV?d00001 diff --git a/config-ui/src/plugins/register/bitbucket/assets/workflow-run-2.jpeg b/config-ui/src/plugins/register/bitbucket/assets/workflow-run-2.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e561e13052dcaacaeb7f67f4c88fa85607181b6b GIT binary patch literal 52643 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 z%0D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 literal 0 HcmV?d00001 diff --git a/config-ui/src/plugins/register/bitbucket/config.tsx b/config-ui/src/plugins/register/bitbucket/config.tsx index 6d7cc6237cc..9f279e27d17 100644 --- a/config-ui/src/plugins/register/bitbucket/config.tsx +++ b/config-ui/src/plugins/register/bitbucket/config.tsx @@ -69,8 +69,6 @@ export const BitbucketConfig: IPluginConfig = { issueStatusInProgress: '', issueStatusDone: 'closed', issueStatusOther: 'on hold,wontfix,duplicate,invalid', - deploymentPattern: '', - productionPattern: '', refdiff: { tagsLimit: 10, tagsPattern: '/v\\d+\\.\\d+(\\.\\d+(-rc)*\\d*)*$/', diff --git a/config-ui/src/plugins/register/bitbucket/transformation.tsx b/config-ui/src/plugins/register/bitbucket/transformation.tsx index 40b2c5e3862..60d1e17921a 100644 --- a/config-ui/src/plugins/register/bitbucket/transformation.tsx +++ b/config-ui/src/plugins/register/bitbucket/transformation.tsx @@ -20,12 +20,16 @@ import { useMemo, useState, useEffect } from 'react'; import { CaretRightOutlined } from '@ant-design/icons'; import { theme, Collapse, Tag, Form, Input, Checkbox, Select } from 'antd'; -import { ExternalLink, HelpTooltip } from '@/components'; +import { ShowMore, ExternalLink, HelpTooltip } from '@/components'; +import { CheckMatchedItems } from '@/plugins'; import { DOC_URL } from '@/release'; import ExampleJpg from './assets/bitbucket-example.jpg'; +import { WorkflowRun } from './workflow-run'; interface Props { + plugin: string; + connectionId: ID; entities: string[]; transformation: any; setTransformation: React.Dispatch>; @@ -33,7 +37,13 @@ interface Props { const ALL_STATES = ['new', 'open', 'resolved', 'closed', 'on hold', 'wontfix', 'duplicate', 'invalid']; -export const BitbucketTransformation = ({ entities, transformation, setTransformation }: Props) => { +export const BitbucketTransformation = ({ + plugin, + connectionId, + entities, + transformation, + setTransformation, +}: Props) => { const [useCustom, setUseCustom] = useState(false); useEffect(() => { @@ -42,7 +52,7 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform } else { setUseCustom(false); } - }, [transformation]); + }, []); const options = useMemo(() => { const disabledOptions = [ @@ -58,6 +68,12 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform const checked = (e.target as HTMLInputElement).checked; if (!checked) { + setTransformation({ + ...transformation, + deploymentPattern: undefined, + productionPattern: undefined, + }); + } else { setTransformation({ ...transformation, deploymentPattern: '', @@ -85,6 +101,8 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, options, @@ -98,6 +116,8 @@ export const BitbucketTransformation = ({ entities, transformation, setTransform }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, options, @@ -106,6 +126,8 @@ const renderCollapseItems = ({ useCustom, onChangeUseCustom, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; options: Array<{ label: string; value: string }>; @@ -204,39 +226,52 @@ const renderCollapseItems = ({ Convert a Bitbucket Pipeline to a DevLake Deployment when its branch/tag name -

6 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�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 z%0AEB8G!EgXyOjg60YLo`|8URs*1OWpWz>w#5AaXQ`6s=dj~)f@pm2xB;B(2AD)v1yxC{o#jX66<8cRID`%1|!Nw^s zeKOQ5TPB340cR)`f6m=7sMTCz)TgDh_^|pMBDla3Y)3?&0XN6mjJx?N;x;@<6_k3a z^lq0@cw+}oQpvYag6doN9bnS48&!p$e|u3$-MMIU%2k(BEYf)#F!QUlDs|}my4Zay z1tx~Zy_@>G60vqX)FFoZAMOB=bvZ}I5`j%qyCyagsvd#s*OixAX57%jbJd-3E_vU3 zKm_-1N`CqIQr`g-79QRKp4dpNwxK>LT#CMSOuqZLivs?gn;e&R1KF4Vav1P8H5X?; zC2o@%p4~D{2KIU1+^)SX34q;5q4KCn2b~*Qq5qN7f&c9D9QA93tB|rg0P|AdP#HG3 zGVnL+{}-I7YeldO$HWT^_P+=+9$9Z;K>Qrd-$5^Wp7+J6qCNmq9d%@A_}gg? zMuRMoGozQLKkeSE*SCV}cry&3FGhPju`cefK(dl248|??Mx z$pOZj@=6H}ltK|+DBeR^R4CY~L;G9o_YW1?zlDOwXU!L#Kg1ryIjwKl61FaoF)(F$<}i+S6uw+1sK5dkySBaiuT^0uO7Q86w|w;O#8ZN+Vp}7J$l5czt@$Ea&8B; zFj6-Fk(0!7gW!sN5m zL8>rT6^qGDF}?d;bkc5A?`0m2__&SlgVS|byv{0CS-fMb41ZE(&+@l2mW~#`e7#(; zzi;S(=T|IwADvu3Q)*{#F;5_0*Y=0<#@^{x%Wf{eX=0p%u3kZI4$uf}#P5LgK6>ah z>n|lR@4bq^Dx86xuim5DVCZc8U3QwV!1k811u%YKwH}Zw}9%K|OdW1z~eS z!MIds4egYJDrs&e9c`W~^Akks_DpO&#Oe=vh)AM&y3cL z_LCG8E{}~?Ro1u6`{Z(&o%K)T>ZV8*nODozV=1!wr0Q=81(xrJmibz|+DJQtvz|R* ze;0ak$q~h=rqvp%?!4qamN>wXMkH$iVM&mI%6~U!NgJZmh~FSg&7(0zk%&9S8dHm- zmgq8HXUANP&=FbpfT<{mlNJ|JtQV5jV= z3XTTi59sKm=r+~INwwUo$s+vub@$3@osu4pW-t>i&Pg;AD7u46tni_7kN-#pP?udg z^MwB)?qJ;;VIbL?rT9rD8~&bBes6&a98hm6zH7o${W%Z-o1Hf~)QZfquLX-&&7DGC zY$+Aas$TyW5@DUu@8X3-<;bmfV3JR1(thH*(ay}jWpiZzgZ(r=YZzXoN#K1%yqg;I zkw6OnMLe8a@*52`erg!rPh20rLCg(-Ws+q?H?=&2aVoqG0 zND8FA67hx{I=DL=U;h8#|F_2fl6PY(=4Y0QTJ_vu84=y66q;Ju=1!~q#}v4l2ri)- zJr*8VM3&0LjmO`z**wY{7UrFwPO6rl%&KM)C1Vz*K<_-T-4#F76^x5TSD*(CVJEVr zDPyIDgv3jc(1eT-jF3%tpndIpP>kBP>BL@9{U!@&^S(J{ucfXS#k{0OVFU2=jB^66 zTn}$noenSXJnT#WyCxx;fk_Eexp9Aq8SEri(7Cwj&5&PlsIJNIqN3$@nXPvK?~LnP z^dBlZT@%%phsn2S9W&Jmy1yQ|2L*v6aeyEyZ#4m z!3DqEr7*!R$zLLAO?6y}QRN_=Xqpj=XWtgg+F@9yT@v`Dl)!d zqJN3@<-lDXkc2@x-m!SjEmija@tjl%Kv*5D9Gq;NsJxx^dnnsj+ujJQtFh4?a&tK6 zGbH+?_xn)2=Av(lbxHB$>_N!P;;Ezic{WpoT2?1N|2>;1*i{ i`aY{_)*sWx9!p&+H^K!+2iwe{|5C~S;9!%xxqkzFacfHe literal 0 HcmV?d00001 diff --git a/config-ui/src/plugins/register/gitlab/config.tsx b/config-ui/src/plugins/register/gitlab/config.tsx index 9caf5260af6..c2f381e8c95 100644 --- a/config-ui/src/plugins/register/gitlab/config.tsx +++ b/config-ui/src/plugins/register/gitlab/config.tsx @@ -74,10 +74,6 @@ export const GitLabConfig: IPluginConfig = { }, scopeConfig: { entities: ['CODE', 'TICKET', 'CODEREVIEW', 'CROSS', 'CICD'], - transformation: { - envNamePattern: '(?i)prod(.*)', - deploymentPattern: '', - productionPattern: '', - }, + transformation: {}, }, }; diff --git a/config-ui/src/plugins/register/gitlab/transformation.tsx b/config-ui/src/plugins/register/gitlab/transformation.tsx index 3ad9b97c6f5..a0c55a25ed1 100644 --- a/config-ui/src/plugins/register/gitlab/transformation.tsx +++ b/config-ui/src/plugins/register/gitlab/transformation.tsx @@ -20,17 +20,29 @@ import { useState, useEffect } from 'react'; import { CaretRightOutlined } from '@ant-design/icons'; import { theme, Collapse, Tag, Input, Checkbox } from 'antd'; -import { ExternalLink, HelpTooltip } from '@/components'; +import { ShowMore, ExternalLink, HelpTooltip } from '@/components'; +import { Deployments, CheckMatchedItems } from '@/plugins'; import { DOC_URL } from '@/release'; +import { WorkflowRun } from './workflow-run'; + interface Props { + plugin: string; + connectionId: ID; entities: string[]; transformation: any; setTransformation: React.Dispatch>; setHasError: React.Dispatch>; } -export const GitLabTransformation = ({ entities, transformation, setTransformation, setHasError }: Props) => { +export const GitLabTransformation = ({ + plugin, + connectionId, + entities, + transformation, + setTransformation, + setHasError, +}: Props) => { const [useCustom, setUseCustom] = useState(false); useEffect(() => { @@ -39,7 +51,7 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati } else { setUseCustom(false); } - }, [transformation]); + }, []); useEffect(() => { setHasError(useCustom && !transformation.deploymentPattern); @@ -49,6 +61,12 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati const checked = (e.target as HTMLInputElement).checked; if (!checked) { + setTransformation({ + ...transformation, + deploymentPattern: undefined, + productionPattern: undefined, + }); + } else { setTransformation({ ...transformation, deploymentPattern: '', @@ -76,6 +94,8 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -88,6 +108,8 @@ export const GitLabTransformation = ({ entities, transformation, setTransformati }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -95,6 +117,8 @@ const renderCollapseItems = ({ useCustom, onChangeUseCustom, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -123,58 +147,65 @@ const renderCollapseItems = ({ Convert a GitLab Deployment to a DevLake Deployment
- If its environment name matches - - onChangeTransformation({ - ...transformation, - envNamePattern: e.target.value, - }) - } + If the environment + - , this deployment is a ‘Production Deployment’ + , this Deployment is a ‘Production Deployment’
Convert a GitLab Pipeline as a DevLake Deployment when: -
- - Its branch/tag name or one of its jobs matches - - - onChangeTransformation({ - ...transformation, - deploymentPattern: e.target.value, - productionPattern: !e.target.value ? '' : transformation.productionPattern, - }) - } - /> - * - -
-
- If the name also matches - - onChangeTransformation({ - ...transformation, - productionPattern: e.target.value, - }) - } - /> - , this deployment is a ‘Production Deployment’ - -
+ {useCustom && ( +
+ Select this option only if you are not enabling GitLab Deployments.

} + btnText="See how to configure" + > + +
+
+ + Its branch/tag name or one of its jobs matches + + + onChangeTransformation({ + ...transformation, + deploymentPattern: e.target.value, + productionPattern: !e.target.value ? '' : transformation.productionPattern, + }) + } + /> + * + +
+
+ If the name also matches + + onChangeTransformation({ + ...transformation, + productionPattern: e.target.value, + }) + } + /> + , this deployment is a ‘Production Deployment’ + +
+ +
+ )} ), }, diff --git a/config-ui/src/plugins/register/gitlab/workflow-run.tsx b/config-ui/src/plugins/register/gitlab/workflow-run.tsx new file mode 100644 index 00000000000..7245c4d0c9b --- /dev/null +++ b/config-ui/src/plugins/register/gitlab/workflow-run.tsx @@ -0,0 +1,100 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
+ Example - Convert GitLab pipeline runs that have executed the ‘build-image’ job on the ‘master’ branch to + production deployments +
+
    +
  1. Go to your GitLab/Build/Jobs page, where you will see the job run history.
  2. +
  3. + Search for the job ‘build-image’, and you will see all pipelines that have executed this job (highlighted in + the yellow rectangle). + +
  4. +
  5. +
    + In the first input field, enter the following regex to identify deployments (as highlighted in the{' '} + yellow rectangle): +
    +
    + Its branch or one of its jobs matches + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify the production deployments (highlighted in + the red rectangle). If left empty, all deployments will be regarded as + Production Deployments. +
    +
    + If the branch or the job also matches , + this deployment will be regarded as a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/plugins/register/jenkins/assets/workflow-run.jpeg b/config-ui/src/plugins/register/jenkins/assets/workflow-run.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..d67bfa58a695b6dc5d7ab14679f95a8c61175413 GIT binary patch literal 238201 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 z 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 RD4PG+WB+?z4g9_GUjPg^*LVN` literal 0 HcmV?d00001 diff --git a/config-ui/src/plugins/register/jenkins/config.tsx b/config-ui/src/plugins/register/jenkins/config.tsx index 9bfc02f4e10..431b880990a 100644 --- a/config-ui/src/plugins/register/jenkins/config.tsx +++ b/config-ui/src/plugins/register/jenkins/config.tsx @@ -56,9 +56,6 @@ export const JenkinsConfig: IPluginConfig = { }, scopeConfig: { entities: ['CICD'], - transformation: { - deploymentPattern: '(deploy|push-image)', - productionPattern: 'prod(.*)', - }, + transformation: {}, }, }; diff --git a/config-ui/src/plugins/register/jenkins/transformation.tsx b/config-ui/src/plugins/register/jenkins/transformation.tsx index 0a44f1dbd44..61a223d1e47 100644 --- a/config-ui/src/plugins/register/jenkins/transformation.tsx +++ b/config-ui/src/plugins/register/jenkins/transformation.tsx @@ -19,16 +19,20 @@ import { CaretRightOutlined } from '@ant-design/icons'; import { theme, Collapse, Tag, Input } from 'antd'; -import { ExternalLink, HelpTooltip } from '@/components'; -import { DOC_URL } from '@/release'; +import { ShowMore, HelpTooltip } from '@/components'; +import { CheckMatchedItems } from '@/plugins'; + +import { WorkflowRun } from './workflow-run'; interface Props { + plugin: string; + connectionId: ID; entities: string[]; transformation: any; setTransformation: React.Dispatch>; } -export const JenkinsTransformation = ({ entities, transformation, setTransformation }: Props) => { +export const JenkinsTransformation = ({ plugin, connectionId, entities, transformation, setTransformation }: Props) => { const { token } = theme.useToken(); const panelStyle: React.CSSProperties = { @@ -46,6 +50,8 @@ export const JenkinsTransformation = ({ entities, transformation, setTransformat style={{ background: token.colorBgContainer }} size="large" items={renderCollapseItems({ + plugin, + connectionId, entities, panelStyle, transformation, @@ -56,11 +62,15 @@ export const JenkinsTransformation = ({ entities, transformation, setTransformat }; const renderCollapseItems = ({ + plugin, + connectionId, entities, panelStyle, transformation, onChangeTransformation, }: { + plugin: string; + connectionId: ID; entities: string[]; panelStyle: React.CSSProperties; transformation: any; @@ -73,24 +83,26 @@ const renderCollapseItems = ({ style: panelStyle, children: ( <> -

+

Deployment DORA

-

- Use Regular Expression to define Deployments in DevLake in order to measure DORA metrics.{' '} - Learn more -

-
Convert a Jenkins Build as a DevLake Deployment when:
+ Use Regular Expression to define Deployments to measure DORA metrics.

} + btnText="See how to configure" + > + +
+
Convert a Jenkins Build as a DevLake Deployment when:
The name of the Jenkins job or one of its stages matches onChangeTransformation({ @@ -108,7 +120,7 @@ const renderCollapseItems = ({ onChangeTransformation({ @@ -120,6 +132,7 @@ const renderCollapseItems = ({ , this Deployment is a ‘Production Deployment’
+ ), }, diff --git a/config-ui/src/plugins/register/jenkins/workflow-run.tsx b/config-ui/src/plugins/register/jenkins/workflow-run.tsx new file mode 100644 index 00000000000..f156f4e7e66 --- /dev/null +++ b/config-ui/src/plugins/register/jenkins/workflow-run.tsx @@ -0,0 +1,97 @@ +/* + * 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. + * + */ + +import { Input } from 'antd'; +import styled from 'styled-components'; + +import { ExternalLink } from '@/components'; + +import Picture from './assets/workflow-run.jpeg'; + +const Wrapper = styled.div` + padding: 8px 16px; + width: 100%; + font-size: 12px; + background-color: #fff; + box-sizing: border-box; + overflow: hidden; + + li { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + + span.blue { + color: #7497f7; + } + + span.yellow { + color: #f4be55; + } + + span.red { + color: #ff8b8b; + } +`; + +export const WorkflowRun = () => { + return ( + +
Example - Convert all builds of Jenkins job ‘Auto_build_deploy_to_demo’ to production deployments
+
    +
  1. Go to your Jenkins job list.
  2. +
  3. + Locate the Jenkins jobs, and find the target job ‘Auto_build_deploy_to_demo’ (highlighted by the{' '} + red rectangle). + +
  4. +
  5. +
    + In the first input field, enter the following regex to identify deployments (as highlighted in the{' '} + yellow rectangle): +
    +
    + The name of the Jenkins job or one of its stages matches + +
    +
  6. +
  7. +
    + In the second input field, enter the following regex to identify production deployments (highlighted by the{' '} + red rectangle). If left empty, all deployments in the{' '} + yellow rectangle will be regarded as Production Deployments. +
    +
    + If the name also matches , this + deployment will be regarded as a ‘Production Deployment’ +
    +
  8. +
+
+ For more information, please refer to{' '} + + this documentation + + . +
+
+ ); +}; diff --git a/config-ui/src/routes/blueprint/detail/components/add-connection-dialog/index.tsx b/config-ui/src/routes/blueprint/detail/components/add-connection-dialog/index.tsx index 2846146bfd6..c3dfa35f3a8 100644 --- a/config-ui/src/routes/blueprint/detail/components/add-connection-dialog/index.tsx +++ b/config-ui/src/routes/blueprint/detail/components/add-connection-dialog/index.tsx @@ -66,7 +66,7 @@ export const AddConnectionDialog = ({ disabled = [], onCancel, onSubmit }: Props const options = useMemo( () => - [{ value: '' }].concat( + [{ plugin: '', label: '', value: '' }].concat( connections .filter((cs) => (disabled.length ? !disabled.includes(cs.unique) : true)) .map((cs) => ({ diff --git a/config-ui/yarn.lock b/config-ui/yarn.lock index 957adec7e25..9e36a73e38c 100644 --- a/config-ui/yarn.lock +++ b/config-ui/yarn.lock @@ -22,7 +22,7 @@ __metadata: languageName: node linkType: hard -"@ant-design/colors@npm:^7.0.0, @ant-design/colors@npm:^7.0.2": +"@ant-design/colors@npm:^7.0.0": version: 7.0.2 resolution: "@ant-design/colors@npm:7.0.2" dependencies: @@ -31,9 +31,32 @@ __metadata: languageName: node linkType: hard -"@ant-design/cssinjs@npm:^1.18.4": - version: 1.18.4 - resolution: "@ant-design/cssinjs@npm:1.18.4" +"@ant-design/colors@npm:^7.1.0": + version: 7.1.0 + resolution: "@ant-design/colors@npm:7.1.0" + dependencies: + "@ctrl/tinycolor": ^3.6.1 + checksum: 6488b4159cea52be8a904caf541064e9f0e267c1df74ed687abd9364e6cfeb0353c64ee078878069f48aa6c381feca2af17612efe0529517c0260f989472b7ae + languageName: node + linkType: hard + +"@ant-design/cssinjs-utils@npm:^1.0.3": + version: 1.0.3 + resolution: "@ant-design/cssinjs-utils@npm:1.0.3" + dependencies: + "@ant-design/cssinjs": ^1.21.0 + "@babel/runtime": ^7.23.2 + rc-util: ^5.38.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: f0709d6135dca946cead159939fd92976d3bb727a7b88e523cf4d87d3914e927ce7bef068c8f1de679138cf6e502487e290ff42c96d1ee7141dfeb80667fa77d + languageName: node + linkType: hard + +"@ant-design/cssinjs@npm:^1.21.0": + version: 1.21.1 + resolution: "@ant-design/cssinjs@npm:1.21.1" dependencies: "@babel/runtime": ^7.11.1 "@emotion/hash": ^0.8.0 @@ -41,11 +64,20 @@ __metadata: classnames: ^2.3.1 csstype: ^3.1.3 rc-util: ^5.35.0 - stylis: ^4.0.13 + stylis: ^4.3.3 peerDependencies: react: ">=16.0.0" react-dom: ">=16.0.0" - checksum: c6028097929a9948d1e9d5441aeab51ff824edacf98976fb06c146397c7cc9b2fc3f88765a0d93345b1fbbf6b766f638260652d5637fcbf6e6bbafe4e79e60bd + checksum: 9260cc7533eb127516a66a21def2878f2da9c27cb5699e5e0586ad5f4420785b7ee0e4d7437a2ad82fe89888536b460bb63c58f366c4b9e5af12ea312f7bf94c + languageName: node + linkType: hard + +"@ant-design/fast-color@npm:^2.0.6": + version: 2.0.6 + resolution: "@ant-design/fast-color@npm:2.0.6" + dependencies: + "@babel/runtime": ^7.24.7 + checksum: 01f81ff5901ee13b3b6dab3884cc07e4fbd82e412404179ad053828f7f218acd0b6ced89ab28440e96e9c51177d90c17020095627b78ebb2468ecb98294287de languageName: node linkType: hard @@ -56,25 +88,25 @@ __metadata: languageName: node linkType: hard -"@ant-design/icons@npm:^5.3.0": - version: 5.3.1 - resolution: "@ant-design/icons@npm:5.3.1" +"@ant-design/icons@npm:^5.4.0": + version: 5.4.0 + resolution: "@ant-design/icons@npm:5.4.0" dependencies: "@ant-design/colors": ^7.0.0 "@ant-design/icons-svg": ^4.4.0 - "@babel/runtime": ^7.11.2 + "@babel/runtime": ^7.24.8 classnames: ^2.2.6 rc-util: ^5.31.1 peerDependencies: react: ">=16.0.0" react-dom: ">=16.0.0" - checksum: b244ed7c36609cf361382ae4f17cb172470c0ac4d9505e98dc09cae625d89df9840df68c8c1fdb0e7603fccc4394b3986da2bab4535d03cfad80cafdbf4bcebb + checksum: 4e6e1d91a7109afc05d3759e44add8b4d7432f14b5b58ce534b700eda5f86d4c8f1fa1d165ab32a0f972b23b0d3664b7bcb895ff468ea595f6f66e0863a3e8ac languageName: node linkType: hard -"@ant-design/react-slick@npm:~1.0.2": - version: 1.0.2 - resolution: "@ant-design/react-slick@npm:1.0.2" +"@ant-design/react-slick@npm:~1.1.2": + version: 1.1.2 + resolution: "@ant-design/react-slick@npm:1.1.2" dependencies: "@babel/runtime": ^7.10.4 classnames: ^2.2.5 @@ -83,7 +115,7 @@ __metadata: throttle-debounce: ^5.0.0 peerDependencies: react: ">=16.9.0" - checksum: c2a2d14270b3551c1af16c4cc8c63e29ee7f08e4203191d834df61211235102fd5d8e4325adfa41ada1c5212e4388849ec0d23fcb980bf69790b565f363e2d1f + checksum: e3f310ceb003311a72bcade5f2171dcd05130ead2c859ebd7111b2c324b079f146fb6f2770b07a3588457fab80c6132b5ec41da4e78f2f2f2944f913c36958c2 languageName: node linkType: hard @@ -1641,7 +1673,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.25.6 resolution: "@babel/runtime@npm:7.25.6" dependencies: @@ -2055,9 +2087,9 @@ __metadata: languageName: node linkType: hard -"@mints/miller-columns@npm:^2.0.0-beta.1": - version: 2.0.0-beta.1 - resolution: "@mints/miller-columns@npm:2.0.0-beta.1" +"@mints/miller-columns@npm:^2.0.0-beta.5": + version: 2.0.0-beta.5 + resolution: "@mints/miller-columns@npm:2.0.0-beta.5" dependencies: "@fontsource/roboto": ^5.0.14 "@mui/material": ^5.16.7 @@ -2076,7 +2108,7 @@ __metadata: react-dom: ^18.2.0 react-infinite-scroll-component: ^6.1.0 styled-components: ^6.1.12 - checksum: ca49de90e123850029cf1db5ac41567bdd04c0d8b60db3783260265e5b283fddd576c38b573de804a7f35c44e228045b8fa5000d9b8e8a75c53c3ce05ca5deec + checksum: 2ff5e7e942a1f5e592d7fe53d5522a59d72075604e80cfcf816d70d67ad33d3982b699770cdab01065bff19a219117b51017ea878ce5f015f120fb6623431839 languageName: node linkType: hard @@ -2299,18 +2331,27 @@ __metadata: languageName: node linkType: hard -"@rc-component/color-picker@npm:~1.5.2": - version: 1.5.2 - resolution: "@rc-component/color-picker@npm:1.5.2" +"@rc-component/async-validator@npm:^5.0.3": + version: 5.0.4 + resolution: "@rc-component/async-validator@npm:5.0.4" dependencies: + "@babel/runtime": ^7.24.4 + checksum: 30de0a62cd0dd08b5243e6a54b664f2eff3ec1529e1f6be5eac16e01946e825f3fe86138222b4a85f3ee9990dff2c83c0dd429ab1cce51fdacd28ab7f3ffb1b1 + languageName: node + linkType: hard + +"@rc-component/color-picker@npm:~2.0.1": + version: 2.0.1 + resolution: "@rc-component/color-picker@npm:2.0.1" + dependencies: + "@ant-design/fast-color": ^2.0.6 "@babel/runtime": ^7.23.6 - "@ctrl/tinycolor": ^3.6.1 classnames: ^2.2.6 rc-util: ^5.38.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: c3f24896f512bb883ee33b264133a749a4193cfe06273b1d6a0bbf2faa404913a995606ec6f5ca625689740cf6d11cf27e532c888ac8bd709703b85ebdb98b9c + checksum: 0c1f45362f50391d09488adca615d4810ad15e240b5938d1014cc22379cb900225eb186ca210c4d78f8abbcd626ff859e47c32c373a181783873fe4069455de4 languageName: node linkType: hard @@ -2364,25 +2405,39 @@ __metadata: languageName: node linkType: hard -"@rc-component/tour@npm:~1.12.3": - version: 1.12.3 - resolution: "@rc-component/tour@npm:1.12.3" +"@rc-component/qrcode@npm:~1.0.0": + version: 1.0.0 + resolution: "@rc-component/qrcode@npm:1.0.0" + dependencies: + "@babel/runtime": ^7.24.7 + classnames: ^2.3.2 + rc-util: ^5.38.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: a1aefd3994375b3d08f15b01c7ec978a3175f7ac22da748e3413bf2c33ca54457a9aa6344b005207abd4d1bc84a2a92ca1f964a6b7d0dcecb6d178edbb58a1e5 + languageName: node + linkType: hard + +"@rc-component/tour@npm:~1.15.1": + version: 1.15.1 + resolution: "@rc-component/tour@npm:1.15.1" dependencies: "@babel/runtime": ^7.18.0 "@rc-component/portal": ^1.0.0-9 - "@rc-component/trigger": ^1.3.6 + "@rc-component/trigger": ^2.0.0 classnames: ^2.3.2 rc-util: ^5.24.4 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 1a137d235e42df80d490023d452d6b571ad1afc07a9b5d3cd9312ae8657b5f2d68209a5c7144d2b5fb9e50712a6d927a1218ea2cab4f5337a7265fa91ca9d023 + checksum: 95e52abc6ef2ca374c3b3d869e599d7c9bbffdb270a631c385478f1a4e682eaffd0c82edc8e853094de465ac63b947cbd742741f6e8daa59cb375f86e5f7ab29 languageName: node linkType: hard -"@rc-component/trigger@npm:^1.17.0, @rc-component/trigger@npm:^1.18.0, @rc-component/trigger@npm:^1.18.3, @rc-component/trigger@npm:^1.3.6, @rc-component/trigger@npm:^1.5.0, @rc-component/trigger@npm:^1.7.0": - version: 1.18.3 - resolution: "@rc-component/trigger@npm:1.18.3" +"@rc-component/trigger@npm:^2.0.0, @rc-component/trigger@npm:^2.1.1, @rc-component/trigger@npm:^2.2.2": + version: 2.2.3 + resolution: "@rc-component/trigger@npm:2.2.3" dependencies: "@babel/runtime": ^7.23.2 "@rc-component/portal": ^1.1.0 @@ -2393,7 +2448,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 272098e67b4c09e8ee8f4fa2e55054c05f2ea5196e26859a2fd1dfb63ee4f02e4ca7b60d15704defb59b34151f042ff906099aee20d67a01066d2f0b76dd0c58 + checksum: 5803280945fe02c04af8439ba196009be13c433ea9a81a7865f86d0fa969766833d2a964c842ec432881ee5704fbc9c6d3445f4b646e1657422634491e948506 languageName: node linkType: hard @@ -3217,61 +3272,63 @@ __metadata: languageName: node linkType: hard -"antd@npm:^5.14.2": - version: 5.14.2 - resolution: "antd@npm:5.14.2" +"antd@npm:^5.20.6": + version: 5.20.6 + resolution: "antd@npm:5.20.6" dependencies: - "@ant-design/colors": ^7.0.2 - "@ant-design/cssinjs": ^1.18.4 - "@ant-design/icons": ^5.3.0 - "@ant-design/react-slick": ~1.0.2 + "@ant-design/colors": ^7.1.0 + "@ant-design/cssinjs": ^1.21.0 + "@ant-design/cssinjs-utils": ^1.0.3 + "@ant-design/icons": ^5.4.0 + "@ant-design/react-slick": ~1.1.2 + "@babel/runtime": ^7.24.8 "@ctrl/tinycolor": ^3.6.1 - "@rc-component/color-picker": ~1.5.2 + "@rc-component/color-picker": ~2.0.1 "@rc-component/mutate-observer": ^1.1.0 - "@rc-component/tour": ~1.12.3 - "@rc-component/trigger": ^1.18.3 + "@rc-component/qrcode": ~1.0.0 + "@rc-component/tour": ~1.15.1 + "@rc-component/trigger": ^2.2.2 classnames: ^2.5.1 copy-to-clipboard: ^3.3.3 - dayjs: ^1.11.10 - qrcode.react: ^3.1.0 - rc-cascader: ~3.21.2 - rc-checkbox: ~3.1.0 - rc-collapse: ~3.7.2 - rc-dialog: ~9.3.4 - rc-drawer: ~7.0.0 - rc-dropdown: ~4.1.0 - rc-field-form: ~1.41.0 - rc-image: ~7.5.1 - rc-input: ~1.4.3 - rc-input-number: ~9.0.0 - rc-mentions: ~2.10.1 - rc-menu: ~9.12.4 - rc-motion: ^2.9.0 - rc-notification: ~5.3.0 - rc-pagination: ~4.0.4 - rc-picker: ~4.1.4 - rc-progress: ~3.5.1 - rc-rate: ~2.12.0 + dayjs: ^1.11.11 + rc-cascader: ~3.28.1 + rc-checkbox: ~3.3.0 + rc-collapse: ~3.7.3 + rc-dialog: ~9.5.2 + rc-drawer: ~7.2.0 + rc-dropdown: ~4.2.0 + rc-field-form: ~2.4.0 + rc-image: ~7.9.0 + rc-input: ~1.6.3 + rc-input-number: ~9.2.0 + rc-mentions: ~2.15.0 + rc-menu: ~9.14.1 + rc-motion: ^2.9.2 + rc-notification: ~5.6.0 + rc-pagination: ~4.2.0 + rc-picker: ~4.6.14 + rc-progress: ~4.0.0 + rc-rate: ~2.13.0 rc-resize-observer: ^1.4.0 rc-segmented: ~2.3.0 - rc-select: ~14.11.0 - rc-slider: ~10.5.0 + rc-select: ~14.15.2 + rc-slider: ~11.1.5 rc-steps: ~6.0.1 rc-switch: ~4.1.0 - rc-table: ~7.39.0 - rc-tabs: ~14.0.0 - rc-textarea: ~1.6.3 - rc-tooltip: ~6.1.3 - rc-tree: ~5.8.5 - rc-tree-select: ~5.17.0 - rc-upload: ~4.5.2 - rc-util: ^5.38.2 + rc-table: ~7.45.7 + rc-tabs: ~15.1.1 + rc-textarea: ~1.8.1 + rc-tooltip: ~6.2.0 + rc-tree: ~5.9.0 + rc-tree-select: ~5.23.0 + rc-upload: ~4.7.0 + rc-util: ^5.43.0 scroll-into-view-if-needed: ^3.1.0 - throttle-debounce: ^5.0.0 + throttle-debounce: ^5.0.2 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: f894c67114bbd920c110aba35e40b85ff6de4f6b3b9b6608437a6db9c9d1fb7cc51aec33482ec725a7faed847aa1bab4affac2f84681c5adadb5c211bfcf97da + checksum: 54923f3a497fc53ae4baaa899de978dc4a64b9a9b5d6e8c081cee8c22a9617bafc3a4a3242cd1e44cf4f340639df93ad542c913b3de6c96674fb5e21afb5b607 languageName: node linkType: hard @@ -3414,13 +3471,6 @@ __metadata: languageName: node linkType: hard -"async-validator@npm:^4.1.0": - version: 4.2.5 - resolution: "async-validator@npm:4.2.5" - checksum: 3e3d891a2e21497c8a646afeb7b1e6ed5f98de5f58ce3600732080f327cb581e65d8d8ff184273f1461dc84105d49f5cf31422a67ce50e787967c306838b6f40 - languageName: node - linkType: hard - "asynciterator.prototype@npm:^1.0.0": version: 1.0.0 resolution: "asynciterator.prototype@npm:1.0.0" @@ -3858,10 +3908,10 @@ __metadata: version: 0.0.0-use.local resolution: "config-ui@workspace:." dependencies: - "@ant-design/icons": ^5.3.0 + "@ant-design/icons": ^5.4.0 "@fontsource/roboto": ^5.0.14 "@mints/hooks": ^1.0.0-beta.2 - "@mints/miller-columns": ^2.0.0-beta.1 + "@mints/miller-columns": ^2.0.0-beta.5 "@mui/icons-material": ^5.16.7 "@mui/material": ^5.16.7 "@mui/styled-engine-sc": ^6.0.0-alpha.18 @@ -3875,7 +3925,7 @@ __metadata: "@types/react-router-dom": ^5.3.3 "@types/styled-components": ^5.1.34 "@vitejs/plugin-react": ^4.2.1 - antd: ^5.14.2 + antd: ^5.20.6 axios: ^1.6.7 classnames: ^2.5.1 cron-parser: ^4.9.0 @@ -4046,6 +4096,13 @@ __metadata: languageName: node linkType: hard +"dayjs@npm:^1.11.11": + version: 1.11.13 + resolution: "dayjs@npm:1.11.13" + checksum: f388db88a6aa93956c1f6121644e783391c7b738b73dbc54485578736565c8931bdfba4bb94e9b1535c6e509c97d5deb918bbe1ae6b34358d994de735055cca9 + languageName: node + linkType: hard + "debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -7255,15 +7312,6 @@ __metadata: languageName: node linkType: hard -"qrcode.react@npm:^3.1.0": - version: 3.1.0 - resolution: "qrcode.react@npm:3.1.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 94a2942ecf83f461d869adb20305ae663c6d1abe93ef2c72442b07d756ce70cf6deb6fd588dc5b382b48c6991cfde1dfd5ac9b814c1461e71d5edb2d945e67fc - languageName: node - linkType: hard - "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -7271,26 +7319,26 @@ __metadata: languageName: node linkType: hard -"rc-cascader@npm:~3.21.2": - version: 3.21.2 - resolution: "rc-cascader@npm:3.21.2" +"rc-cascader@npm:~3.28.1": + version: 3.28.1 + resolution: "rc-cascader@npm:3.28.1" dependencies: "@babel/runtime": ^7.12.5 array-tree-filter: ^2.1.0 classnames: ^2.3.1 - rc-select: ~14.11.0 - rc-tree: ~5.8.1 + rc-select: ~14.15.0 + rc-tree: ~5.9.0 rc-util: ^5.37.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 448dd4562edb67d24259e620b026061597c1ccea2823474b4fdeec4d789f7c241bfb5e1e99daab29bb1a9c5f103f741efd4531f2f506ab35058914765be313df + checksum: 5d83970fd348d01d71d0d0d095c9a8d5fb7000e94600f480e33cac7cf701b198ca702b68e78b728c6ffdc9c882f2568a3ebc6075a50b3336b31f8e845db042cb languageName: node linkType: hard -"rc-checkbox@npm:~3.1.0": - version: 3.1.0 - resolution: "rc-checkbox@npm:3.1.0" +"rc-checkbox@npm:~3.3.0": + version: 3.3.0 + resolution: "rc-checkbox@npm:3.3.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.3.2 @@ -7298,13 +7346,13 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: f15dd3e3e3120567b633392e37c6d904f2b3c32eb752f4197231b6d79bfa257bde9cd32616ad08c0ad5b053d7b197c9e0684479053b4dea384e466ab53f5c7b4 + checksum: 95d48a1012339163e98bea6e158e5c650e45759550c50f1615f610a19ce31b0af384df899dfded147e1b16d2016e90f16a949792bb79f5b7f6709cf95a9eb1a5 languageName: node linkType: hard -"rc-collapse@npm:~3.7.2": - version: 3.7.2 - resolution: "rc-collapse@npm:3.7.2" +"rc-collapse@npm:~3.7.3": + version: 3.7.3 + resolution: "rc-collapse@npm:3.7.3" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x @@ -7313,13 +7361,13 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: b8e295fbd96325545bab7f7e4014fe5bb606ce973544479e3012704439b910215e5197e0e26bdc08d42d2321e7694c5e2d5a6c1bd81b790e03826b2bf60791b5 + checksum: c77c615d9501149aac02cb80dacb1f2f6fa7cca4659ee175b520e8d6089c5f09b0c919d2173e46af71a0815c897d404a89b6a069a3ad41b1a3ddc1cbb1c302cf languageName: node linkType: hard -"rc-dialog@npm:~9.3.4": - version: 9.3.4 - resolution: "rc-dialog@npm:9.3.4" +"rc-dialog@npm:~9.5.2": + version: 9.5.2 + resolution: "rc-dialog@npm:9.5.2" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/portal": ^1.0.0-8 @@ -7329,91 +7377,91 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 75d689d281ae3a1a85faa2f87c95ac65995ed58f696898edbe89a79604e18213565edc1d21291c9a640379fa6705c19ec51ba9275d69cde877d21f5108eb3503 + checksum: 58e747c958ebb058c903863071c86599546c4c52a8a6a09b06faee45b55d3836b3aaac9081613497c6cc3771ae7bb2b384a75c8edc32fb1412ccdaad420dce16 languageName: node linkType: hard -"rc-drawer@npm:~7.0.0": - version: 7.0.0 - resolution: "rc-drawer@npm:7.0.0" +"rc-drawer@npm:~7.2.0": + version: 7.2.0 + resolution: "rc-drawer@npm:7.2.0" dependencies: - "@babel/runtime": ^7.10.1 + "@babel/runtime": ^7.23.9 "@rc-component/portal": ^1.1.1 classnames: ^2.2.6 rc-motion: ^2.6.1 - rc-util: ^5.36.0 + rc-util: ^5.38.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 57c646c1b99be344c995eb67c36e9f78f1af6c1c3fce78d79738fe48dbb682f0143c993888535aaa5a912906ed713cd1df5d43f4a982bd98399467e1b539987f + checksum: 1ce22b459dbe736665c1db78cca03777ef5814d0bdf8cbda1ca88dc522e4b4ec3bcda04db81c98695050c29e9406bb892ab6be06fbae2adf78a0c1bcf71b7e67 languageName: node linkType: hard -"rc-dropdown@npm:~4.1.0": - version: 4.1.0 - resolution: "rc-dropdown@npm:4.1.0" +"rc-dropdown@npm:~4.2.0": + version: 4.2.0 + resolution: "rc-dropdown@npm:4.2.0" dependencies: "@babel/runtime": ^7.18.3 - "@rc-component/trigger": ^1.7.0 + "@rc-component/trigger": ^2.0.0 classnames: ^2.2.6 rc-util: ^5.17.0 peerDependencies: react: ">=16.11.0" react-dom: ">=16.11.0" - checksum: 97417289ad4e3c3b68980c9bb80d3429fba9fdf0011f73fd1bee1b9d0c7c602ee469ac52aadca6fec85430595a8581a069750ad696472f2ca951d5e44850a6f4 + checksum: 436ef23be5436fa730327a83d853cf2cce74823fa72b813068998a180aeca7978e42bf342bc4dfe1b1cb554bfc7e013324a15ed21a9b80b778d1c9312c5c6e05 languageName: node linkType: hard -"rc-field-form@npm:~1.41.0": - version: 1.41.0 - resolution: "rc-field-form@npm:1.41.0" +"rc-field-form@npm:~2.4.0": + version: 2.4.0 + resolution: "rc-field-form@npm:2.4.0" dependencies: "@babel/runtime": ^7.18.0 - async-validator: ^4.1.0 + "@rc-component/async-validator": ^5.0.3 rc-util: ^5.32.2 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 5340296d62e453d60ed42e19208c91ce2d2af5ff1d525829ea003109150011f3e944296a129792f749de6fc4c2113ea3297fdaef953de27606e03d73d937dc2b + checksum: 341e28e4095b84e143fdad43ca4062ead0f04b6304b6f669d82ca383bcbb4386a78efa7ca4d5476db0e0bce1c0c68524f887a713f91c9681ac928e0c5572ae88 languageName: node linkType: hard -"rc-image@npm:~7.5.1": - version: 7.5.1 - resolution: "rc-image@npm:7.5.1" +"rc-image@npm:~7.9.0": + version: 7.9.0 + resolution: "rc-image@npm:7.9.0" dependencies: "@babel/runtime": ^7.11.2 "@rc-component/portal": ^1.0.2 classnames: ^2.2.6 - rc-dialog: ~9.3.4 + rc-dialog: ~9.5.2 rc-motion: ^2.6.2 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: ec5ffd6ed34a2f1502a4374a622144c1554f83a376b87ffc54712ddd891c83e423cc0e5c3c228606ee0e1dc571df685d493c9e10582b352064b2073ec72c8d4b + checksum: 90712e1d8a8d67d53356d1a9f348cd6a0c51b763e526ebfba66ef704414c2b6b948548ba5d88c8f5c6ed8e7775dfb73c6efeac873e516969459eb96a6195c207 languageName: node linkType: hard -"rc-input-number@npm:~9.0.0": - version: 9.0.0 - resolution: "rc-input-number@npm:9.0.0" +"rc-input-number@npm:~9.2.0": + version: 9.2.0 + resolution: "rc-input-number@npm:9.2.0" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/mini-decimal": ^1.0.1 classnames: ^2.2.5 - rc-input: ~1.4.0 - rc-util: ^5.28.0 + rc-input: ~1.6.0 + rc-util: ^5.40.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 4109c5af3f19bde8ee3d46a8b9bbc3f95d1386e5481e207bea567bbddea22a517b11a2ce7b6487d70b9a5287b1d98f08e7c9758d23c8524d073ea56d65871718 + checksum: 0fb00352c014614044aad1deeb344c2d8e45b0e5303890f83a01ee90bee47c9846b7d2bf7cafb4fcf5fc9d39eac2088de69ad580d03583ca0b8489fb5c81b355 languageName: node linkType: hard -"rc-input@npm:~1.4.0, rc-input@npm:~1.4.3": - version: 1.4.3 - resolution: "rc-input@npm:1.4.3" +"rc-input@npm:~1.6.0, rc-input@npm:~1.6.3": + version: 1.6.3 + resolution: "rc-input@npm:1.6.3" dependencies: "@babel/runtime": ^7.11.1 classnames: ^2.2.1 @@ -7421,34 +7469,34 @@ __metadata: peerDependencies: react: ">=16.0.0" react-dom: ">=16.0.0" - checksum: 7c4f9cb5e21caf7dd2b6f8c70fe5d493e43e5db0e0fbf8414512b8217f24c198c549bfbd4422461482389904595df8ef794a677aea37d66bbd8030dafa4799b6 + checksum: ed73ac0275d5b989eddcb0202b8eed9a6d2d12c8b82646d814eb67b78e3956e6b624d8461a377c454d91cbfebd405893d24bd9bc377a1ee6a910b4a09c426fc7 languageName: node linkType: hard -"rc-mentions@npm:~2.10.1": - version: 2.10.1 - resolution: "rc-mentions@npm:2.10.1" +"rc-mentions@npm:~2.15.0": + version: 2.15.0 + resolution: "rc-mentions@npm:2.15.0" dependencies: "@babel/runtime": ^7.22.5 - "@rc-component/trigger": ^1.5.0 + "@rc-component/trigger": ^2.0.0 classnames: ^2.2.6 - rc-input: ~1.4.0 - rc-menu: ~9.12.0 - rc-textarea: ~1.6.1 + rc-input: ~1.6.0 + rc-menu: ~9.14.0 + rc-textarea: ~1.8.0 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 0b1fc9690cbf76a72acf020a94eb1a33fdd2545c8170622c99e925b630d25874ab52110376861d1ec95ca50fcd8cef417e7c83fb723592073a798d86e9bb24e6 + checksum: bead0b303bee045186b941c61e6af93777b406904f2c40546cdfd7cbed016140b3a36d1cc66b0ed3a7cfb34d3a18fa01e588933d42bcaf8e68cbb21bde2f05c0 languageName: node linkType: hard -"rc-menu@npm:~9.12.0, rc-menu@npm:~9.12.4": - version: 9.12.4 - resolution: "rc-menu@npm:9.12.4" +"rc-menu@npm:~9.14.0, rc-menu@npm:~9.14.1": + version: 9.14.1 + resolution: "rc-menu@npm:9.14.1" dependencies: "@babel/runtime": ^7.10.1 - "@rc-component/trigger": ^1.17.0 + "@rc-component/trigger": ^2.0.0 classnames: 2.x rc-motion: ^2.4.3 rc-overflow: ^1.3.1 @@ -7456,7 +7504,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 3d7770defb882a444b21d6c437b0cf8759226a98233a50d48d0554bf2addab05c67544466b54c9bcc641d7859e7a9be84031d3493a521b697d56c9b9c2a0e7f3 + checksum: 52e729ea4656f50616767559de7bc5eaae411dfba28ec79308f52a7dd2ead7a615e62097bd60429ac98cb3f996fe6bdbb6a223bdc8422cf629387c5c48c8de46 languageName: node linkType: hard @@ -7474,9 +7522,23 @@ __metadata: languageName: node linkType: hard -"rc-notification@npm:~5.3.0": - version: 5.3.0 - resolution: "rc-notification@npm:5.3.0" +"rc-motion@npm:^2.9.2": + version: 2.9.2 + resolution: "rc-motion@npm:2.9.2" + dependencies: + "@babel/runtime": ^7.11.1 + classnames: ^2.2.1 + rc-util: ^5.43.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 704dceedaf7f75e884b6a6e1134e674c1351ee6c6b1bd6a18ff73594d1ba0379cab77abd7fcad7d842ca07595bfe0a7ab291210a7144f7fd2e5e68a199e1561c + languageName: node + linkType: hard + +"rc-notification@npm:~5.6.0": + version: 5.6.0 + resolution: "rc-notification@npm:5.6.0" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x @@ -7485,7 +7547,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 1e6bc146e687815d784e0b4c626a9af82435086bc02bb5e19827baa523e26440d6ed03b43de83a15e0272b83bebede3b67d61c4d4af2240ae7dcdd6604f0ef58 + checksum: 265d9c1e0c31c3155cd08a3500d412b247594cffbd2eb32527f20c7688336930fa28eb0c69133d684bcce80266f2f665bb5d78c9b15af8ea9145ef32bef6241f languageName: node linkType: hard @@ -7504,9 +7566,9 @@ __metadata: languageName: node linkType: hard -"rc-pagination@npm:~4.0.4": - version: 4.0.4 - resolution: "rc-pagination@npm:4.0.4" +"rc-pagination@npm:~4.2.0": + version: 4.2.0 + resolution: "rc-pagination@npm:4.2.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.3.2 @@ -7514,20 +7576,20 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 2ff6f2dd6ad0b855d1e747d09534f2efe9a124af4ff4cd5d5550a6cae9392879c06f471d4ee29d2a72c2c416f89dac6e43a7788650db5b8e54001affba2b172c + checksum: 78a889bade203e559558b7b973d848c2b1626a68b24f7e458526d8839641ad4b57c62a12cc6d4107a351b3a962e2f782bd33794586dd909cd11e17032431d845 languageName: node linkType: hard -"rc-picker@npm:~4.1.4": - version: 4.1.5 - resolution: "rc-picker@npm:4.1.5" +"rc-picker@npm:~4.6.14": + version: 4.6.14 + resolution: "rc-picker@npm:4.6.14" dependencies: - "@babel/runtime": ^7.10.1 - "@rc-component/trigger": ^1.5.0 + "@babel/runtime": ^7.24.7 + "@rc-component/trigger": ^2.0.0 classnames: ^2.2.1 rc-overflow: ^1.3.2 rc-resize-observer: ^1.4.0 - rc-util: ^5.38.1 + rc-util: ^5.43.0 peerDependencies: date-fns: ">= 2.x" dayjs: ">= 1.x" @@ -7544,13 +7606,13 @@ __metadata: optional: true moment: optional: true - checksum: 732f04d78afd3361c83f0d7498a4432e088903b0d92fb62c489d97ee9307562a5da043c629e79993f71b441016e0d6793bbe75557c41f62658e4c15b8c8e0cf1 + checksum: 1048407363fc7be6f8dbedcbdb011705faa76c38c616947358724dd6b59d7fab74823857f780b8d10a38d68a7a2be7ffe79bb7d22b3dde4faf3ce7cc6d964bff languageName: node linkType: hard -"rc-progress@npm:~3.5.1": - version: 3.5.1 - resolution: "rc-progress@npm:3.5.1" +"rc-progress@npm:~4.0.0": + version: 4.0.0 + resolution: "rc-progress@npm:4.0.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.6 @@ -7558,13 +7620,13 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: b0722a696396f985267e35e26f49c1c1bd6a17b4918eb93318fc36a7a5ffae9806932d4982a7da0d83349648ca85325b792003ec40240820fd6e00e0bc6f3c1d + checksum: cd058f1becea650142c21f7ad36fc2b3e145d06c26d432c38ba1f10c9fc0895c51471a9fe775426849b2c6e6fa3c68c6877b1a42b60014d5fa1b350524bb7ae2 languageName: node linkType: hard -"rc-rate@npm:~2.12.0": - version: 2.12.0 - resolution: "rc-rate@npm:2.12.0" +"rc-rate@npm:~2.13.0": + version: 2.13.0 + resolution: "rc-rate@npm:2.13.0" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.5 @@ -7572,7 +7634,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: aa41bb6b89a53cb69641123e8e3dfe9e6bb3092fb102b80eb251d32e18c5f7ad9a6f47c7c848ece91eee68f8df5b90719e026c14a148d4645aecf3489727bed5 + checksum: 08e0327c006adbd4a6b4c4e2a8863237d81d213703cf2156cd4b161ffa28ab8c9938c4baa15c337569e2c7f28205d7afdc544f59341b6e058a73a5c7e297b813 languageName: node linkType: hard @@ -7606,12 +7668,12 @@ __metadata: languageName: node linkType: hard -"rc-select@npm:~14.11.0, rc-select@npm:~14.11.0-0": - version: 14.11.0 - resolution: "rc-select@npm:14.11.0" +"rc-select@npm:~14.15.0, rc-select@npm:~14.15.2": + version: 14.15.2 + resolution: "rc-select@npm:14.15.2" dependencies: "@babel/runtime": ^7.10.1 - "@rc-component/trigger": ^1.5.0 + "@rc-component/trigger": ^2.1.1 classnames: 2.x rc-motion: ^2.0.1 rc-overflow: ^1.3.1 @@ -7620,21 +7682,21 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: e3258545a64c687b2e3c456edf8c426961cf69823d67972580db49f470cd5bd11a7e1a55033c206b542c5c130ee45a2dd2436a9dae00c6528190d170eef6ff31 + checksum: 7432f111391878e61019b6b18c782151049ed3361d1902b7fc891145fdfdb1f5d42a2345e35d8d0078899a8700e9b4dbf89cca7c654752bcaa68d28407ab8d98 languageName: node linkType: hard -"rc-slider@npm:~10.5.0": - version: 10.5.0 - resolution: "rc-slider@npm:10.5.0" +"rc-slider@npm:~11.1.5": + version: 11.1.5 + resolution: "rc-slider@npm:11.1.5" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.5 - rc-util: ^5.27.0 + rc-util: ^5.36.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 7d29cf4edee57615ab5d000cd1641216829988934db1e920243040615fa194147a4c2b065388b9d8e984a04424b67c997975fccde1e94ae85f66dca365934f1c + checksum: eadf2e0e981525fbd3d5e403d7cfece12372603f7c64e32c417b5d20d939c6520d9c7c318b1396bfcb14d95fbc35e5bed9403ab41b5cba60659f253ada3d92f5 languageName: node linkType: hard @@ -7666,90 +7728,90 @@ __metadata: languageName: node linkType: hard -"rc-table@npm:~7.39.0": - version: 7.39.0 - resolution: "rc-table@npm:7.39.0" +"rc-table@npm:~7.45.7": + version: 7.45.7 + resolution: "rc-table@npm:7.45.7" dependencies: "@babel/runtime": ^7.10.1 "@rc-component/context": ^1.4.0 classnames: ^2.2.5 rc-resize-observer: ^1.1.0 rc-util: ^5.37.0 - rc-virtual-list: ^3.11.1 + rc-virtual-list: ^3.14.2 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 4de25e29d4b8f2c4afbaae1ea3620923d2c3e537c4ef9af0e8e57cf7447ce49a5cfe1a8bb8d5de7b38efc77ea835385d76808eb34aeb9408564d1a30fcc9e6c8 + checksum: c9e3cc14dbb45593e33e2179a92a00e46de5af74d8596c8a11433a4e3420746ec597fa92b25e4d98faa10fd6a603e947f69d123bc07a21a9441b1ffc863701ab languageName: node linkType: hard -"rc-tabs@npm:~14.0.0": - version: 14.0.0 - resolution: "rc-tabs@npm:14.0.0" +"rc-tabs@npm:~15.1.1": + version: 15.1.1 + resolution: "rc-tabs@npm:15.1.1" dependencies: "@babel/runtime": ^7.11.2 classnames: 2.x - rc-dropdown: ~4.1.0 - rc-menu: ~9.12.0 + rc-dropdown: ~4.2.0 + rc-menu: ~9.14.0 rc-motion: ^2.6.2 rc-resize-observer: ^1.0.0 rc-util: ^5.34.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 4847c623b8bb219ad80d4ebd59ae7e389feb2c1a9eacd18127b3f567d0c1db555b87e88cc72bf21201d8a60cac0eed6f930261f368979d720a8a22e39567ef85 + checksum: 77065468e4e74f8737de5faba9e22ef8d5b255d2db578d4081a29ded6fab4cf18fae3d6b1db7d784c1b47f61bd6b608f6d9737cbc300952532e273a0091f8b47 languageName: node linkType: hard -"rc-textarea@npm:~1.6.1, rc-textarea@npm:~1.6.3": - version: 1.6.3 - resolution: "rc-textarea@npm:1.6.3" +"rc-textarea@npm:~1.8.0, rc-textarea@npm:~1.8.1": + version: 1.8.1 + resolution: "rc-textarea@npm:1.8.1" dependencies: "@babel/runtime": ^7.10.1 classnames: ^2.2.1 - rc-input: ~1.4.0 + rc-input: ~1.6.0 rc-resize-observer: ^1.0.0 rc-util: ^5.27.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: a9774cafd228da8900859187db39b3e3ebe0fc53abe727af14a545062ba6b0d6a568f356fed77394f0f1296b328d28eba9c50068c8034d40967de8a6e283b1f5 + checksum: f7a4f78f6346c66f974209007d915688815e5c13472d2f8fb05d2836e1ffb040afdf88e4a320f4e1f484a82c33b19d8b65c9a71ff8cb78adeb9d02d2cbc08eb6 languageName: node linkType: hard -"rc-tooltip@npm:~6.1.3": - version: 6.1.3 - resolution: "rc-tooltip@npm:6.1.3" +"rc-tooltip@npm:~6.2.0": + version: 6.2.0 + resolution: "rc-tooltip@npm:6.2.0" dependencies: "@babel/runtime": ^7.11.2 - "@rc-component/trigger": ^1.18.0 + "@rc-component/trigger": ^2.0.0 classnames: ^2.3.1 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: f67cf4e409d110f9f4098807303bd4590297f45ffb21d20f3c59a93de45b38c477eeee346e78b9c2e07bffd2ed53e22f435023113a08b553ed10e269754507e2 + checksum: 950201af1743f655a867f8e2c9892784d3bb7b9a9f8b48aa0b22c5066b351f8895683e034cf2b8a8de6780641a84dab4bc6b4ecdcb81261b26462801f5cedf11 languageName: node linkType: hard -"rc-tree-select@npm:~5.17.0": - version: 5.17.0 - resolution: "rc-tree-select@npm:5.17.0" +"rc-tree-select@npm:~5.23.0": + version: 5.23.0 + resolution: "rc-tree-select@npm:5.23.0" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x - rc-select: ~14.11.0-0 - rc-tree: ~5.8.1 + rc-select: ~14.15.0 + rc-tree: ~5.9.0 rc-util: ^5.16.1 peerDependencies: react: "*" react-dom: "*" - checksum: 245061c480ae5625fdb016a098770d6bfac0a6445856d4870a02b78e236a6510e241a4eaef36bb36236c6dca936a992a967e327a04d0440685ad6d0ba7c18b12 + checksum: e3d055818b54d4c3ac79e8fab48b97cb4eabc769636f05524796d580041b7f088f727799ee29d2cd456d71e4dc97d3fac7b6be57aee273d51ee4a58064acf489 languageName: node linkType: hard -"rc-tree@npm:~5.8.1, rc-tree@npm:~5.8.5": - version: 5.8.5 - resolution: "rc-tree@npm:5.8.5" +"rc-tree@npm:~5.9.0": + version: 5.9.0 + resolution: "rc-tree@npm:5.9.0" dependencies: "@babel/runtime": ^7.10.1 classnames: 2.x @@ -7759,13 +7821,13 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 9f5d652b4a6a5c93e8b6ddb6ecbd11560d845661dcb1d7d03b97c31181592bfb54ef350fae90eff461a027639c2b1a74ec5b709920125efb7b66959377359e2f + checksum: 73f8372cf7607c3791e31d31347bac0093ddc1636b96abbb00965854eb3f88e21e2da43270c9ec9290092eccad9a14e6b682db04655391aa9a7263d91a9f015e languageName: node linkType: hard -"rc-upload@npm:~4.5.2": - version: 4.5.2 - resolution: "rc-upload@npm:4.5.2" +"rc-upload@npm:~4.7.0": + version: 4.7.0 + resolution: "rc-upload@npm:4.7.0" dependencies: "@babel/runtime": ^7.18.3 classnames: ^2.2.5 @@ -7773,11 +7835,11 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 5a7e1942657d91d78dab3a84367629d8dac7c3dcd961d8839d1d481e982504de2944c74c5b79fb63e3971ff84bc667e841e0e4305af10b37615c185e6d92d644 + checksum: 9fd953d7d06adf37f4940cb3284274df0322ce86320425a809f99aa831cca2d453f6a31aa625bb0eb73596b1b5aeaf65b76650c2e61002f1913c9c1e4a0694e1 languageName: node linkType: hard -"rc-util@npm:^5.0.1, rc-util@npm:^5.16.1, rc-util@npm:^5.17.0, rc-util@npm:^5.18.1, rc-util@npm:^5.2.0, rc-util@npm:^5.20.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.25.2, rc-util@npm:^5.27.0, rc-util@npm:^5.28.0, rc-util@npm:^5.30.0, rc-util@npm:^5.31.1, rc-util@npm:^5.32.2, rc-util@npm:^5.34.1, rc-util@npm:^5.35.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1, rc-util@npm:^5.38.2": +"rc-util@npm:^5.0.1, rc-util@npm:^5.16.1, rc-util@npm:^5.17.0, rc-util@npm:^5.18.1, rc-util@npm:^5.2.0, rc-util@npm:^5.20.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.25.2, rc-util@npm:^5.27.0, rc-util@npm:^5.30.0, rc-util@npm:^5.31.1, rc-util@npm:^5.32.2, rc-util@npm:^5.34.1, rc-util@npm:^5.35.0, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1": version: 5.38.2 resolution: "rc-util@npm:5.38.2" dependencies: @@ -7790,7 +7852,35 @@ __metadata: languageName: node linkType: hard -"rc-virtual-list@npm:^3.11.1, rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2": +"rc-util@npm:^5.40.1, rc-util@npm:^5.43.0": + version: 5.43.0 + resolution: "rc-util@npm:5.43.0" + dependencies: + "@babel/runtime": ^7.18.3 + react-is: ^18.2.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 48c10afb5886aed86d1f5241883f972b2b16235b0cc4867a05d061324f107aa113260c34eeb13ad18f4b66d1264dbcb3baf725c8ea34fbdaa504410d4e71b3ce + languageName: node + linkType: hard + +"rc-virtual-list@npm:^3.14.2": + version: 3.14.5 + resolution: "rc-virtual-list@npm:3.14.5" + dependencies: + "@babel/runtime": ^7.20.0 + classnames: ^2.2.6 + rc-resize-observer: ^1.0.0 + rc-util: ^5.36.0 + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: f68957cc1b78eb9bfcbad87a2d3cce942c301fd0a7dd894548cca81f64433a321b567762d745d199e6c4667f070f2437972d2a24bf6d97d5b05c53b665b706a3 + languageName: node + linkType: hard + +"rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2": version: 3.11.4 resolution: "rc-virtual-list@npm:3.11.4" dependencies: @@ -8769,7 +8859,7 @@ __metadata: languageName: node linkType: hard -"stylis@npm:4.3.1, stylis@npm:^4.0.13": +"stylis@npm:4.3.1": version: 4.3.1 resolution: "stylis@npm:4.3.1" checksum: d365f1b008677b2147e8391e9cf20094a4202a5f9789562e7d9d0a3bd6f0b3067d39e8fd17cce5323903a56f6c45388e3d839e9c0bb5a738c91726992b14966d @@ -8783,6 +8873,13 @@ __metadata: languageName: node linkType: hard +"stylis@npm:^4.3.3": + version: 4.3.4 + resolution: "stylis@npm:4.3.4" + checksum: 7e3a482c7bba6e0e9e3187972e958acf800b1abe99f23e081fcb5dea8e4a05eca44286c1381ce2bc7179245ddbd7bf1f74237ed413fce7491320a543bcfebda9 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -8850,6 +8947,13 @@ __metadata: languageName: node linkType: hard +"throttle-debounce@npm:^5.0.2": + version: 5.0.2 + resolution: "throttle-debounce@npm:5.0.2" + checksum: 90d026691bfedf692d9a5addd1d5b30460c6a87a9c588ae05779402e3bfd042bad2bf828edb05512f2e9e601566e8663443d929cf963a998207e193fb1d7eff8 + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" From 1877da500a945904858f5d44c6871532cb19ddc4 Mon Sep 17 00:00:00 2001 From: Klesh Wong Date: Fri, 27 Sep 2024 09:00:15 +0800 Subject: [PATCH 23/32] feat: gitlab extractors and convertors support incremental mode (#7997) * feat: gitlab mr_extractor support incremental sync * feat: incr mode transformation support for deployment/issue/job/mr and others * feat: removed mr_enricher and all gitlab transformers support incr-mode * fix: some gitlab subtasks are missing connection in left join clause * fix: test cases failed due to gitlab transformers support incr-mode * fix: linting * fix: do not collect all accounts from jihulab.com * fix: typo * fix: gitlab mr comments won't be converted to domain layer till next run * feat: improve gitlab MR comments/commits collection performance * fix: gitlab issues/mrs child records are not deleted * docs: update stateful extractor doc * fix: gitlab mr detail test * refactor: unify stateful extractor and convertor helper * docs: update stateful extractor/convertor doc * refactor: remove useless type hint * fix: shoud not be deleting records not extracted by current extractor * fix: jira issue extractor should not deleting sprint_issue * refactor: remove commit related subtasks * fix: remove commit conversion e2e test * feat(gitlab): update ExtractApiChildPipelines (#8016) * fix: retransform should run in fullsync mode * fix: gitlab issue assignees are not being converted --------- Co-authored-by: Lynwee <1507509064@qq.com> --- .../api/api_extractor_stateful.go | 48 +++-- .../helpers/pluginhelper/api/api_rawdata.go | 2 +- .../api/data_convertor_stateful.go | 26 ++- .../pluginhelper/api/enrich_with_regex.go | 8 + .../pluginhelper/api/subtask_state_manager.go | 2 +- backend/impls/dalgorm/encdec_serializer.go | 5 + backend/plugins/gitlab/e2e/mr_commits_test.go | 33 ---- backend/plugins/gitlab/e2e/mr_detail_test.go | 2 + backend/plugins/gitlab/e2e/mr_enrich_test.go | 79 --------- ..._gitlab_merge_requests_for_enrich_test.csv | 25 --- ...tlab_merge_requests_for_mr_commit_test.csv | 12 +- ...itlab_merge_requests_for_mr_notes_test.csv | 34 ++-- .../gitlab/e2e/snapshot_tables/commits.csv | 65 ------- .../e2e/snapshot_tables/repo_commits.csv | 38 ---- .../20240904_remove_mr_review_fields.go | 40 +++++ backend/plugins/gitlab/models/mr.go | 4 +- .../plugins/gitlab/tasks/account_collector.go | 4 +- .../gitlab/tasks/child_pipeline_extractor.go | 29 +-- .../plugins/gitlab/tasks/commit_collector.go | 80 --------- .../plugins/gitlab/tasks/commit_convertor.go | 108 ------------ .../plugins/gitlab/tasks/commit_extractor.go | 116 ------------ .../gitlab/tasks/deployment_convertor.go | 40 ++--- .../gitlab/tasks/deployment_extractor.go | 16 +- .../gitlab/tasks/issue_assignee_convertor.go | 49 +++--- .../plugins/gitlab/tasks/issue_convertor.go | 55 +++--- .../plugins/gitlab/tasks/issue_extractor.go | 44 +++-- .../gitlab/tasks/issue_label_convertor.go | 53 +++--- backend/plugins/gitlab/tasks/job_convertor.go | 51 +++--- backend/plugins/gitlab/tasks/job_extractor.go | 18 +- .../gitlab/tasks/mr_assignee_convertor.go | 52 +++--- .../gitlab/tasks/mr_commit_convertor.go | 64 +++---- .../gitlab/tasks/mr_commit_extractor.go | 56 ++++-- backend/plugins/gitlab/tasks/mr_convertor.go | 57 +++--- .../gitlab/tasks/mr_detail_extractor.go | 25 ++- backend/plugins/gitlab/tasks/mr_enricher.go | 165 ------------------ .../plugins/gitlab/tasks/mr_enricher_test.go | 112 ------------ backend/plugins/gitlab/tasks/mr_extractor.go | 78 +++++++-- .../gitlab/tasks/mr_label_convertor.go | 53 +++--- ...ment_convertor.go => mr_note_convertor.go} | 55 +++--- .../plugins/gitlab/tasks/mr_note_extractor.go | 18 +- .../gitlab/tasks/mr_reviewer_convertor.go | 53 +++--- .../gitlab/tasks/pipeline_commit_convertor.go | 45 ++--- .../gitlab/tasks/pipeline_detail_convertor.go | 45 +++-- .../gitlab/tasks/pipeline_detail_extractor.go | 18 +- .../gitlab/tasks/pipeline_extractor.go | 17 +- backend/plugins/gitlab/tasks/shared.go | 24 ++- .../gitlab/tasks/trigger_job_extractor.go | 17 +- backend/plugins/jira/tasks/epic_extractor.go | 10 +- .../jira/tasks/issue_changelog_convertor.go | 2 +- .../jira/tasks/issue_changelog_extractor.go | 9 +- backend/plugins/jira/tasks/issue_convertor.go | 13 +- backend/plugins/jira/tasks/issue_extractor.go | 35 ++-- backend/server/api/blueprints/blueprints.go | 1 + .../routes/blueprint/detail/status-panel.tsx | 2 +- 54 files changed, 709 insertions(+), 1403 deletions(-) delete mode 100644 backend/plugins/gitlab/e2e/mr_enrich_test.go delete mode 100644 backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_enrich_test.csv delete mode 100644 backend/plugins/gitlab/e2e/snapshot_tables/commits.csv delete mode 100644 backend/plugins/gitlab/e2e/snapshot_tables/repo_commits.csv create mode 100644 backend/plugins/gitlab/models/migrationscripts/20240904_remove_mr_review_fields.go delete mode 100644 backend/plugins/gitlab/tasks/commit_collector.go delete mode 100644 backend/plugins/gitlab/tasks/commit_convertor.go delete mode 100644 backend/plugins/gitlab/tasks/commit_extractor.go delete mode 100644 backend/plugins/gitlab/tasks/mr_enricher.go delete mode 100644 backend/plugins/gitlab/tasks/mr_enricher_test.go rename backend/plugins/gitlab/tasks/{mr_comment_convertor.go => mr_note_convertor.go} (70%) diff --git a/backend/helpers/pluginhelper/api/api_extractor_stateful.go b/backend/helpers/pluginhelper/api/api_extractor_stateful.go index 00e2764b4c3..2c994afdb5f 100644 --- a/backend/helpers/pluginhelper/api/api_extractor_stateful.go +++ b/backend/helpers/pluginhelper/api/api_extractor_stateful.go @@ -18,6 +18,7 @@ limitations under the License. package api import ( + "encoding/json" "reflect" "github.com/apache/incubator-devlake/core/dal" @@ -27,9 +28,10 @@ import ( ) // StatefulApiExtractorArgs is a struct that contains the arguments for a stateful api extractor -type StatefulApiExtractorArgs struct { +type StatefulApiExtractorArgs[InputType any] struct { *SubtaskCommonArgs - Extract func(row *RawData) ([]any, errors.Error) + BeforeExtract func(issue *InputType, stateManager *SubtaskStateManager) errors.Error + Extract func(body *InputType, row *RawData) ([]any, errors.Error) } // StatefulApiExtractor is a struct that manages the stateful API extraction process. @@ -41,7 +43,7 @@ type StatefulApiExtractorArgs struct { // // Example: // -// extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs{ +// extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[apiv2models.Issue]{ // SubtaskCommonArgs: &api.SubtaskCommonArgs{ // SubTaskContext: subtaskCtx, // Table: RAW_ISSUE_TABLE, @@ -54,8 +56,17 @@ type StatefulApiExtractorArgs struct { // // Ensure that the configuration is serializable and contains only public fields. // // It is also recommended that the configuration includes only the necessary fields used by the extractor. // ..}, -// Extract: func(row *api.RawData) ([]interface{}, errors.Error) { -// return extractIssues(data, config, row, userFieldMap) +// BeforeExtract: func(body *IssuesResponse, stateManager *api.SubtaskStateManager) errors.Error { +// if stateManager.IsIncremental() { +// // It is important to delete all existing child-records under DiffSync Mode +// err := db.Delete( +// &models.JiraIssueLabel{}, +// dal.Where("connection_id = ? AND issue_id = ?", data.Options.ConnectionId, body.Id), +// ) +// } +// return nil +// }, +// Extract: func(apiIssue *apiv2models.Issue, row *api.RawData) ([]interface{}, errors.Error) { // }, // }) // @@ -64,25 +75,25 @@ type StatefulApiExtractorArgs struct { // } // // return extractor.Execute() -type StatefulApiExtractor struct { - *StatefulApiExtractorArgs +type StatefulApiExtractor[InputType any] struct { + *StatefulApiExtractorArgs[InputType] *SubtaskStateManager } // NewStatefulApiExtractor creates a new StatefulApiExtractor -func NewStatefulApiExtractor(args *StatefulApiExtractorArgs) (*StatefulApiExtractor, errors.Error) { +func NewStatefulApiExtractor[InputType any](args *StatefulApiExtractorArgs[InputType]) (*StatefulApiExtractor[InputType], errors.Error) { stateManager, err := NewSubtaskStateManager(args.SubtaskCommonArgs) if err != nil { return nil, err } - return &StatefulApiExtractor{ + return &StatefulApiExtractor[InputType]{ StatefulApiExtractorArgs: args, SubtaskStateManager: stateManager, }, nil } // Execute sub-task -func (extractor *StatefulApiExtractor) Execute() errors.Error { +func (extractor *StatefulApiExtractor[InputType]) Execute() errors.Error { // load data from database db := extractor.GetDal() logger := extractor.GetLogger() @@ -135,7 +146,20 @@ func (extractor *StatefulApiExtractor) Execute() errors.Error { return errors.Default.Wrap(err, "error fetching row") } - results, err := extractor.Extract(row) + body := new(InputType) + err = errors.Convert(json.Unmarshal(row.Data, body)) + if err != nil { + return err + } + + if extractor.BeforeExtract != nil { + err = extractor.BeforeExtract(body, extractor.SubtaskStateManager) + if err != nil { + return err + } + } + + results, err := extractor.Extract(body, row) if err != nil { return errors.Default.Wrap(err, "error calling plugin Extract implementation") } @@ -169,4 +193,4 @@ func (extractor *StatefulApiExtractor) Execute() errors.Error { return extractor.SubtaskStateManager.Close() } -var _ plugin.SubTask = (*StatefulApiExtractor)(nil) +var _ plugin.SubTask = (*StatefulApiExtractor[any])(nil) diff --git a/backend/helpers/pluginhelper/api/api_rawdata.go b/backend/helpers/pluginhelper/api/api_rawdata.go index ef16dde6db8..5e9bb783529 100644 --- a/backend/helpers/pluginhelper/api/api_rawdata.go +++ b/backend/helpers/pluginhelper/api/api_rawdata.go @@ -34,7 +34,7 @@ type RawData struct { Data []byte Url string Input json.RawMessage `gorm:"type:json"` - CreatedAt time.Time + CreatedAt time.Time `gorm:"index"` } type TaskOptions interface { diff --git a/backend/helpers/pluginhelper/api/data_convertor_stateful.go b/backend/helpers/pluginhelper/api/data_convertor_stateful.go index 058a1fa3255..1c5292dc230 100644 --- a/backend/helpers/pluginhelper/api/data_convertor_stateful.go +++ b/backend/helpers/pluginhelper/api/data_convertor_stateful.go @@ -27,9 +27,10 @@ import ( type StatefulDataConverterArgs[InputType any] struct { *SubtaskCommonArgs - Input func(*SubtaskStateManager) (dal.Rows, errors.Error) - Convert func(row *InputType) ([]any, errors.Error) - BatchSize int + Input func(*SubtaskStateManager) (dal.Rows, errors.Error) + BeforeConvert func(issue *InputType, stateManager *SubtaskStateManager) errors.Error + Convert func(row *InputType) ([]any, errors.Error) + BatchSize int } // StatefulDataConverter is a struct that manages the stateful data conversion process. @@ -47,7 +48,7 @@ type StatefulDataConverterArgs[InputType any] struct { // // Example: // -// converter, err := api.NewStatefulDataConverter[models.JiraIssue](&api.StatefulDataConverterArgs[models.JiraIssue]{ +// converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.JiraIssue]{ // SubtaskCommonArgs: &api.SubtaskCommonArgs{ // SubTaskContext: subtaskCtx, // Table: RAW_ISSUE_TABLE, @@ -78,6 +79,15 @@ type StatefulDataConverterArgs[InputType any] struct { // } // return db.Cursor(clauses...) // }, +// BeforeConvert: func(jiraIssue *models.GitlabMergeRequest, stateManager *api.SubtaskStateManager) errors.Error { +// // It is important to delete all existing child-records under DiffSync Mode +// issueId := issueIdGen.Generate(data.Options.ConnectionId, jiraIssue.IssueId) +// if err := db.Delete(&ticket.IssueAssignee{}, dal.Where("issue_id = ?", issueId)); err != nil { +// return err +// } +// ... +// return nil +// }, // Convert: func(jiraIssue *models.JiraIssue) ([]interface{}, errors.Error) { // }, // }) @@ -93,7 +103,6 @@ type StatefulDataConverter[InputType any] struct { } func NewStatefulDataConverter[ - OptType any, InputType any, ]( args *StatefulDataConverterArgs[InputType], @@ -146,6 +155,13 @@ func (converter *StatefulDataConverter[InputType]) Execute() errors.Error { return errors.Default.Wrap(err, "error fetching rows") } + if converter.BeforeConvert != nil { + err = converter.BeforeConvert(inputRow, converter.SubtaskStateManager) + if err != nil { + return err + } + } + results, err := converter.Convert(inputRow) if err != nil { return errors.Default.Wrap(err, "error calling Converter plugin implementation") diff --git a/backend/helpers/pluginhelper/api/enrich_with_regex.go b/backend/helpers/pluginhelper/api/enrich_with_regex.go index 4425fe32188..b31fce78bc3 100644 --- a/backend/helpers/pluginhelper/api/enrich_with_regex.go +++ b/backend/helpers/pluginhelper/api/enrich_with_regex.go @@ -107,6 +107,14 @@ func (r *RegexEnricher) ReturnNameIfOmittedOrMatched(name string, targets ...str return r.ReturnNameIfMatched(name, targets...) } +func (r *RegexEnricher) PlainMap() map[string]string { + m := make(map[string]string) + for k, v := range r.regexpMap { + m[k] = v.String() + } + return m +} + // TryAdd a named regexp if given pattern is not empty func (r *RegexEnricher) TryAddList(name string, patterns ...string) errors.Error { if _, ok := r.regexMapList[name]; ok { diff --git a/backend/helpers/pluginhelper/api/subtask_state_manager.go b/backend/helpers/pluginhelper/api/subtask_state_manager.go index 407a291bffb..7dd7d2370b0 100644 --- a/backend/helpers/pluginhelper/api/subtask_state_manager.go +++ b/backend/helpers/pluginhelper/api/subtask_state_manager.go @@ -34,7 +34,7 @@ type SubtaskCommonArgs struct { plugin.SubTaskContext Table string // raw table name Params any // for filtering rows belonging to the scope (jira board, github repo) of the subtask - SubtaskConfig any // for determining whether the subtask should run in incremental or full sync mode + SubtaskConfig any // for determining whether the subtask should run in Incremental or Full-Sync mode by comparing with the previous config to see if it changed BatchSize int // batch size for saving data } diff --git a/backend/impls/dalgorm/encdec_serializer.go b/backend/impls/dalgorm/encdec_serializer.go index bb658919590..fd7a9d88059 100644 --- a/backend/impls/dalgorm/encdec_serializer.go +++ b/backend/impls/dalgorm/encdec_serializer.go @@ -91,6 +91,11 @@ func (es *EncDecSerializer) Value(ctx context.Context, field *schema.Field, dst } target = string(b) } + if field.GORMDataType == "string" { + println("field.GORMDataType == string", field.Size) + gormTag, ok := field.Tag.Lookup("gorm") + println(ok, gormTag) + } return plugin.Encrypt(es.encryptionSecret, target) } diff --git a/backend/plugins/gitlab/e2e/mr_commits_test.go b/backend/plugins/gitlab/e2e/mr_commits_test.go index d5ef9d2a43a..2f85cc7756e 100644 --- a/backend/plugins/gitlab/e2e/mr_commits_test.go +++ b/backend/plugins/gitlab/e2e/mr_commits_test.go @@ -133,37 +133,4 @@ func TestGitlabMrCommitDataFlow(t *testing.T) { CSVRelPath: "./snapshot_tables/pull_request_commits.csv", IgnoreTypes: []interface{}{common.Model{}}, }) - - // verify conversion - dataflowTester.FlushTabler(&code.Commit{}) - dataflowTester.FlushTabler(&code.RepoCommit{}) - dataflowTester.Subtask(tasks.ConvertCommitsMeta, taskData) - dataflowTester.VerifyTable( - code.Commit{}, - "./snapshot_tables/commits.csv", - e2ehelper.ColumnWithRawData( - "sha", - "additions", - "deletions", - "dev_eq", - "message", - "author_name", - "author_email", - "authored_date", - "author_id", - "committer_name", - "committer_email", - "committed_date", - "committer_id", - ), - ) - - dataflowTester.VerifyTable( - code.RepoCommit{}, - "./snapshot_tables/repo_commits.csv", - e2ehelper.ColumnWithRawData( - "repo_id", - "commit_sha", - ), - ) } diff --git a/backend/plugins/gitlab/e2e/mr_detail_test.go b/backend/plugins/gitlab/e2e/mr_detail_test.go index c9235667634..02d1e550134 100644 --- a/backend/plugins/gitlab/e2e/mr_detail_test.go +++ b/backend/plugins/gitlab/e2e/mr_detail_test.go @@ -41,6 +41,8 @@ func TestGitlabMrDetailDataFlow(t *testing.T) { }, } // import raw data table + dataflowTester.FlushTabler(&code.PullRequestAssignee{}) + dataflowTester.FlushTabler(&code.PullRequestReviewer{}) dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_gitlab_api_merge_requests.csv", "_raw_gitlab_api_merge_request_details") diff --git a/backend/plugins/gitlab/e2e/mr_enrich_test.go b/backend/plugins/gitlab/e2e/mr_enrich_test.go deleted file mode 100644 index fd18003ccdd..00000000000 --- a/backend/plugins/gitlab/e2e/mr_enrich_test.go +++ /dev/null @@ -1,79 +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 e2e - -import ( - "testing" - - "github.com/apache/incubator-devlake/helpers/e2ehelper" - "github.com/apache/incubator-devlake/plugins/gitlab/impl" - "github.com/apache/incubator-devlake/plugins/gitlab/models" - "github.com/apache/incubator-devlake/plugins/gitlab/tasks" -) - -func TestGitlabMrEnrichDataFlow(t *testing.T) { - - var gitlab impl.Gitlab - dataflowTester := e2ehelper.NewDataFlowTester(t, "gitlab", gitlab) - - taskData := &tasks.GitlabTaskData{ - Options: &tasks.GitlabOptions{ - ConnectionId: 1, - ProjectId: 12345678, - ScopeConfig: new(models.GitlabScopeConfig), - }, - } - - // import data table - dataflowTester.ImportCsvIntoTabler("./snapshot_tables/_tool_gitlab_merge_requests.csv", &models.GitlabMergeRequest{}) - dataflowTester.ImportCsvIntoTabler("./snapshot_tables/_tool_gitlab_mr_commits.csv", &models.GitlabMrCommit{}) - dataflowTester.ImportCsvIntoTabler("./snapshot_tables/_tool_gitlab_mr_notes.csv", &models.GitlabMrNote{}) - - // verify extraction - dataflowTester.Subtask(tasks.EnrichMergeRequestsMeta, taskData) - dataflowTester.VerifyTable( - models.GitlabMergeRequest{}, - "./snapshot_tables/_tool_gitlab_merge_requests_for_enrich_test.csv", - e2ehelper.ColumnWithRawData( - "connection_id", - "gitlab_id", - "iid", - "project_id", - "source_project_id", - "target_project_id", - "state", - "title", - "web_url", - "user_notes_count", - "work_in_progress", - "source_branch", - "target_branch", - "merge_commit_sha", - "merged_at", - "gitlab_created_at", - "closed_at", - "merged_by_username", - "description", - "author_username", - "author_user_id", - "component", - "first_comment_time", - "review_rounds", - ), - ) -} diff --git a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_enrich_test.csv b/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_enrich_test.csv deleted file mode 100644 index 56804c7303b..00000000000 --- a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_enrich_test.csv +++ /dev/null @@ -1,25 +0,0 @@ -connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state,title,web_url,user_notes_count,work_in_progress,source_branch,target_branch,merge_commit_sha,merged_at,gitlab_created_at,closed_at,merged_by_username,description,author_username,author_user_id,component,first_comment_time,review_rounds,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -1,32348491,1,12345678,12345678,12345678,merged,"Resolve ""Add documentation to snowflake spend package""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/1,1,0,1-add-documentation-to-snowflake-spend-package,master,da1d6dea48f5972ffc683da6cff30934e7d6c52c,2019-06-28T14:32:06.192+00:00,2019-06-28T05:21:43.743+00:00,,tayloramurphy,Closes #1,emilie,2295562,,,2,,,0, -1,35064956,3,12345678,13835497,12345678,merged,Update README to include steps to resolve a potential dbt-utils conflict,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/3,3,0,5-update-readme-to-include-steps-to-resolve-a-potential-dbt-utils-conflict,master,d678bea9d47b42eb13512d1c9d6a592d80b432d4,2019-08-26T14:15:27.922+00:00,2019-08-15T19:34:32.706+00:00,,emilie,Closes #5,martinguindon,3871284,,,1,,,0, -1,35841926,4,12345678,12345678,12345678,merged,"Resolve ""Config is not generic enough""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/4,0,0,4-config-is-not-generic-enough,master,e95b5db25e15a38e21d11cb45cc21bf17d5c407c,2019-08-26T15:37:50.105+00:00,2019-08-26T15:32:49.557+00:00,,emilie,Closes #4,emilie,2295562,,,1,,,0, -1,53445063,5,12345678,15706315,12345678,merged,Issue 3 Base model,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5,20,0,issue_3,master,f2ee4cf121a328ce39723506dc18e4661941971a,2020-03-25T18:36:45.801+00:00,2020-03-24T12:46:15.891+00:00,,tayloramurphy,,nehiljain,783199,,,1,,,0, -1,53627854,6,12345678,15706063,12345678,merged,Update schema.yml typo in docs,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/6,0,0,patch-1,master,12dcc23a45adce0b12f8687438ec3a28274c7c30,2020-03-25T19:04:19.844+00:00,2020-03-25T19:02:16.747+00:00,,tayloramurphy,,nehiljain,783199,,,1,,,0, -1,55146687,8,12345678,12345678,12345678,merged,"Resolve ""Document release process""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/8,3,0,6-document-release-process,master,7c8245a3a5eda7f502737940aaf7944d99c58f2e,2020-04-08T20:52:11.150+00:00,2020-04-08T20:07:10.223+00:00,,emilie,Closes #6,m_walker,5212782,,,1,,,0, -1,55146787,9,12345678,15706315,12345678,opened,Issue 3: Transformed model for query performance,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/9,14,0,issue_3,master,,,2020-04-08T20:09:08.130+00:00,,,,nehiljain,783199,,,1,,,0, -1,58311001,10,12345678,12345678,12345678,merged,Update version in readme,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/10,0,0,emilie-master-patch-23079,master,66c0f1de49a0c876b8f93e8e0dce3327e766f59d,2020-05-11T17:09:20.603+00:00,2020-05-11T17:09:12.265+00:00,,emilie,,emilie,2295562,,,1,,,0, -1,62519057,11,12345678,19569570,12345678,opened,Clustering metering models,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/11,0,0,clustering-metering,master,,,2020-06-24T12:34:04.792+00:00,,,,jainnehil,842680,,,1,,,0, -1,65505080,12,12345678,12345678,12345678,merged,"Resolve ""Upgrade package for dbt 0.17""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/12,0,0,11-upgrade-package-for-dbt-0-17,master,9bfc136eb90802c2ce59956c34dde01bb3de0d50,2020-07-24T21:13:35.321+00:00,2020-07-24T17:47:08.238+00:00,,tayloramurphy,"Closes #11 - -* Upgrades to 0.17.0 format -* Formatting changes to be in line with GitLab SQL Style Guide",tayloramurphy,1942272,,,1,,,0, -1,68978485,13,12345678,15706315,12345678,closed,Include more snowflake qrt columns,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/13,0,0,include_more_snowflake_qrt_columns,master,,,2020-08-27T20:17:01.825+00:00,2020-08-27T20:20:08.150+00:00,,,aianus,2478227,,,1,,,0, -1,89243644,14,12345678,24539973,12345678,merged,Update README.md to use the newest version as an example,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/14,0,0,ThomasLaPiana-master-patch-93997,master,21840a7eadb58babe8aeae2960da851a3ed00ddc,2021-02-19T20:13:05.969+00:00,2021-02-19T20:12:14.302+00:00,,tayloramurphy,Update README.md to use the newest version as an example. The old version doesn't work with the current version of dbt,ThomasLaPiana,2061802,,,1,,,0, -1,110817220,16,12345678,28584714,12345678,merged,Update packages.yml to point to dbt-labs instead of fishtown,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/16,5,0,GJMcClintock-master-patch-24867,master,6f45b467c478df1c67d19cf6d4cbb8e05a710662,2021-08-12T06:12:54.329+00:00,2021-08-03T15:02:54.955+00:00,,vedprakash2021,With the company name change the old repo is deprecated.,GJMcClintock,9439881,,,1,,,0, -1,111383524,17,12345678,0,12345678,closed,The package name changed -> https://hub.getdbt.com/dbt-labs/dbt_utils/latest/,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/17,1,0,swiffer-master-patch-77533,master,,,2021-08-07T06:50:25.458+00:00,2021-08-07T06:51:14.933+00:00,,,swiffer,156402,,,1,,,0, -1,114994501,18,12345678,29298577,12345678,opened,Add support for Snowpipe usage monitoring,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/18,0,0,master,master,,,2021-09-01T21:15:30.334+00:00,,,Add models and docs for Snowflake pipes (Snowpipe) usage monitoring based on the views in Snowflake Usage schema,gary-beautypie,9635687,,,1,,,0, -1,135775405,19,12345678,32935405,12345678,opened,Updates for dbt 1.0,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/19,1,0,updates_for_dbt_1.0,master,,,2022-01-18T19:59:30.723+00:00,,,"This MR sets up the repo for dbt 1.0 -A few configs were renamed. - -Could a new release be made for dbt 1.0?",johnj4,10663622,,,1,,,0, -1,145012495,20,12345678,34491818,12345678,closed,Draft: Update dbt_project.yml,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/20,0,1,PedramNavid-master-patch-20645,master,,,2022-03-15T03:07:06.077+00:00,2022-03-15T03:07:22.665+00:00,,,PedramNavid,9722492,,,1,,,0, -1,158698019,21,12345678,12345678,12345678,opened,Draft: Corrections for dbt 1,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/21,0,1,updates_for_dbt_1_1,master,,,2022-06-03T09:24:53.707+00:00,,,Closes https://gitlab.com/gitlab-data/analytics/-/issues/12941,paul_armstrong,5618371,,,1,,,0, diff --git a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_commit_test.csv b/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_commit_test.csv index 2ba28fadbaf..dc468a58ba5 100644 --- a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_commit_test.csv +++ b/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_commit_test.csv @@ -1,5 +1,5 @@ -connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state,title,web_url,user_notes_count,work_in_progress,source_branch,target_branch,merge_commit_sha,merged_at,gitlab_created_at,closed_at,merged_by_username,description,author_username,author_user_id,component,first_comment_time,review_rounds,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -1,32348491,1,12345678,12345678,12345678,merged,"Resolve ""Add documentation to snowflake spend package""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/1,1,0,1-add-documentation-to-snowflake-spend-package,master,da1d6dea48f5972ffc683da6cff30934e7d6c52c,2019-06-28T14:32:06.192+00:00,2019-06-28T05:21:43.743+00:00,,tayloramurphy,Closes #1,emilie,2295562,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,1, +connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state,title,web_url,user_notes_count,work_in_progress,source_branch,target_branch,merge_commit_sha,merged_at,gitlab_created_at,closed_at,merged_by_username,description,author_username,author_user_id,component,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +1,32348491,1,12345678,12345678,12345678,merged,"Resolve ""Add documentation to snowflake spend package""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/1,1,0,1-add-documentation-to-snowflake-spend-package,master,da1d6dea48f5972ffc683da6cff30934e7d6c52c,2019-06-28T14:32:06.192+00:00,2019-06-28T05:21:43.743+00:00,,tayloramurphy,Closes #1,emilie,2295562,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,1, 1,34300715,2,12345678,12345678,12345678,merged,"Resolve ""Handle multiple prices and date ranges""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/2,9,0,2-handle-multiple-prices-and-date-ranges,master,2fe82576fdbd0a43a2d5e02c17c6dc6ce3e188ee,2019-08-04T22:24:41.219+00:00,2019-08-01T21:36:45.020+00:00,,emilie,"Closes #2 * Adds a model to amortize the snowflake_contract_rates.csv properly @@ -8,7 +8,7 @@ connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state Testing by running dbt seed on https://gitlab.com/gitlab-data/analytics/merge_requests/1351/diffs and pinning dbt deps to this branch `2-handle...`. -All models ran fine and the data looks great in my scratch schema!",tayloramurphy,1942272,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,2, -1,35064956,3,12345678,13835497,12345678,merged,Update README to include steps to resolve a potential dbt-utils conflict,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/3,3,0,5-update-readme-to-include-steps-to-resolve-a-potential-dbt-utils-conflict,master,d678bea9d47b42eb13512d1c9d6a592d80b432d4,2019-08-26T14:15:27.922+00:00,2019-08-15T19:34:32.706+00:00,,emilie,Closes #5,martinguindon,3871284,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,3, -1,35841926,4,12345678,12345678,12345678,merged,"Resolve ""Config is not generic enough""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/4,0,0,4-config-is-not-generic-enough,master,e95b5db25e15a38e21d11cb45cc21bf17d5c407c,2019-08-26T15:37:50.105+00:00,2019-08-26T15:32:49.557+00:00,,emilie,Closes #4,emilie,2295562,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,4, -1,53445063,5,12345678,15706315,12345678,merged,Issue 3 Base model,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5,20,0,issue_3,master,f2ee4cf121a328ce39723506dc18e4661941971a,2020-03-25T18:36:45.801+00:00,2020-03-24T12:46:15.891+00:00,,tayloramurphy,,nehiljain,783199,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,5, +All models ran fine and the data looks great in my scratch schema!",tayloramurphy,1942272,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,2, +1,35064956,3,12345678,13835497,12345678,merged,Update README to include steps to resolve a potential dbt-utils conflict,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/3,3,0,5-update-readme-to-include-steps-to-resolve-a-potential-dbt-utils-conflict,master,d678bea9d47b42eb13512d1c9d6a592d80b432d4,2019-08-26T14:15:27.922+00:00,2019-08-15T19:34:32.706+00:00,,emilie,Closes #5,martinguindon,3871284,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,3, +1,35841926,4,12345678,12345678,12345678,merged,"Resolve ""Config is not generic enough""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/4,0,0,4-config-is-not-generic-enough,master,e95b5db25e15a38e21d11cb45cc21bf17d5c407c,2019-08-26T15:37:50.105+00:00,2019-08-26T15:32:49.557+00:00,,emilie,Closes #4,emilie,2295562,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,4, +1,53445063,5,12345678,15706315,12345678,merged,Issue 3 Base model,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5,20,0,issue_3,master,f2ee4cf121a328ce39723506dc18e4661941971a,2020-03-25T18:36:45.801+00:00,2020-03-24T12:46:15.891+00:00,,tayloramurphy,,nehiljain,783199,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,5, diff --git a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_notes_test.csv b/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_notes_test.csv index fe38d4100c2..05d7a0c7df5 100644 --- a/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_notes_test.csv +++ b/backend/plugins/gitlab/e2e/snapshot_tables/_tool_gitlab_merge_requests_for_mr_notes_test.csv @@ -1,6 +1,6 @@ -connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state,title,web_url,user_notes_count,work_in_progress,source_branch,target_branch,merge_commit_sha,merged_at,gitlab_created_at,closed_at,merged_by_username,description,author_username,author_user_id,component,first_comment_time,review_rounds,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -1,15869219,37,12345678,12345678,12345678,opened,Draft: Corrections for dbt 1,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/21,0,1,updates_for_dbt_1_1,master,,,2022-06-03T09:24:53.707+00:00,,,Closes https://gitlab.com/gitlab-data/analytics/-/issues/12941,paul_armstrong,5618371,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,21, -1,32348491,1,12345678,12345678,12345678,merged,"Resolve ""Add documentation to snowflake spend package""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/1,1,0,1-add-documentation-to-snowflake-spend-package,master,da1d6dea48f5972ffc683da6cff30934e7d6c52c,2019-06-28T14:32:06.192+00:00,2019-06-28T05:21:43.743+00:00,,tayloramurphy,Closes #1,emilie,2295562,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,1, +connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state,title,web_url,user_notes_count,work_in_progress,source_branch,target_branch,merge_commit_sha,merged_at,gitlab_created_at,closed_at,merged_by_username,description,author_username,author_user_id,component,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +1,15869219,37,12345678,12345678,12345678,opened,Draft: Corrections for dbt 1,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/21,0,1,updates_for_dbt_1_1,master,,,2022-06-03T09:24:53.707+00:00,,,Closes https://gitlab.com/gitlab-data/analytics/-/issues/12941,paul_armstrong,5618371,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,21, +1,32348491,1,12345678,12345678,12345678,merged,"Resolve ""Add documentation to snowflake spend package""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/1,1,0,1-add-documentation-to-snowflake-spend-package,master,da1d6dea48f5972ffc683da6cff30934e7d6c52c,2019-06-28T14:32:06.192+00:00,2019-06-28T05:21:43.743+00:00,,tayloramurphy,Closes #1,emilie,2295562,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,1, 1,34300715,2,12345678,12345678,12345678,merged,"Resolve ""Handle multiple prices and date ranges""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/2,9,0,2-handle-multiple-prices-and-date-ranges,master,2fe82576fdbd0a43a2d5e02c17c6dc6ce3e188ee,2019-08-04T22:24:41.219+00:00,2019-08-01T21:36:45.020+00:00,,emilie,"Closes #2 * Adds a model to amortize the snowflake_contract_rates.csv properly @@ -9,23 +9,23 @@ connection_id,gitlab_id,iid,project_id,source_project_id,target_project_id,state Testing by running dbt seed on https://gitlab.com/gitlab-data/analytics/merge_requests/1351/diffs and pinning dbt deps to this branch `2-handle...`. -All models ran fine and the data looks great in my scratch schema!",tayloramurphy,1942272,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,2, -1,35064956,3,12345678,13835497,12345678,merged,Update README to include steps to resolve a potential dbt-utils conflict,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/3,3,0,5-update-readme-to-include-steps-to-resolve-a-potential-dbt-utils-conflict,master,d678bea9d47b42eb13512d1c9d6a592d80b432d4,2019-08-26T14:15:27.922+00:00,2019-08-15T19:34:32.706+00:00,,emilie,Closes #5,martinguindon,3871284,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,3, -1,35841926,4,12345678,12345678,12345678,merged,"Resolve ""Config is not generic enough""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/4,0,0,4-config-is-not-generic-enough,master,e95b5db25e15a38e21d11cb45cc21bf17d5c407c,2019-08-26T15:37:50.105+00:00,2019-08-26T15:32:49.557+00:00,,emilie,Closes #4,emilie,2295562,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,4, -1,53445063,5,12345678,15706315,12345678,merged,Issue 3 Base model,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5,20,0,issue_3,master,f2ee4cf121a328ce39723506dc18e4661941971a,2020-03-25T18:36:45.801+00:00,2020-03-24T12:46:15.891+00:00,,tayloramurphy,,nehiljain,783199,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,5, -1,53627854,6,12345678,15706063,12345678,merged,Update schema.yml typo in docs,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/6,0,0,patch-1,master,12dcc23a45adce0b12f8687438ec3a28274c7c30,2020-03-25T19:04:19.844+00:00,2020-03-25T19:02:16.747+00:00,,tayloramurphy,,nehiljain,783199,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,6, -1,53640548,7,12345678,12345678,12345678,merged,"Resolve ""Add sources and cleanup structure""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/7,5,0,7-add-sources-and-cleanup-structure,master,1161de80448bc66072c3ea39600d9940dde87a5b,2020-04-07T12:51:50.096+00:00,2020-03-25T21:58:40.647+00:00,,emilie,Closes #7,tayloramurphy,1942272,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,7, -1,55146687,8,12345678,12345678,12345678,merged,"Resolve ""Document release process""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/8,3,0,6-document-release-process,master,7c8245a3a5eda7f502737940aaf7944d99c58f2e,2020-04-08T20:52:11.150+00:00,2020-04-08T20:07:10.223+00:00,,emilie,Closes #6,m_walker,5212782,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,8, -1,55146787,9,12345678,15706315,12345678,opened,Issue 3: Transformed model for query performance,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/9,14,0,issue_3,master,,,2020-04-08T20:09:08.130+00:00,,,,nehiljain,783199,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,9, -1,58311001,10,12345678,12345678,12345678,merged,Update version in readme,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/10,0,0,emilie-master-patch-23079,master,66c0f1de49a0c876b8f93e8e0dce3327e766f59d,2020-05-11T17:09:20.603+00:00,2020-05-11T17:09:12.265+00:00,,emilie,,emilie,2295562,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,10, -1,62519057,11,12345678,19569570,12345678,opened,Clustering metering models,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/11,0,0,clustering-metering,master,,,2020-06-24T12:34:04.792+00:00,,,,jainnehil,842680,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,11, +All models ran fine and the data looks great in my scratch schema!",tayloramurphy,1942272,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,2, +1,35064956,3,12345678,13835497,12345678,merged,Update README to include steps to resolve a potential dbt-utils conflict,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/3,3,0,5-update-readme-to-include-steps-to-resolve-a-potential-dbt-utils-conflict,master,d678bea9d47b42eb13512d1c9d6a592d80b432d4,2019-08-26T14:15:27.922+00:00,2019-08-15T19:34:32.706+00:00,,emilie,Closes #5,martinguindon,3871284,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,3, +1,35841926,4,12345678,12345678,12345678,merged,"Resolve ""Config is not generic enough""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/4,0,0,4-config-is-not-generic-enough,master,e95b5db25e15a38e21d11cb45cc21bf17d5c407c,2019-08-26T15:37:50.105+00:00,2019-08-26T15:32:49.557+00:00,,emilie,Closes #4,emilie,2295562,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,4, +1,53445063,5,12345678,15706315,12345678,merged,Issue 3 Base model,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/5,20,0,issue_3,master,f2ee4cf121a328ce39723506dc18e4661941971a,2020-03-25T18:36:45.801+00:00,2020-03-24T12:46:15.891+00:00,,tayloramurphy,,nehiljain,783199,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,5, +1,53627854,6,12345678,15706063,12345678,merged,Update schema.yml typo in docs,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/6,0,0,patch-1,master,12dcc23a45adce0b12f8687438ec3a28274c7c30,2020-03-25T19:04:19.844+00:00,2020-03-25T19:02:16.747+00:00,,tayloramurphy,,nehiljain,783199,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,6, +1,53640548,7,12345678,12345678,12345678,merged,"Resolve ""Add sources and cleanup structure""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/7,5,0,7-add-sources-and-cleanup-structure,master,1161de80448bc66072c3ea39600d9940dde87a5b,2020-04-07T12:51:50.096+00:00,2020-03-25T21:58:40.647+00:00,,emilie,Closes #7,tayloramurphy,1942272,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,7, +1,55146687,8,12345678,12345678,12345678,merged,"Resolve ""Document release process""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/8,3,0,6-document-release-process,master,7c8245a3a5eda7f502737940aaf7944d99c58f2e,2020-04-08T20:52:11.150+00:00,2020-04-08T20:07:10.223+00:00,,emilie,Closes #6,m_walker,5212782,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,8, +1,55146787,9,12345678,15706315,12345678,opened,Issue 3: Transformed model for query performance,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/9,14,0,issue_3,master,,,2020-04-08T20:09:08.130+00:00,,,,nehiljain,783199,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,9, +1,58311001,10,12345678,12345678,12345678,merged,Update version in readme,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/10,0,0,emilie-master-patch-23079,master,66c0f1de49a0c876b8f93e8e0dce3327e766f59d,2020-05-11T17:09:20.603+00:00,2020-05-11T17:09:12.265+00:00,,emilie,,emilie,2295562,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,10, +1,62519057,11,12345678,19569570,12345678,opened,Clustering metering models,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/11,0,0,clustering-metering,master,,,2020-06-24T12:34:04.792+00:00,,,,jainnehil,842680,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,11, 1,65505080,12,12345678,12345678,12345678,merged,"Resolve ""Upgrade package for dbt 0.17""",https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/12,0,0,11-upgrade-package-for-dbt-0-17,master,9bfc136eb90802c2ce59956c34dde01bb3de0d50,2020-07-24T21:13:35.321+00:00,2020-07-24T17:47:08.238+00:00,,tayloramurphy,"Closes #11 * Upgrades to 0.17.0 format -* Formatting changes to be in line with GitLab SQL Style Guide",tayloramurphy,1942272,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,12, +* Formatting changes to be in line with GitLab SQL Style Guide",tayloramurphy,1942272,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,12, 1,135772105,30,12345678,32935405,12345678,opened,Updates for dbt 1.0,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/19,1,0,updates_for_dbt_1.0,master,,,2022-01-18T19:59:30.723+00:00,,,"This MR sets up the repo for dbt 1.0 A few configs were renamed. -Could a new release be made for dbt 1.0?",johnj4,10663622,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,19, -1,145032495,46,12345678,34491818,12345678,closed,Draft: Update dbt_project.yml,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/20,0,1,PedramNavid-master-patch-20645,master,,,2022-03-15T03:07:06.077+00:00,2022-03-15T03:07:22.665+00:00,,,PedramNavid,9722492,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,20, -1,1149942101,29,12345678,29298577,12345678,opened,Add support for Snowpipe usage monitoring,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/18,0,0,master,master,,,2021-09-01T21:15:30.334+00:00,,,Add models and docs for Snowflake pipes (Snowpipe) usage monitoring based on the views in Snowflake Usage schema,gary-beautypie,9635687,,,0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,18, +Could a new release be made for dbt 1.0?",johnj4,10663622,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,19, +1,145032495,46,12345678,34491818,12345678,closed,Draft: Update dbt_project.yml,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/20,0,1,PedramNavid-master-patch-20645,master,,,2022-03-15T03:07:06.077+00:00,2022-03-15T03:07:22.665+00:00,,,PedramNavid,9722492,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,20, +1,1149942101,29,12345678,29298577,12345678,opened,Add support for Snowpipe usage monitoring,https://gitlab.com/gitlab-data/snowflake_spend/-/merge_requests/18,0,0,master,master,,,2021-09-01T21:15:30.334+00:00,,,Add models and docs for Snowflake pipes (Snowpipe) usage monitoring based on the views in Snowflake Usage schema,gary-beautypie,9635687,,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_requests,18, diff --git a/backend/plugins/gitlab/e2e/snapshot_tables/commits.csv b/backend/plugins/gitlab/e2e/snapshot_tables/commits.csv deleted file mode 100644 index ea3ba115e55..00000000000 --- a/backend/plugins/gitlab/e2e/snapshot_tables/commits.csv +++ /dev/null @@ -1,65 +0,0 @@ -sha,additions,deletions,dev_eq,message,author_name,author_email,authored_date,author_id,committer_name,committer_email,committed_date,committer_id,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -05976c113b02fb71d5c43682bd2f9d96a3454efa,0,0,0,"tab refcatoring -",Nehil Jain,nehil@snaptravel.com,2020-03-24T18:14:03.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T18:14:03.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,34, -083864201849f6707a34d24e61c43638696f95a6,0,0,0,"Update README to include steps to resolve a potential dbt-utils conflict -",Martin Guindon,mguindon@absolunet.com,2019-08-15T19:32:19.000+00:00,mguindon@absolunet.com,Martin Guindon,mguindon@absolunet.com,2019-08-15T19:32:19.000+00:00,mguindon@absolunet.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,6, -08973065d33c6fd2fb1f592b7a1e0fbe2ee72edd,0,0,0,"add usage day -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:35:08.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:35:08.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,11, -0a4574d52b5964c37bfcb2952f6c6a8a9c6d5bcf,0,0,0,"fix name -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T19:00:50.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T19:00:50.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,7, -0dbb8bfdbbf7373656fa3eb036bdcbb25ae162da,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:40.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:40.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,26, -1cba71b355d2bd4e1350602cfb9b98cce5a5cb4d,0,0,0,"update documentation -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:53:44.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:53:44.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,8, -1f16955d45cec904c8968bb27689d91a71e9a2f2,0,0,0,"change cte address -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:28:44.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:28:44.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,12, -211795deaaaaddb23b797261cdcd148e6083d5b2,0,0,0,Update snowflake_query_history.sql,Nehil,nehil@getsnaptravel.com,2020-03-24T22:44:07.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T22:44:07.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,21, -25f2b34099a3e1867fcf73a54e50f78f3c8d8f75,0,0,0,"add documentation -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:47:28.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:47:28.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,9, -382084b42697577d3a6adf71ce73d4b5ddd22977,0,0,0,"add info on dashboard -",emilie,emilie.burke@gmail.com,2019-06-28T10:54:26.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-06-28T10:54:26.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,2, -3f04e0a61d0c4d2dd736a6bcaa3a06826269a533,0,0,0,"finish top level readme -",emilie,emilie.burke@gmail.com,2019-06-28T10:48:49.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-06-28T10:48:49.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,3, -45bed79fcdc6ba3444245f55660f839db50d79c8,0,0,0,Update .gitignore,Nehil,nehil@getsnaptravel.com,2020-03-24T18:15:29.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T18:15:29.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,33, -48295660f8bd0c0a024849d4407830face57d4bc,0,0,0,"add docs and sources -",emilie,emilie.burke@gmail.com,2020-04-05T14:39:43.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2020-04-05T14:39:43.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,37, -4f0d2f7b1a47d21b01a68e59c12d6f8885ab230e,0,0,0,"mr comments -",Nehil Jain,nehil@snaptravel.com,2020-03-24T22:40:36.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T22:40:36.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,24, -553f7613b178301da4075202afe91ebda5d97ab5,0,0,0,Update schema.yml typo for docs,Nehil,nehil@getsnaptravel.com,2020-03-25T19:01:57.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-25T19:01:57.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,16, -5a141ad0c28960b02c40e6c476d8df3cc76f58c4,0,0,0,"schema yml, untested -",Nehil Jain,2761999+nehiljain@users.noreply.github.com,2020-03-24T21:18:16.000+00:00,2761999+nehiljain@users.noreply.github.com,Nehil Jain,2761999+nehiljain@users.noreply.github.com,2020-03-24T21:18:16.000+00:00,2761999+nehiljain@users.noreply.github.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,31, -5b6a2be437e0c66ba6276030a61a10583c3f83fa,0,0,0,"merging online changes -",Nehil Jain,nehil@snaptravel.com,2020-03-24T22:42:54.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T22:42:54.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,22, -5d6c369200c633b06d85c9375f61fef297761ef1,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:22:42.000+00:00,tmurphy@gitlab.com,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:22:42.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,19, -645a724b558a7fa3885fa233d06f68f833d893fc,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:36.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:36.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,27, -64abdcdd9ee9c821f56faf93c5bb0ebc57f575e4,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:31.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:31.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,28, -6ebf519f25328e49a004f5a574c8b69ba7420be1,0,0,0,"add contract rate and dbt-utils -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:18:15.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:18:15.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,15, -81b12c995b2fc12e20fd05113cf36dbd57b6e7b0,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:21:04.000+00:00,tmurphy@gitlab.com,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:21:04.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,20, -846deac12a1263e4631ced45abbc5e157b23c1be,0,0,0,"testing -",Nehil Jain,nehil@snaptravel.com,2020-03-24T21:27:46.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T21:27:46.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,30, -8a40765e605966842b05b5d8cdf2dd6890556d09,0,0,0,"change dbt-util version -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:22:09.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:22:09.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,14, -8a96911c5350f7575215f02f0242f7e27ad3d1f4,0,0,0,"add documentation -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:46:42.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T18:46:42.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,10, -91e5666bdfe90e5ada3e65aaa9240b2b0b1a072f,0,0,0,"remove config -",emilie,emilie.burke@gmail.com,2019-08-26T15:34:33.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-08-26T15:34:33.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,17, -93d13cf14a470995ec35186292bf165e1152dc2a,0,0,0,"comments on sql -",Nehil Jain,nehiljain@Hansons-iMac.local,2020-03-24T18:55:11.000+00:00,nehiljain@Hansons-iMac.local,Nehil Jain,nehiljain@Hansons-iMac.local,2020-03-24T18:55:11.000+00:00,nehiljain@Hansons-iMac.local,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,32, -9a80506e158547d87e7ad2902c0196deff5b5c07,0,0,0,"base mmodel for query performance -",Nehil Jain,nehil@snaptravel.com,2020-03-24T12:52:28.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T12:52:28.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,35, -9e5ec04b0a8273b73936ea150275919b0602c260,0,0,0,"change names -",Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:24:35.000+00:00,tmurphy@gitlab.com,Taylor A. Murphy,tmurphy@gitlab.com,2019-08-02T17:24:35.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,13, -9ef8183140bae8c39a440d9c7eb47f3bc7dcab75,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:22:47.000+00:00,tmurphy@gitlab.com,"Taylor A Murphy, PhD",tmurphy@gitlab.com,2020-03-25T13:22:47.000+00:00,tmurphy@gitlab.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,18, -a09f2d4ae88e78d7424fba1ae6d0c036b677271d,0,0,0,"update readme -",emilie,emilie.burke@gmail.com,2020-04-05T14:43:47.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2020-04-05T14:43:47.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,36, -abbe0ab2c7bb1dc2cfaa3ef3062f378fb908ba71,0,0,0,"add first bit -",emilie,emilie.burke@gmail.com,2019-06-28T05:40:36.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-06-28T05:40:36.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,5, -ad25fcda15e310a7eb34b3e38ff9b962b54f0e03,0,0,0,"add more info to readme -",emilie,emilie.burke@gmail.com,2019-06-28T11:03:52.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-06-28T11:03:52.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,1, -bb6dfec8dcdacb5b6b37dbd8eb1aa6f9e8c06138,0,0,0,"merging online changes -",Nehil Jain,nehil@snaptravel.com,2020-03-24T22:41:35.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T22:41:35.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,23, -c4d406c077af582837d3611a46eded70151f93fb,0,0,0,"tested schema and the model -",Nehil Jain,nehil@snaptravel.com,2020-03-24T22:37:23.000+00:00,nehil@snaptravel.com,Nehil Jain,nehil@snaptravel.com,2020-03-24T22:37:23.000+00:00,nehil@snaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,29, -e01d4f03811cd0da9949848731236e0aa261cf54,0,0,0,"move analyses -",emilie,emilie.burke@gmail.com,2019-06-28T10:43:17.000+00:00,emilie.burke@gmail.com,emilie,emilie.burke@gmail.com,2019-06-28T10:43:17.000+00:00,emilie.burke@gmail.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,4, -e24fecacb1a2c85f904bef57ffd5598ca2df023c,0,0,0,Apply suggestion to models/base/snowflake_query_history.sql,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:42.000+00:00,nehil@getsnaptravel.com,Nehil,nehil@getsnaptravel.com,2020-03-24T22:39:42.000+00:00,nehil@getsnaptravel.com,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,25, diff --git a/backend/plugins/gitlab/e2e/snapshot_tables/repo_commits.csv b/backend/plugins/gitlab/e2e/snapshot_tables/repo_commits.csv deleted file mode 100644 index 1b3ee220d34..00000000000 --- a/backend/plugins/gitlab/e2e/snapshot_tables/repo_commits.csv +++ /dev/null @@ -1,38 +0,0 @@ -repo_id,commit_sha,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -gitlab:GitlabProject:1:12345678,05976c113b02fb71d5c43682bd2f9d96a3454efa,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,34, -gitlab:GitlabProject:1:12345678,083864201849f6707a34d24e61c43638696f95a6,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,6, -gitlab:GitlabProject:1:12345678,08973065d33c6fd2fb1f592b7a1e0fbe2ee72edd,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,11, -gitlab:GitlabProject:1:12345678,0a4574d52b5964c37bfcb2952f6c6a8a9c6d5bcf,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,7, -gitlab:GitlabProject:1:12345678,0dbb8bfdbbf7373656fa3eb036bdcbb25ae162da,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,26, -gitlab:GitlabProject:1:12345678,1cba71b355d2bd4e1350602cfb9b98cce5a5cb4d,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,8, -gitlab:GitlabProject:1:12345678,1f16955d45cec904c8968bb27689d91a71e9a2f2,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,12, -gitlab:GitlabProject:1:12345678,211795deaaaaddb23b797261cdcd148e6083d5b2,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,21, -gitlab:GitlabProject:1:12345678,25f2b34099a3e1867fcf73a54e50f78f3c8d8f75,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,9, -gitlab:GitlabProject:1:12345678,382084b42697577d3a6adf71ce73d4b5ddd22977,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,2, -gitlab:GitlabProject:1:12345678,3f04e0a61d0c4d2dd736a6bcaa3a06826269a533,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,3, -gitlab:GitlabProject:1:12345678,45bed79fcdc6ba3444245f55660f839db50d79c8,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,33, -gitlab:GitlabProject:1:12345678,48295660f8bd0c0a024849d4407830face57d4bc,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,37, -gitlab:GitlabProject:1:12345678,4f0d2f7b1a47d21b01a68e59c12d6f8885ab230e,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,24, -gitlab:GitlabProject:1:12345678,553f7613b178301da4075202afe91ebda5d97ab5,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,16, -gitlab:GitlabProject:1:12345678,5a141ad0c28960b02c40e6c476d8df3cc76f58c4,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,31, -gitlab:GitlabProject:1:12345678,5b6a2be437e0c66ba6276030a61a10583c3f83fa,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,22, -gitlab:GitlabProject:1:12345678,5d6c369200c633b06d85c9375f61fef297761ef1,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,19, -gitlab:GitlabProject:1:12345678,645a724b558a7fa3885fa233d06f68f833d893fc,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,27, -gitlab:GitlabProject:1:12345678,64abdcdd9ee9c821f56faf93c5bb0ebc57f575e4,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,28, -gitlab:GitlabProject:1:12345678,6ebf519f25328e49a004f5a574c8b69ba7420be1,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,15, -gitlab:GitlabProject:1:12345678,81b12c995b2fc12e20fd05113cf36dbd57b6e7b0,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,20, -gitlab:GitlabProject:1:12345678,846deac12a1263e4631ced45abbc5e157b23c1be,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,30, -gitlab:GitlabProject:1:12345678,8a40765e605966842b05b5d8cdf2dd6890556d09,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,14, -gitlab:GitlabProject:1:12345678,8a96911c5350f7575215f02f0242f7e27ad3d1f4,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,10, -gitlab:GitlabProject:1:12345678,91e5666bdfe90e5ada3e65aaa9240b2b0b1a072f,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,17, -gitlab:GitlabProject:1:12345678,93d13cf14a470995ec35186292bf165e1152dc2a,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,32, -gitlab:GitlabProject:1:12345678,9a80506e158547d87e7ad2902c0196deff5b5c07,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,35, -gitlab:GitlabProject:1:12345678,9e5ec04b0a8273b73936ea150275919b0602c260,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,13, -gitlab:GitlabProject:1:12345678,9ef8183140bae8c39a440d9c7eb47f3bc7dcab75,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,18, -gitlab:GitlabProject:1:12345678,a09f2d4ae88e78d7424fba1ae6d0c036b677271d,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,36, -gitlab:GitlabProject:1:12345678,abbe0ab2c7bb1dc2cfaa3ef3062f378fb908ba71,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,5, -gitlab:GitlabProject:1:12345678,ad25fcda15e310a7eb34b3e38ff9b962b54f0e03,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,1, -gitlab:GitlabProject:1:12345678,bb6dfec8dcdacb5b6b37dbd8eb1aa6f9e8c06138,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,23, -gitlab:GitlabProject:1:12345678,c4d406c077af582837d3611a46eded70151f93fb,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,29, -gitlab:GitlabProject:1:12345678,e01d4f03811cd0da9949848731236e0aa261cf54,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,4, -gitlab:GitlabProject:1:12345678,e24fecacb1a2c85f904bef57ffd5598ca2df023c,"{""ConnectionId"":1,""ProjectId"":12345678}",_raw_gitlab_api_merge_request_commits,25, diff --git a/backend/plugins/gitlab/models/migrationscripts/20240904_remove_mr_review_fields.go b/backend/plugins/gitlab/models/migrationscripts/20240904_remove_mr_review_fields.go new file mode 100644 index 00000000000..2628033f06f --- /dev/null +++ b/backend/plugins/gitlab/models/migrationscripts/20240904_remove_mr_review_fields.go @@ -0,0 +1,40 @@ +/* +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 = (*removeMrEnricherFields)(nil) + +type removeMrEnricherFields struct{} + +func (script *removeMrEnricherFields) Up(basicRes context.BasicRes) errors.Error { + return basicRes.GetDal().DropColumns("_tool_gitlab_merge_requests", "first_comment_time", "review_rounds") +} + +func (*removeMrEnricherFields) Version() uint64 { + return 20240904152414 +} + +func (*removeMrEnricherFields) Name() string { + return "remove mr review fields in favor of dora plugin" +} diff --git a/backend/plugins/gitlab/models/mr.go b/backend/plugins/gitlab/models/mr.go index 6ac3c9b7690..c25df4ba07f 100644 --- a/backend/plugins/gitlab/models/mr.go +++ b/backend/plugins/gitlab/models/mr.go @@ -50,9 +50,7 @@ type GitlabMergeRequest struct { Description string AuthorUsername string `gorm:"type:varchar(255)"` AuthorUserId int - Component string `gorm:"type:varchar(255)"` - FirstCommentTime *time.Time `gorm:"comment:Time when the first comment occurred"` - ReviewRounds int `gorm:"comment:How many rounds of review this MR went through"` + Component string `gorm:"type:varchar(255)"` common.NoPKModel } diff --git a/backend/plugins/gitlab/tasks/account_collector.go b/backend/plugins/gitlab/tasks/account_collector.go index 52ea1a72d84..e0849858971 100644 --- a/backend/plugins/gitlab/tasks/account_collector.go +++ b/backend/plugins/gitlab/tasks/account_collector.go @@ -43,7 +43,7 @@ var CollectAccountsMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "collect gitlab users, does not support either timeFilter or diffSync.", DomainTypes: []string{plugin.DOMAIN_TYPE_CROSS}, - Dependencies: []*plugin.SubTaskMeta{&EnrichMergeRequestsMeta}, + Dependencies: []*plugin.SubTaskMeta{}, } func CollectAccounts(taskCtx plugin.SubTaskContext) errors.Error { @@ -58,7 +58,7 @@ func CollectAccounts(taskCtx plugin.SubTaskContext) errors.Error { } // Collect all users if endpoint is private gitlab instance - if !strings.HasPrefix(data.ApiClient.GetEndpoint(), "https://gitlab.com") { + if !strings.HasPrefix(data.ApiClient.GetEndpoint(), "https://gitlab.com") && !strings.HasPrefix(data.ApiClient.GetEndpoint(), "https://jihulab.com") { urlTemplate = "/users" } diff --git a/backend/plugins/gitlab/tasks/child_pipeline_extractor.go b/backend/plugins/gitlab/tasks/child_pipeline_extractor.go index 4c7d8d8755e..62c5948fc7d 100644 --- a/backend/plugins/gitlab/tasks/child_pipeline_extractor.go +++ b/backend/plugins/gitlab/tasks/child_pipeline_extractor.go @@ -18,8 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" - "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -40,32 +38,19 @@ var ExtractApiChildPipelinesMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiChildPipelinesMeta}, } -func ExtractApiChildPipelines(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_CHILD_PIPELINE_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - gitlabApiChildPipeline := &ApiPipeline{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiChildPipeline)) - if err != nil { - return nil, err - } - pipelineProject := convertApiPipelineToGitlabPipelineProject(gitlabApiChildPipeline, data.Options.ConnectionId, data.Options.ProjectId) +func ExtractApiChildPipelines(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_CHILD_PIPELINE_TABLE) + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[ApiPipeline]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiPipeline *ApiPipeline, row *api.RawData) ([]interface{}, errors.Error) { + pipelineProject := convertApiPipelineToGitlabPipelineProject(gitlabApiPipeline, data.Options.ConnectionId, data.Options.ProjectId) return []interface{}{pipelineProject}, nil }, }) - - if err != nil { - return err - } - - err = extractor.Execute() if err != nil { return err } - - return nil + return extractor.Execute() } func convertApiPipelineToGitlabPipelineProject(gitlabApiChildPipeline *ApiPipeline, connectionId uint64, projectId int) *models.GitlabPipelineProject { diff --git a/backend/plugins/gitlab/tasks/commit_collector.go b/backend/plugins/gitlab/tasks/commit_collector.go deleted file mode 100644 index 4bb2e960f8f..00000000000 --- a/backend/plugins/gitlab/tasks/commit_collector.go +++ /dev/null @@ -1,80 +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 ( - "github.com/apache/incubator-devlake/core/errors" - "github.com/apache/incubator-devlake/core/models/common" - "github.com/apache/incubator-devlake/core/plugin" - "github.com/apache/incubator-devlake/helpers/pluginhelper/api" -) - -func init() { - RegisterSubtaskMeta(&CollectApiCommitsMeta) -} - -const RAW_COMMIT_TABLE = "gitlab_api_commit" - -var CollectApiCommitsMeta = plugin.SubTaskMeta{ - Name: "Collect Commits", - EntryPoint: CollectApiCommits, - EnabledByDefault: false, - Description: "Collect commit data from gitlab api, does not support either timeFilter or diffSync.", - DomainTypes: []string{plugin.DOMAIN_TYPE_CODE}, - Dependencies: []*plugin.SubTaskMeta{&ConvertJobMeta}, -} - -type GitlabApiCommit struct { - GitlabId string `json:"id"` - Title string - Message string - ProjectId int - ShortId string `json:"short_id"` - AuthorName string `json:"author_name"` - AuthorEmail string `json:"author_email"` - AuthoredDate common.Iso8601Time `json:"authored_date"` - CommitterName string `json:"committer_name"` - CommitterEmail string `json:"committer_email"` - CommittedDate common.Iso8601Time `json:"committed_date"` - WebUrl string `json:"web_url"` - Stats struct { - Additions int - Deletions int - Total int - } -} - -func CollectApiCommits(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_COMMIT_TABLE) - - collector, err := api.NewApiCollector(api.ApiCollectorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - ApiClient: data.ApiClient, - PageSize: 100, - Incremental: false, - UrlTemplate: "projects/{{ .Params.ProjectId }}/repository/commits", - Query: GetQuery, - ResponseParser: GetRawMessageFromResponse, - }) - - if err != nil { - return err - } - - return collector.Execute() -} diff --git a/backend/plugins/gitlab/tasks/commit_convertor.go b/backend/plugins/gitlab/tasks/commit_convertor.go deleted file mode 100644 index c0fb77a794d..00000000000 --- a/backend/plugins/gitlab/tasks/commit_convertor.go +++ /dev/null @@ -1,108 +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" - - "github.com/apache/incubator-devlake/core/dal" - "github.com/apache/incubator-devlake/core/errors" - "github.com/apache/incubator-devlake/core/models/domainlayer/code" - "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" - "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" - "github.com/apache/incubator-devlake/plugins/gitlab/models" -) - -func init() { - RegisterSubtaskMeta(&ConvertCommitsMeta) -} - -var ConvertCommitsMeta = plugin.SubTaskMeta{ - Name: "Convert Commits", - EntryPoint: ConvertApiCommits, - EnabledByDefault: false, - Description: "Update domain layer commit according to GitlabCommit", - DomainTypes: []string{plugin.DOMAIN_TYPE_CODE}, - Dependencies: []*plugin.SubTaskMeta{&ConvertMrLabelsMeta}, -} - -func ConvertApiCommits(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_COMMIT_TABLE) - db := taskCtx.GetDal() - - // select all commits belongs to the project - clauses := []dal.Clause{ - dal.Select("gc.*"), - dal.From("_tool_gitlab_commits gc"), - dal.Join(`left join _tool_gitlab_project_commits gpc on ( - gpc.commit_sha = gc.sha - )`), - dal.Where("gpc.gitlab_project_id = ? and gpc.connection_id = ? ", - data.Options.ProjectId, data.Options.ConnectionId), - } - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() - - // TODO: adopt batch indate operation - //userDidGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabCommit{}), - Input: cursor, - - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabCommit := inputRow.(*models.GitlabCommit) - - // convert commit - commit := &code.Commit{} - commit.Sha = gitlabCommit.Sha - commit.Message = gitlabCommit.Message - commit.Additions = gitlabCommit.Additions - commit.Deletions = gitlabCommit.Deletions - commit.AuthorId = gitlabCommit.AuthorEmail - commit.AuthorName = gitlabCommit.AuthorName - commit.AuthorEmail = gitlabCommit.AuthorEmail - commit.AuthoredDate = gitlabCommit.AuthoredDate - commit.CommitterName = gitlabCommit.CommitterName - commit.CommitterEmail = gitlabCommit.CommitterEmail - commit.CommittedDate = gitlabCommit.CommittedDate - commit.CommitterId = gitlabCommit.CommitterEmail - - // convert repo / commits relationship - repoCommit := &code.RepoCommit{ - RepoId: didgen.NewDomainIdGenerator(&models.GitlabProject{}).Generate(data.Options.ConnectionId, data.Options.ProjectId), - CommitSha: gitlabCommit.Sha, - } - - return []interface{}{ - commit, - repoCommit, - }, nil - }, - }) - if err != nil { - return err - } - - return converter.Execute() -} diff --git a/backend/plugins/gitlab/tasks/commit_extractor.go b/backend/plugins/gitlab/tasks/commit_extractor.go deleted file mode 100644 index 664f8eae3fd..00000000000 --- a/backend/plugins/gitlab/tasks/commit_extractor.go +++ /dev/null @@ -1,116 +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 ( - "encoding/json" - - "github.com/apache/incubator-devlake/core/errors" - "github.com/apache/incubator-devlake/core/plugin" - "github.com/apache/incubator-devlake/helpers/pluginhelper/api" - "github.com/apache/incubator-devlake/plugins/gitlab/models" -) - -func init() { - RegisterSubtaskMeta(&ExtractApiCommitsMeta) -} - -var ExtractApiCommitsMeta = plugin.SubTaskMeta{ - Name: "Extract Commits", - EntryPoint: ExtractApiCommits, - EnabledByDefault: false, - Description: "Extract raw commit data into tool layer table GitlabCommit,GitlabAccount and GitlabProjectCommit", - DomainTypes: []string{plugin.DOMAIN_TYPE_CODE}, - Dependencies: []*plugin.SubTaskMeta{&CollectApiCommitsMeta}, -} - -func ExtractApiCommits(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_COMMIT_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - // need to extract 3 kinds of entities here - results := make([]interface{}, 0, 3) - - // create gitlab commit - gitlabApiCommit := &GitlabApiCommit{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiCommit)) - if err != nil { - return nil, err - } - gitlabCommit, err := ConvertCommit(gitlabApiCommit) - if err != nil { - return nil, err - } - - // create project/commits relationship - gitlabProjectCommit := &models.GitlabProjectCommit{GitlabProjectId: data.Options.ProjectId} - gitlabProjectCommit.CommitSha = gitlabCommit.Sha - - // create gitlab user - GitlabAccountAuthor := &models.GitlabAccount{} - GitlabAccountAuthor.Email = gitlabCommit.AuthorEmail - GitlabAccountAuthor.Name = gitlabCommit.AuthorName - - gitlabProjectCommit.ConnectionId = data.Options.ConnectionId - GitlabAccountAuthor.ConnectionId = data.Options.ConnectionId - results = append(results, gitlabCommit) - results = append(results, gitlabProjectCommit) - results = append(results, GitlabAccountAuthor) - - // For Commiter Email is not same as AuthorEmail - if gitlabCommit.CommitterEmail != GitlabAccountAuthor.Email { - gitlabAccountCommitter := &models.GitlabAccount{} - gitlabAccountCommitter.Email = gitlabCommit.CommitterEmail - gitlabAccountCommitter.Name = gitlabCommit.CommitterName - gitlabAccountCommitter.ConnectionId = data.Options.ConnectionId - results = append(results, gitlabAccountCommitter) - } - - return results, nil - }, - }) - - if err != nil { - return err - } - - return extractor.Execute() -} - -// Convert the API response to our DB model instance -func ConvertCommit(commit *GitlabApiCommit) (*models.GitlabCommit, errors.Error) { - gitlabCommit := &models.GitlabCommit{ - Sha: commit.GitlabId, - Title: commit.Title, - Message: commit.Message, - ShortId: commit.ShortId, - AuthorName: commit.AuthorName, - AuthorEmail: commit.AuthorEmail, - AuthoredDate: commit.AuthoredDate.ToTime(), - CommitterName: commit.CommitterName, - CommitterEmail: commit.CommitterEmail, - CommittedDate: commit.CommittedDate.ToTime(), - WebUrl: commit.WebUrl, - Additions: commit.Stats.Additions, - Deletions: commit.Stats.Deletions, - Total: commit.Stats.Total, - } - return gitlabCommit, nil -} diff --git a/backend/plugins/gitlab/tasks/deployment_convertor.go b/backend/plugins/gitlab/tasks/deployment_convertor.go index 06ed5923de0..60a464b7872 100644 --- a/backend/plugins/gitlab/tasks/deployment_convertor.go +++ b/backend/plugins/gitlab/tasks/deployment_convertor.go @@ -19,7 +19,6 @@ package tasks import ( "fmt" - "reflect" "time" "github.com/apache/incubator-devlake/core/dal" @@ -50,9 +49,9 @@ var ConvertDeploymentMeta = plugin.SubTaskMeta{ // ConvertDeployment should be split into two task theoretically // But in GitLab, all deployments have commits, so there is no need to change it. -func ConvertDeployment(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_DEPLOYMENT) - db := taskCtx.GetDal() +func ConvertDeployment(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_DEPLOYMENT) + db := subtaskCtx.GetDal() repo := &models.GitlabProject{} err := db.First(repo, dal.Where("gitlab_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId)) @@ -61,25 +60,24 @@ func ConvertDeployment(taskCtx plugin.SubTaskContext) errors.Error { } projectIdGen := didgen.NewDomainIdGenerator(&models.GitlabProject{}) - - cursor, err := db.Cursor( - dal.From(&models.GitlabDeployment{}), - dal.Where("connection_id = ? AND gitlab_id = ?", data.Options.ConnectionId, data.Options.ProjectId), - ) - if err != nil { - return err - } - defer cursor.Close() - idGen := didgen.NewDomainIdGenerator(&models.GitlabDeployment{}) - converter, err := api.NewDataConverter(api.DataConverterArgs{ - InputRowType: reflect.TypeOf(models.GitlabDeployment{}), - Input: cursor, - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabDeployment := inputRow.(*models.GitlabDeployment) - + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabDeployment]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(&models.GitlabDeployment{}), + dal.Where("connection_id = ? AND gitlab_id = ?", data.Options.ConnectionId, data.Options.ProjectId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(gitlabDeployment *models.GitlabDeployment) ([]interface{}, errors.Error) { var duration *float64 if gitlabDeployment.DeployableDuration != nil { deployableDuration := cast.ToFloat64(*gitlabDeployment.DeployableDuration) diff --git a/backend/plugins/gitlab/tasks/deployment_extractor.go b/backend/plugins/gitlab/tasks/deployment_extractor.go index 0b439aceb56..258471b01c4 100644 --- a/backend/plugins/gitlab/tasks/deployment_extractor.go +++ b/backend/plugins/gitlab/tasks/deployment_extractor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" "time" "github.com/apache/incubator-devlake/core/errors" @@ -44,16 +43,11 @@ var ExtractDeploymentMeta = plugin.SubTaskMeta{ } func ExtractDeployment(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_DEPLOYMENT) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - deploymentResp := &GitlabDeploymentResp{} - err := errors.Convert(json.Unmarshal(row.Data, deploymentResp)) - if err != nil { - return nil, err - } + subtaskCommonArgs, data := CreateSubtaskCommonArgs(taskCtx, RAW_DEPLOYMENT) + + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[GitlabDeploymentResp]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(deploymentResp *GitlabDeploymentResp, row *api.RawData) ([]interface{}, errors.Error) { gitlabDeployment := deploymentResp.toGitlabDeployment(data.Options.ConnectionId, data.Options.ProjectId) return []interface{}{ gitlabDeployment, diff --git a/backend/plugins/gitlab/tasks/issue_assignee_convertor.go b/backend/plugins/gitlab/tasks/issue_assignee_convertor.go index f4a70065d8a..ce5ce593fcc 100644 --- a/backend/plugins/gitlab/tasks/issue_assignee_convertor.go +++ b/backend/plugins/gitlab/tasks/issue_assignee_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/models/domainlayer/ticket" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -40,35 +38,36 @@ var ConvertIssueAssigneeMeta = plugin.SubTaskMeta{ Description: "Convert tool layer table _tool_gitlab_issue_assignees into domain layer table issue_assignees", DomainTypes: []string{plugin.DOMAIN_TYPE_TICKET}, DependencyTables: []string{models.GitlabIssueAssignee{}.TableName()}, - Dependencies: []*plugin.SubTaskMeta{&ExtractApiIssuesMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertIssuesMeta}, } -func ConvertIssueAssignee(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_TABLE) - - cursor, err := db.Cursor( - dal.From(&models.GitlabIssueAssignee{}), - dal.Where("project_id = ? and connection_id=?", data.Options.ProjectId, data.Options.ConnectionId), - ) - if err != nil { - return err - } - defer cursor.Close() +func ConvertIssueAssignee(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_ISSUE_TABLE) + db := subtaskCtx.GetDal() issueIdGen := didgen.NewDomainIdGenerator(&models.GitlabIssue{}) accountIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabIssueAssignee{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - input := inputRow.(*models.GitlabIssueAssignee) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabIssueAssignee]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(&models.GitlabIssueAssignee{}), + dal.Where("connection_id = ? AND project_id = ?", data.Options.ConnectionId, data.Options.ProjectId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(issueAssignee *models.GitlabIssueAssignee) ([]interface{}, errors.Error) { domainIssueAssignee := &ticket.IssueAssignee{ - IssueId: issueIdGen.Generate(data.Options.ConnectionId, input.GitlabId), - AssigneeId: accountIdGen.Generate(data.Options.ConnectionId, input.AssigneeId), - AssigneeName: input.AssigneeName, + IssueId: issueIdGen.Generate(data.Options.ConnectionId, issueAssignee.GitlabId), + AssigneeId: accountIdGen.Generate(data.Options.ConnectionId, issueAssignee.AssigneeId), + AssigneeName: issueAssignee.AssigneeName, } return []interface{}{domainIssueAssignee}, nil }, diff --git a/backend/plugins/gitlab/tasks/issue_convertor.go b/backend/plugins/gitlab/tasks/issue_convertor.go index 9be3c1d1822..63af1c6593e 100644 --- a/backend/plugins/gitlab/tasks/issue_convertor.go +++ b/backend/plugins/gitlab/tasks/issue_convertor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "reflect" "strconv" "strings" @@ -28,7 +27,7 @@ import ( "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/models/domainlayer/ticket" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -45,32 +44,41 @@ var ConvertIssuesMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&ConvertApiMrCommitsMeta}, } -func ConvertIssues(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_TABLE) - projectId := data.Options.ProjectId - - clauses := []dal.Clause{ - dal.Select("issues.*"), - dal.From("_tool_gitlab_issues issues"), - dal.Where("project_id = ? and connection_id = ?", projectId, data.Options.ConnectionId), - } - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertIssues(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_ISSUE_TABLE) + db := subtaskCtx.GetDal() + projectId := data.Options.ProjectId issueIdGen := didgen.NewDomainIdGenerator(&models.GitlabIssue{}) accountIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) boardIdGen := didgen.NewDomainIdGenerator(&models.GitlabProject{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabIssue{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - issue := inputRow.(*models.GitlabIssue) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabIssue]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(&models.GitlabIssue{}), + dal.Where("connection_id = ? AND project_id = ?", data.Options.ConnectionId, data.Options.ProjectId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + BeforeConvert: func(issue *models.GitlabIssue, stateManager *api.SubtaskStateManager) errors.Error { + issueId := issueIdGen.Generate(data.Options.ConnectionId, issue.GitlabId) + if err := db.Delete(&ticket.IssueLabel{}, dal.Where("issue_id = ?", issueId)); err != nil { + return err + } + if err := db.Delete(&ticket.IssueAssignee{}, dal.Where("issue_id = ?", issueId)); err != nil { + return err + } + return nil + }, + Convert: func(issue *models.GitlabIssue) ([]interface{}, errors.Error) { domainIssue := &ticket.Issue{ DomainEntity: domainlayer.DomainEntity{Id: issueIdGen.Generate(data.Options.ConnectionId, issue.GitlabId)}, IssueKey: strconv.Itoa(issue.Number), @@ -107,6 +115,7 @@ func ConvertIssues(taskCtx plugin.SubTaskContext) errors.Error { BoardId: boardIdGen.Generate(data.Options.ConnectionId, projectId), IssueId: domainIssue.Id, } + return []interface{}{ domainIssue, boardIssue, diff --git a/backend/plugins/gitlab/tasks/issue_extractor.go b/backend/plugins/gitlab/tasks/issue_extractor.go index 717e0ca9861..802d58a6074 100644 --- a/backend/plugins/gitlab/tasks/issue_extractor.go +++ b/backend/plugins/gitlab/tasks/issue_extractor.go @@ -18,9 +18,9 @@ limitations under the License. package tasks import ( - "encoding/json" "regexp" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -133,8 +133,10 @@ type IssuesResponse struct { } } -func ExtractApiIssues(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_TABLE) +func ExtractApiIssues(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_ISSUE_TABLE) + + db := subtaskCtx.GetDal() config := data.Options.ScopeConfig var issueSeverityRegex *regexp.Regexp var issueComponentRegex *regexp.Regexp @@ -162,15 +164,33 @@ func ExtractApiIssues(taskCtx plugin.SubTaskContext) errors.Error { return errors.Default.Wrap(err, "regexp Compile issuePriority failed") } } - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - body := &IssuesResponse{} - err := errors.Convert(json.Unmarshal(row.Data, body)) - if err != nil { - return nil, err + subtaskCommonArgs.SubtaskConfig = map[string]interface{}{ + "issueSeverity": issueSeverity, + "issueComponent": issueComponent, + "issuePriorityRegex": issuePriorityRegex, + } + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[IssuesResponse]{ + SubtaskCommonArgs: subtaskCommonArgs, + BeforeExtract: func(body *IssuesResponse, stateManager *api.SubtaskStateManager) errors.Error { + if stateManager.IsIncremental() { + err := db.Delete( + &models.GitlabIssueLabel{}, + dal.Where("connection_id = ? AND issue_id = ?", data.Options.ConnectionId, body.Id), + ) + if err != nil { + return err + } + err = db.Delete( + &models.GitlabIssueAssignee{}, + dal.Where("connection_id = ? AND gitlab_id = ?", data.Options.ConnectionId, body.Id), + ) + if err != nil { + return err + } } - + return nil + }, + Extract: func(body *IssuesResponse, row *api.RawData) ([]interface{}, errors.Error) { if body.ProjectId == 0 { return nil, nil } @@ -182,9 +202,9 @@ func ExtractApiIssues(taskCtx plugin.SubTaskContext) errors.Error { } for _, label := range body.Labels { results = append(results, &models.GitlabIssueLabel{ + ConnectionId: data.Options.ConnectionId, IssueId: gitlabIssue.GitlabId, LabelName: label, - ConnectionId: data.Options.ConnectionId, }) if issueSeverityRegex != nil && issueSeverityRegex.MatchString(label) { gitlabIssue.Severity = label diff --git a/backend/plugins/gitlab/tasks/issue_label_convertor.go b/backend/plugins/gitlab/tasks/issue_label_convertor.go index c5e8968dda6..fab745dda9e 100644 --- a/backend/plugins/gitlab/tasks/issue_label_convertor.go +++ b/backend/plugins/gitlab/tasks/issue_label_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/models/domainlayer/ticket" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -42,35 +40,32 @@ var ConvertIssueLabelsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&ConvertIssuesMeta}, } -func ConvertIssueLabels(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_ISSUE_TABLE) - projectId := data.Options.ProjectId - clauses := []dal.Clause{ - dal.Select("*"), - dal.From(&models.GitlabIssueLabel{}), - dal.Join(`left join _tool_gitlab_issues on - _tool_gitlab_issues.gitlab_id = _tool_gitlab_issue_labels.issue_id`), - dal.Where(`_tool_gitlab_issues.project_id = ? - and _tool_gitlab_issues.connection_id = ?`, - projectId, data.Options.ConnectionId), - dal.Orderby("issue_id ASC"), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertIssueLabels(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_ISSUE_TABLE) + db := subtaskCtx.GetDal() + projectId := data.Options.ProjectId issueIdGen := didgen.NewDomainIdGenerator(&models.GitlabIssue{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabIssueLabel{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - issueLabel := inputRow.(*models.GitlabIssueLabel) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabIssueLabel]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.Select("l.*"), + dal.From("_tool_gitlab_issue_labels l"), + dal.Join("LEFT JOIN _tool_gitlab_issues s ON s.gitlab_id = l.issue_id AND l.connection_id = s.connection_id"), + dal.Where("s.project_id = ? AND s.connection_id = ?", projectId, data.Options.ConnectionId), + // dal.Orderby("s.issue_id ASC"), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("l.updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(issueLabel *models.GitlabIssueLabel) ([]interface{}, errors.Error) { domainIssueLabel := &ticket.IssueLabel{ IssueId: issueIdGen.Generate(data.Options.ConnectionId, issueLabel.IssueId), LabelName: issueLabel.LabelName, diff --git a/backend/plugins/gitlab/tasks/job_convertor.go b/backend/plugins/gitlab/tasks/job_convertor.go index e6e14a41f3e..517701a6d11 100644 --- a/backend/plugins/gitlab/tasks/job_convertor.go +++ b/backend/plugins/gitlab/tasks/job_convertor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "reflect" "time" "github.com/apache/incubator-devlake/core/dal" @@ -28,7 +27,7 @@ import ( "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" - gitlabModels "github.com/apache/incubator-devlake/plugins/gitlab/models" + "github.com/apache/incubator-devlake/plugins/gitlab/models" ) func init() { @@ -44,35 +43,31 @@ var ConvertJobMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&ConvertPipelineCommitMeta}, } -func ConvertJobs(taskCtx plugin.SubTaskContext) (err errors.Error) { - db := taskCtx.GetDal() - data := taskCtx.GetData().(*GitlabTaskData) +func ConvertJobs(subtaskCtx plugin.SubTaskContext) (err errors.Error) { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_JOB_TABLE) + db := subtaskCtx.GetDal() regexEnricher := data.RegexEnricher + subtaskCommonArgs.SubtaskConfig = regexEnricher.PlainMap() - cursor, err := db.Cursor(dal.From(gitlabModels.GitlabJob{}), - dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId)) - if err != nil { - return err - } - defer cursor.Close() - - jobIdGen := didgen.NewDomainIdGenerator(&gitlabModels.GitlabJob{}) - projectIdGen := didgen.NewDomainIdGenerator(&gitlabModels.GitlabProject{}) - pipelineIdGen := didgen.NewDomainIdGenerator(&gitlabModels.GitlabPipeline{}) - converter, err := api.NewDataConverter(api.DataConverterArgs{ - InputRowType: reflect.TypeOf(gitlabModels.GitlabJob{}), - Input: cursor, - RawDataSubTaskArgs: api.RawDataSubTaskArgs{ - Ctx: taskCtx, - Params: gitlabModels.GitlabApiParams{ - ConnectionId: data.Options.ConnectionId, - ProjectId: data.Options.ProjectId, - }, - Table: RAW_JOB_TABLE, + jobIdGen := didgen.NewDomainIdGenerator(&models.GitlabJob{}) + projectIdGen := didgen.NewDomainIdGenerator(&models.GitlabProject{}) + pipelineIdGen := didgen.NewDomainIdGenerator(&models.GitlabPipeline{}) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabJob]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(models.GitlabJob{}), + dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) }, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabJob := inputRow.(*gitlabModels.GitlabJob) - + Convert: func(gitlabJob *models.GitlabJob) ([]interface{}, errors.Error) { createdAt := time.Now() if gitlabJob.GitlabCreatedAt != nil { createdAt = *gitlabJob.GitlabCreatedAt diff --git a/backend/plugins/gitlab/tasks/job_extractor.go b/backend/plugins/gitlab/tasks/job_extractor.go index 420fe7a302f..15b1343dcf8 100644 --- a/backend/plugins/gitlab/tasks/job_extractor.go +++ b/backend/plugins/gitlab/tasks/job_extractor.go @@ -18,8 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" - "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -59,18 +57,12 @@ var ExtractApiJobsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiJobsMeta}, } -func ExtractApiJobs(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_JOB_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - gitlabApiJob := &ApiJob{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiJob)) - if err != nil { - return nil, err - } +func ExtractApiJobs(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_JOB_TABLE) + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[ApiJob]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiJob *ApiJob, row *api.RawData) ([]interface{}, errors.Error) { gitlabPipeline, err := convertJob(gitlabApiJob, data.Options.ProjectId) if err != nil { return nil, err diff --git a/backend/plugins/gitlab/tasks/mr_assignee_convertor.go b/backend/plugins/gitlab/tasks/mr_assignee_convertor.go index d638d1dc0b3..d22714a7485 100644 --- a/backend/plugins/gitlab/tasks/mr_assignee_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_assignee_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -39,39 +37,33 @@ var ConvertMrAssigneesMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Convert tool layer table gitlab_assignees into domain layer table pull_request_assignees", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ExtractApiMergeRequestDetailsMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta}, } -func ConvertMrAssignees(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) +func ConvertMrAssignees(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_TABLE) + db := subtaskCtx.GetDal() projectId := data.Options.ProjectId - clauses := []dal.Clause{ - dal.Select("_tool_gitlab_assignees.*"), - dal.From(&models.GitlabAssignee{}), - dal.Join(`left join _tool_gitlab_merge_requests mr on - mr.gitlab_id = _tool_gitlab_assignees.merge_request_id`), - dal.Where(`mr.project_id = ? - and mr.connection_id = ?`, - projectId, data.Options.ConnectionId), - dal.Orderby("_tool_gitlab_assignees.merge_request_id ASC"), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() - mrIdGen := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) accountIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabAssignee{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - mrAssignee := inputRow.(*models.GitlabAssignee) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabAssignee]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(&models.GitlabAssignee{}), + dal.Where(`project_id = ? and connection_id = ?`, projectId, data.Options.ConnectionId), + dal.Orderby("merge_request_id ASC"), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(mrAssignee *models.GitlabAssignee) ([]interface{}, errors.Error) { domainPrAssigne := &code.PullRequestAssignee{ PullRequestId: mrIdGen.Generate(data.Options.ConnectionId, mrAssignee.MergeRequestId), AssigneeId: accountIdGen.Generate(data.Options.ConnectionId, mrAssignee.AssigneeId), diff --git a/backend/plugins/gitlab/tasks/mr_commit_convertor.go b/backend/plugins/gitlab/tasks/mr_commit_convertor.go index 74ae0d926bb..6f7ff2a5f8e 100644 --- a/backend/plugins/gitlab/tasks/mr_commit_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_commit_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -39,45 +37,39 @@ var ConvertApiMrCommitsMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Add domain layer PullRequestCommit according to GitlabMrCommit", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ConvertMrCommentMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta}, } -func ConvertApiMergeRequestsCommits(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_COMMITS_TABLE) - db := taskCtx.GetDal() - - clauses := []dal.Clause{ - dal.From(&models.GitlabMrCommit{}), - dal.Join(`left join _tool_gitlab_merge_requests - on _tool_gitlab_merge_requests.gitlab_id = - _tool_gitlab_mr_commits.merge_request_id`), - dal.Where(`_tool_gitlab_merge_requests.project_id = ? - and _tool_gitlab_merge_requests.connection_id = ?`, - data.Options.ProjectId, data.Options.ConnectionId), - dal.Orderby("merge_request_id ASC"), - } +func ConvertApiMergeRequestsCommits(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_COMMITS_TABLE) + db := subtaskCtx.GetDal() - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - - // TODO: adopt batch indate operation domainIdGenerator := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabMrCommit{}), - Input: cursor, - - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - GitlabMrCommit := inputRow.(*models.GitlabMrCommit) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabMrCommit]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.Select("c.*"), + dal.From("_tool_gitlab_mr_commits c"), + dal.Join(`LEFT JOIN _tool_gitlab_merge_requests mr ON mr.gitlab_id = c.merge_request_id AND c.connection_id = mr.connection_id`), + dal.Where(`mr.project_id = ? and mr.connection_id = ?`, data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("c.updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(mrCommit *models.GitlabMrCommit) ([]interface{}, errors.Error) { domainPrcommit := &code.PullRequestCommit{ - CommitSha: GitlabMrCommit.CommitSha, - PullRequestId: domainIdGenerator.Generate(data.Options.ConnectionId, GitlabMrCommit.MergeRequestId), - CommitAuthorName: GitlabMrCommit.CommitAuthorName, - CommitAuthorEmail: GitlabMrCommit.CommitAuthorEmail, - CommitAuthoredDate: *GitlabMrCommit.CommitAuthoredDate, + CommitSha: mrCommit.CommitSha, + PullRequestId: domainIdGenerator.Generate(data.Options.ConnectionId, mrCommit.MergeRequestId), + CommitAuthorName: mrCommit.CommitAuthorName, + CommitAuthorEmail: mrCommit.CommitAuthorEmail, + CommitAuthoredDate: *mrCommit.CommitAuthoredDate, } return []interface{}{ domainPrcommit, diff --git a/backend/plugins/gitlab/tasks/mr_commit_extractor.go b/backend/plugins/gitlab/tasks/mr_commit_extractor.go index 5c73c8665bc..7a94f9fee55 100644 --- a/backend/plugins/gitlab/tasks/mr_commit_extractor.go +++ b/backend/plugins/gitlab/tasks/mr_commit_extractor.go @@ -40,18 +40,33 @@ var ExtractApiMrCommitsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiMrCommitsMeta}, } -func ExtractApiMergeRequestsCommits(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_COMMITS_TABLE) +type GitlabApiCommit struct { + GitlabId string `json:"id"` + Title string + Message string + ProjectId int + ShortId string `json:"short_id"` + AuthorName string `json:"author_name"` + AuthorEmail string `json:"author_email"` + AuthoredDate common.Iso8601Time `json:"authored_date"` + CommitterName string `json:"committer_name"` + CommitterEmail string `json:"committer_email"` + CommittedDate common.Iso8601Time `json:"committed_date"` + WebUrl string `json:"web_url"` + Stats struct { + Additions int + Deletions int + Total int + } +} + +func ExtractApiMergeRequestsCommits(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_COMMITS_TABLE) - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[GitlabApiCommit]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiCommit *GitlabApiCommit, row *api.RawData) ([]interface{}, errors.Error) { // create gitlab commit - gitlabApiCommit := &GitlabApiCommit{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiCommit)) - if err != nil { - return nil, err - } gitlabCommit, err := ConvertCommit(gitlabApiCommit) if err != nil { return nil, err @@ -91,3 +106,24 @@ func ExtractApiMergeRequestsCommits(taskCtx plugin.SubTaskContext) errors.Error return extractor.Execute() } + +// Convert the API response to our DB model instance +func ConvertCommit(commit *GitlabApiCommit) (*models.GitlabCommit, errors.Error) { + gitlabCommit := &models.GitlabCommit{ + Sha: commit.GitlabId, + Title: commit.Title, + Message: commit.Message, + ShortId: commit.ShortId, + AuthorName: commit.AuthorName, + AuthorEmail: commit.AuthorEmail, + AuthoredDate: commit.AuthoredDate.ToTime(), + CommitterName: commit.CommitterName, + CommitterEmail: commit.CommitterEmail, + CommittedDate: commit.CommittedDate.ToTime(), + WebUrl: commit.WebUrl, + Additions: commit.Stats.Additions, + Deletions: commit.Stats.Deletions, + Total: commit.Stats.Total, + } + return gitlabCommit, nil +} diff --git a/backend/plugins/gitlab/tasks/mr_convertor.go b/backend/plugins/gitlab/tasks/mr_convertor.go index 478276c71f4..f2dd24d74a8 100644 --- a/backend/plugins/gitlab/tasks/mr_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_convertor.go @@ -18,15 +18,13 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -43,32 +41,43 @@ var ConvertApiMergeRequestsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&ConvertProjectMeta}, } -func ConvertApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) - db := taskCtx.GetDal() - clauses := []dal.Clause{ - dal.From(&models.GitlabMergeRequest{}), - dal.Where("project_id=? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertApiMergeRequests(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_TABLE) + db := subtaskCtx.GetDal() domainMrIdGenerator := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) domainRepoIdGenerator := didgen.NewDomainIdGenerator(&models.GitlabProject{}) domainUserIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabMergeRequest{}), - Input: cursor, - - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabMr := inputRow.(*models.GitlabMergeRequest) - + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabMergeRequest]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(&models.GitlabMergeRequest{}), + dal.Where("project_id=? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + BeforeConvert: func(gitlabMr *models.GitlabMergeRequest, stateManager *api.SubtaskStateManager) errors.Error { + mrId := domainMrIdGenerator.Generate(data.Options.ConnectionId, gitlabMr.GitlabId) + if err := db.Delete(&code.PullRequestAssignee{}, dal.Where("pull_request_id = ?", mrId)); err != nil { + return err + } + if err := db.Delete(&code.PullRequestReviewer{}, dal.Where("pull_request_id = ?", mrId)); err != nil { + return err + } + if err := db.Delete(&code.PullRequestLabel{}, dal.Where("pull_request_id = ?", mrId)); err != nil { + return err + } + return nil + }, + Convert: func(gitlabMr *models.GitlabMergeRequest) ([]interface{}, errors.Error) { domainPr := &code.PullRequest{ DomainEntity: domainlayer.DomainEntity{ Id: domainMrIdGenerator.Generate(data.Options.ConnectionId, gitlabMr.GitlabId), diff --git a/backend/plugins/gitlab/tasks/mr_detail_extractor.go b/backend/plugins/gitlab/tasks/mr_detail_extractor.go index 3dbc72e8af7..3945752467a 100644 --- a/backend/plugins/gitlab/tasks/mr_detail_extractor.go +++ b/backend/plugins/gitlab/tasks/mr_detail_extractor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" "regexp" "github.com/apache/incubator-devlake/core/errors" @@ -37,11 +36,12 @@ var ExtractApiMergeRequestDetailsMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Extract raw merge request Details data into tool layer table GitlabMergeRequest and GitlabReviewer", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ExtractApiCommitsMeta}, + Dependencies: []*plugin.SubTaskMeta{&CollectApiMergeRequestDetailsMeta}, } -func ExtractApiMergeRequestDetails(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_DETAIL_TABLE) +func ExtractApiMergeRequestDetails(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_DETAIL_TABLE) + db := subtaskCtx.GetDal() config := data.Options.ScopeConfig var labelTypeRegex *regexp.Regexp var labelComponentRegex *regexp.Regexp @@ -60,15 +60,14 @@ func ExtractApiMergeRequestDetails(taskCtx plugin.SubTaskContext) errors.Error { return errors.Default.Wrap(err, "regexp Compile prComponent failed") } } - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - mr := &MergeRequestRes{} - err := errors.Convert(json.Unmarshal(row.Data, mr)) - if err != nil { - return nil, err - } - + subtaskCommonArgs.SubtaskConfig = map[string]string{ + "prType": prType, + "prComponent": prComponent, + } + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[MergeRequestRes]{ + SubtaskCommonArgs: subtaskCommonArgs, + BeforeExtract: beforeExtractMr(db, data), + Extract: func(mr *MergeRequestRes, row *api.RawData) ([]interface{}, errors.Error) { gitlabMergeRequest, err := convertMergeRequest(mr) if err != nil { return nil, err diff --git a/backend/plugins/gitlab/tasks/mr_enricher.go b/backend/plugins/gitlab/tasks/mr_enricher.go deleted file mode 100644 index 327765208bc..00000000000 --- a/backend/plugins/gitlab/tasks/mr_enricher.go +++ /dev/null @@ -1,165 +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" - "time" - - "github.com/apache/incubator-devlake/core/dal" - "github.com/apache/incubator-devlake/core/errors" - "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" - "github.com/apache/incubator-devlake/plugins/gitlab/models" -) - -func init() { - RegisterSubtaskMeta(&EnrichMergeRequestsMeta) -} - -var EnrichMergeRequestsMeta = plugin.SubTaskMeta{ - Name: "Enrich Merge Requests", - EntryPoint: EnrichMergeRequests, - EnabledByDefault: true, - Description: "Enrich merge requests data from GitlabCommit, GitlabMrNote and GitlabMergeRequest", - DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ExtractApiJobsMeta}, -} - -func EnrichMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) - - db := taskCtx.GetDal() - clauses := []dal.Clause{ - dal.From(&models.GitlabMergeRequest{}), - dal.Where("project_id=? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } // get mrs from theDB - defer cursor.Close() - - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabMergeRequest{}), - Input: cursor, - - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabMr := inputRow.(*models.GitlabMergeRequest) - // enrich first_comment_time field - notes := make([]models.GitlabMrNote, 0) - // `system` = 0 is needed since we only care about human comments - noteClauses := []dal.Clause{ - dal.From(&models.GitlabMrNote{}), - dal.Where("merge_request_id = ? AND is_system = ? AND connection_id = ? ", - gitlabMr.GitlabId, false, data.Options.ConnectionId), - dal.Orderby("gitlab_created_at asc"), - } - err = db.All(¬es, noteClauses...) - if err != nil { - return nil, err - } - - commits := make([]models.GitlabCommit, 0) - commitClauses := []dal.Clause{ - dal.From(&models.GitlabCommit{}), - dal.Join(`join _tool_gitlab_mr_commits gmrc - on gmrc.commit_sha = _tool_gitlab_commits.sha`), - dal.Where("merge_request_id = ? AND gmrc.connection_id = ?", - gitlabMr.GitlabId, data.Options.ConnectionId), - dal.Orderby("authored_date asc"), - } - err = db.All(&commits, commitClauses...) - if err != nil { - return nil, err - } - - // calculate reviewRounds from commits and notes - reviewRounds := getReviewRounds(commits, notes) - gitlabMr.ReviewRounds = reviewRounds - - if len(notes) > 0 { - earliestNote, err := findEarliestNote(notes) - if err != nil { - return nil, err - } - if earliestNote != nil { - gitlabMr.FirstCommentTime = &earliestNote.GitlabCreatedAt - } - } - return []interface{}{ - gitlabMr, - }, nil - }, - }) - if err != nil { - return err - } - - return converter.Execute() -} - -func findEarliestNote(notes []models.GitlabMrNote) (*models.GitlabMrNote, errors.Error) { - var earliestNote *models.GitlabMrNote - earliestTime := time.Now() - for i := range notes { - if !notes[i].Resolvable { - continue - } - noteTime := notes[i].GitlabCreatedAt - if noteTime.Before(earliestTime) { - earliestTime = noteTime - earliestNote = ¬es[i] - } - } - return earliestNote, nil -} - -func getReviewRounds(commits []models.GitlabCommit, notes []models.GitlabMrNote) int { - i := 0 - j := 0 - reviewRounds := 0 - if len(commits) == 0 && len(notes) == 0 { - return 1 - } - // state is used to keep track of previous activity - // 0: init, 1: commit, 2: comment - // whenever state is switched to comment, we increment reviewRounds by 1 - state := 0 // 0, 1, 2 - for i < len(commits) && j < len(notes) { - if commits[i].AuthoredDate.Before(notes[j].GitlabCreatedAt) { - i++ - state = 1 - } else { - j++ - if state != 2 { - reviewRounds++ - } - state = 2 - } - } - // There's another implicit round of review in 2 scenarios - // One: the last state is commit (state == 1) - // Two: the last state is comment but there're still commits left - if state == 1 || i < len(commits) { - reviewRounds++ - } - return reviewRounds -} diff --git a/backend/plugins/gitlab/tasks/mr_enricher_test.go b/backend/plugins/gitlab/tasks/mr_enricher_test.go deleted file mode 100644 index f22fd275af4..00000000000 --- a/backend/plugins/gitlab/tasks/mr_enricher_test.go +++ /dev/null @@ -1,112 +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 ( - "github.com/apache/incubator-devlake/plugins/gitlab/models" - "github.com/stretchr/testify/assert" - "testing" - "time" -) - -func TestFindEarliestNote(t *testing.T) { - baseTime, err := time.Parse(time.RFC3339, "2022-01-02T15:04:05Z") - assert.Nil(t, err) - // Create some sample notes - note1 := models.GitlabMrNote{Resolvable: true, GitlabCreatedAt: baseTime.Add(-time.Hour)} - note2 := models.GitlabMrNote{Resolvable: false, GitlabCreatedAt: baseTime.Add(-time.Minute)} - note3 := models.GitlabMrNote{Resolvable: true, GitlabCreatedAt: baseTime.Add(-time.Second)} - - // Call the function with the sample notes - notes := []models.GitlabMrNote{note1, note2, note3} - earliestNote, err := findEarliestNote(notes) - - // Check that no error was returned - if err != nil { - t.Errorf("findEarliestNote returned an error: %v", err) - } - - // Check that the correct note was returned - if earliestNote == nil { - t.Errorf("findEarliestNote returned nil, expected a note") - } - if !assert.Equal(t, note1, *earliestNote) { - t.Errorf("findEarliestNote returned the wrong note: got %v, expected %v", earliestNote, ¬e1) - } - - // Modify one of the notes to make it unresolvable - notes[0].Resolvable = false - - // Call the function again with the modified notes - earliestNote, err = findEarliestNote(notes) - - // Check that no error was returned - if err != nil { - t.Errorf("findEarliestNote returned an error: %v", err) - } - - // Check that the correct note was returned - if earliestNote == nil { - t.Errorf("findEarliestNote returned nil, expected a note") - } - if !assert.Equal(t, note3, *earliestNote) { - t.Errorf("findEarliestNote returned the wrong note: got %v, expected %v", earliestNote, ¬e3) - } -} - -func TestGetReviewRounds(t *testing.T) { - baseTime, err := time.Parse(time.RFC3339, "2022-01-02T15:04:05Z") - assert.Nil(t, err) - // Test case 1: empty input - var commits []models.GitlabCommit - var notes []models.GitlabMrNote - expected := 1 - if got := getReviewRounds(commits, notes); got != expected { - t.Errorf("getReviewRounds(%v, %v) = %d, expected %d", commits, notes, got, expected) - } - - // Test case 2: single comment - commits = []models.GitlabCommit{ - {AuthoredDate: baseTime.Add(-time.Hour * 2)}, - {AuthoredDate: baseTime.Add(-time.Hour)}, - } - notes = []models.GitlabMrNote{ - {GitlabCreatedAt: baseTime}, - } - expected = 1 - if got := getReviewRounds(commits, notes); got != expected { - t.Errorf("getReviewRounds(%v, %v) = %d, expected %d", commits, notes, got, expected) - } - - // Test case 3: multiple comments - commits = []models.GitlabCommit{ - {AuthoredDate: baseTime.Add(-time.Hour * 15)}, - {AuthoredDate: baseTime.Add(-time.Hour * 9)}, - {AuthoredDate: baseTime.Add(-time.Hour * 3)}, - {AuthoredDate: baseTime}, - } - notes = []models.GitlabMrNote{ - {GitlabCreatedAt: baseTime.Add(-time.Hour * 14)}, - {GitlabCreatedAt: baseTime.Add(-time.Hour * 7)}, - {GitlabCreatedAt: baseTime.Add(-time.Hour * 2)}, - } - expected = 4 - if got := getReviewRounds(commits, notes); got != expected { - t.Errorf("getReviewRounds(%v, %v) = %d, expected %d", commits, notes, got, expected) - } -} diff --git a/backend/plugins/gitlab/tasks/mr_extractor.go b/backend/plugins/gitlab/tasks/mr_extractor.go index 76253833bc0..3a8457b0cf0 100644 --- a/backend/plugins/gitlab/tasks/mr_extractor.go +++ b/backend/plugins/gitlab/tasks/mr_extractor.go @@ -18,10 +18,10 @@ limitations under the License. package tasks import ( - "encoding/json" "regexp" "strings" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -96,8 +96,10 @@ var ExtractApiMergeRequestsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiMergeRequestsMeta}, } -func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) +func ExtractApiMergeRequests(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_TABLE) + + db := subtaskCtx.GetDal() config := data.Options.ScopeConfig var labelTypeRegex *regexp.Regexp var labelComponentRegex *regexp.Regexp @@ -118,17 +120,15 @@ func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { } } - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - - mr := &MergeRequestRes{} - s := string(row.Data) - err := errors.Convert(json.Unmarshal(row.Data, mr)) - if err != nil { - return nil, err - } + subtaskCommonArgs.SubtaskConfig = map[string]any{ + "prType": prType, + "prComponent": prComponent, + } + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[MergeRequestRes]{ + SubtaskCommonArgs: subtaskCommonArgs, + BeforeExtract: beforeExtractMr(db, data), + Extract: func(mr *MergeRequestRes, row *api.RawData) ([]interface{}, errors.Error) { gitlabMergeRequest, err := convertMergeRequest(mr) if err != nil { return nil, err @@ -136,15 +136,23 @@ func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { // if we can not find merged_at and closed_at info in the detail // we need get detail for gitlab v11 + s := string(row.Data) if !strings.Contains(s, "\"merged_at\":") { if !strings.Contains(s, "\"closed_at\":") { gitlabMergeRequest.IsDetailRequired = true } } - results := make([]interface{}, 0, len(mr.Reviewers)+1) + results := make([]interface{}, 0, len(mr.Reviewers)+len(mr.Labels)+1) gitlabMergeRequest.ConnectionId = data.Options.ConnectionId results = append(results, gitlabMergeRequest) + err = db.Delete( + &models.GitlabMrLabel{}, + dal.Where("connection_id = ? AND mr_id = ?", data.Options.ConnectionId, gitlabMergeRequest.GitlabId), + ) + if err != nil { + return nil, err + } for _, label := range mr.Labels { results = append(results, &models.GitlabMrLabel{ MrId: gitlabMergeRequest.GitlabId, @@ -160,6 +168,13 @@ func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { gitlabMergeRequest.Component = label } } + err = db.Delete( + &models.GitlabReviewer{}, + dal.Where("connection_id = ? AND merge_request_id = ?", data.Options.ConnectionId, gitlabMergeRequest.GitlabId), + ) + if err != nil { + return nil, err + } for _, reviewer := range mr.Reviewers { gitlabReviewer := &models.GitlabReviewer{ ConnectionId: data.Options.ConnectionId, @@ -174,6 +189,13 @@ func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { } results = append(results, gitlabReviewer) } + err = db.Delete( + &models.GitlabAssignee{}, + dal.Where("connection_id = ? AND merge_request_id = ?", data.Options.ConnectionId, gitlabMergeRequest.GitlabId), + ) + if err != nil { + return nil, err + } for _, assignee := range mr.Assignees { gitlabAssignee := &models.GitlabAssignee{ ConnectionId: data.Options.ConnectionId, @@ -188,17 +210,13 @@ func ExtractApiMergeRequests(taskCtx plugin.SubTaskContext) errors.Error { } results = append(results, gitlabAssignee) } - return results, nil }, }) - if err != nil { - return errors.Convert(err) + return err } - return extractor.Execute() - } func convertMergeRequest(mr *MergeRequestRes) (*models.GitlabMergeRequest, errors.Error) { @@ -230,3 +248,25 @@ func convertMergeRequest(mr *MergeRequestRes) (*models.GitlabMergeRequest, error } return gitlabMergeRequest, nil } + +func beforeExtractMr(db dal.Dal, data *GitlabTaskData) func(mr *MergeRequestRes, stateManager *api.SubtaskStateManager) errors.Error { + return func(mr *MergeRequestRes, stateManager *api.SubtaskStateManager) errors.Error { + if stateManager.IsIncremental() { + err := db.Delete( + &models.GitlabMrLabel{}, + dal.Where("connection_id = ? AND mr_id = ?", data.Options.ConnectionId, mr.GitlabId), + ) + if err != nil { + return err + } + err = db.Delete( + &models.GitlabAssignee{}, + dal.Where("connection_id = ? AND merge_request_id = ?", data.Options.ConnectionId, mr.GitlabId), + ) + if err != nil { + return err + } + } + return nil + } +} diff --git a/backend/plugins/gitlab/tasks/mr_label_convertor.go b/backend/plugins/gitlab/tasks/mr_label_convertor.go index 934085e8163..b5f29a1a84f 100644 --- a/backend/plugins/gitlab/tasks/mr_label_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_label_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -39,38 +37,33 @@ var ConvertMrLabelsMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Convert tool layer table gitlab_mr_labels into domain layer table pull_request_labels", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ConvertIssueLabelsMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta}, } -func ConvertMrLabels(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) - projectId := data.Options.ProjectId - clauses := []dal.Clause{ - dal.Select("*"), - dal.From(&models.GitlabMrLabel{}), - dal.Join(`left join _tool_gitlab_merge_requests on - _tool_gitlab_merge_requests.gitlab_id = _tool_gitlab_mr_labels.mr_id`), - dal.Where(`_tool_gitlab_merge_requests.project_id = ? - and _tool_gitlab_merge_requests.connection_id = ?`, - projectId, data.Options.ConnectionId), - dal.Orderby("mr_id ASC"), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertMrLabels(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_TABLE) + db := subtaskCtx.GetDal() mrIdGen := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabMrLabel{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - mrLabel := inputRow.(*models.GitlabMrLabel) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabMrLabel]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.Select("c.*"), + dal.From("_tool_gitlab_mr_labels c"), + dal.Join(`LEFT JOIN _tool_gitlab_merge_requests mr ON mr.gitlab_id = c.mr_id AND c.connection_id = mr.connection_id`), + dal.Where(`mr.project_id = ? and mr.connection_id = ?`, data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("c.updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(mrLabel *models.GitlabMrLabel) ([]interface{}, errors.Error) { domainIssueLabel := &code.PullRequestLabel{ PullRequestId: mrIdGen.Generate(data.Options.ConnectionId, mrLabel.MrId), LabelName: mrLabel.LabelName, diff --git a/backend/plugins/gitlab/tasks/mr_comment_convertor.go b/backend/plugins/gitlab/tasks/mr_note_convertor.go similarity index 70% rename from backend/plugins/gitlab/tasks/mr_comment_convertor.go rename to backend/plugins/gitlab/tasks/mr_note_convertor.go index 3b6d1cceef0..a55cc567310 100644 --- a/backend/plugins/gitlab/tasks/mr_comment_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_note_convertor.go @@ -18,15 +18,13 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -36,44 +34,39 @@ func init() { var ConvertMrCommentMeta = plugin.SubTaskMeta{ Name: "Convert MR Comments", - EntryPoint: ConvertMergeRequestComment, + EntryPoint: ConvertMergeRequestNote, EnabledByDefault: true, Description: "Add domain layer Comment according to GitlabMrComment", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta, &ExtractApiMrNotesMeta}, } -func ConvertMergeRequestComment(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_NOTES_TABLE) - db := taskCtx.GetDal() - clauses := []dal.Clause{ - dal.From(&models.GitlabMrComment{}), - dal.Join(`left join _tool_gitlab_merge_requests on - _tool_gitlab_merge_requests.gitlab_id = - _tool_gitlab_mr_comments.merge_request_id`), - dal.Where(`_tool_gitlab_merge_requests.project_id = ? - and _tool_gitlab_mr_comments.connection_id = ?`, - data.Options.ProjectId, data.Options.ConnectionId), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertMergeRequestNote(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_NOTES_TABLE) + db := subtaskCtx.GetDal() domainIdGeneratorComment := didgen.NewDomainIdGenerator(&models.GitlabMrComment{}) prIdGen := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) accountIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabMrComment{}), - Input: cursor, - - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabComments := inputRow.(*models.GitlabMrComment) - + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabMrComment]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.Select("c.*"), + dal.From("_tool_gitlab_mr_comments c"), + dal.Join(`LEFT JOIN _tool_gitlab_merge_requests mr ON mr.gitlab_id = c.merge_request_id AND c.connection_id = mr.connection_id`), + dal.Where(`mr.project_id = ? and mr.connection_id = ?`, data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("c.updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(gitlabComments *models.GitlabMrComment) ([]interface{}, errors.Error) { domainComment := &code.PullRequestComment{ DomainEntity: domainlayer.DomainEntity{ Id: domainIdGeneratorComment.Generate(data.Options.ConnectionId, gitlabComments.GitlabId), diff --git a/backend/plugins/gitlab/tasks/mr_note_extractor.go b/backend/plugins/gitlab/tasks/mr_note_extractor.go index a27d1141ce7..725a2fe484d 100644 --- a/backend/plugins/gitlab/tasks/mr_note_extractor.go +++ b/backend/plugins/gitlab/tasks/mr_note_extractor.go @@ -18,8 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" - "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -57,18 +55,12 @@ var ExtractApiMrNotesMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiMrNotesMeta}, } -func ExtractApiMergeRequestsNotes(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_NOTES_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - mrNote := &MergeRequestNote{} - err := errors.Convert(json.Unmarshal(row.Data, mrNote)) - if err != nil { - return nil, err - } +func ExtractApiMergeRequestsNotes(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_NOTES_TABLE) + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[MergeRequestNote]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(mrNote *MergeRequestNote, row *api.RawData) ([]interface{}, errors.Error) { toolMrNote, err := convertMergeRequestNote(mrNote) toolMrNote.ConnectionId = data.Options.ConnectionId if err != nil { diff --git a/backend/plugins/gitlab/tasks/mr_reviewer_convertor.go b/backend/plugins/gitlab/tasks/mr_reviewer_convertor.go index b702de5733b..f9298b093f6 100644 --- a/backend/plugins/gitlab/tasks/mr_reviewer_convertor.go +++ b/backend/plugins/gitlab/tasks/mr_reviewer_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/code" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -39,39 +37,34 @@ var ConvertMrReviewersMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Convert tool layer table gitlab_reviewers into domain layer table pull_request_reviewers", DomainTypes: []string{plugin.DOMAIN_TYPE_CODE_REVIEW}, - Dependencies: []*plugin.SubTaskMeta{&ExtractApiMergeRequestDetailsMeta}, + Dependencies: []*plugin.SubTaskMeta{&ConvertApiMergeRequestsMeta}, } -func ConvertMrReviewers(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_MERGE_REQUEST_TABLE) - projectId := data.Options.ProjectId - clauses := []dal.Clause{ - dal.Select("_tool_gitlab_reviewers.*"), - dal.From(&models.GitlabReviewer{}), - dal.Join(`left join _tool_gitlab_merge_requests mr on - mr.gitlab_id = _tool_gitlab_reviewers.merge_request_id`), - dal.Where(`mr.project_id = ? - and mr.connection_id = ?`, - projectId, data.Options.ConnectionId), - dal.Orderby("_tool_gitlab_reviewers.merge_request_id ASC"), - } - - cursor, err := db.Cursor(clauses...) - if err != nil { - return err - } - defer cursor.Close() +func ConvertMrReviewers(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_MERGE_REQUEST_TABLE) + db := subtaskCtx.GetDal() mrIdGen := didgen.NewDomainIdGenerator(&models.GitlabMergeRequest{}) accountIdGen := didgen.NewDomainIdGenerator(&models.GitlabAccount{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - InputRowType: reflect.TypeOf(models.GitlabReviewer{}), - Input: cursor, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - mrReviewer := inputRow.(*models.GitlabReviewer) + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabReviewer]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.Select("c.*"), + dal.From("_tool_gitlab_reviewers c"), + dal.Join(`LEFT JOIN _tool_gitlab_merge_requests mr ON mr.gitlab_id = c.merge_request_id AND c.connection_id = mr.connection_id`), + dal.Where(`mr.project_id = ? and mr.connection_id = ?`, data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("c.updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) + }, + Convert: func(mrReviewer *models.GitlabReviewer) ([]interface{}, errors.Error) { domainPrReviewer := &code.PullRequestReviewer{ PullRequestId: mrIdGen.Generate(data.Options.ConnectionId, mrReviewer.MergeRequestId), ReviewerId: accountIdGen.Generate(data.Options.ConnectionId, mrReviewer.ReviewerId), diff --git a/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go b/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go index 4984270d9de..2064cc6c921 100644 --- a/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go +++ b/backend/plugins/gitlab/tasks/pipeline_commit_convertor.go @@ -18,14 +18,12 @@ limitations under the License. package tasks import ( - "reflect" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/devops" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -42,9 +40,9 @@ var ConvertPipelineCommitMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&ConvertDetailPipelineMeta}, } -func ConvertPipelineCommits(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - data := taskCtx.GetData().(*GitlabTaskData) +func ConvertPipelineCommits(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_PIPELINE_TABLE) + db := subtaskCtx.GetDal() repo := &models.GitlabProject{} err := db.First(repo, dal.Where("gitlab_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId)) @@ -52,29 +50,24 @@ func ConvertPipelineCommits(taskCtx plugin.SubTaskContext) errors.Error { return err } - cursor, err := db.Cursor(dal.From(models.GitlabPipelineProject{}), - dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId)) - if err != nil { - return err - } - defer cursor.Close() - pipelineIdGen := didgen.NewDomainIdGenerator(&models.GitlabPipeline{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - InputRowType: reflect.TypeOf(models.GitlabPipelineProject{}), - Input: cursor, - RawDataSubTaskArgs: helper.RawDataSubTaskArgs{ - Ctx: taskCtx, - Params: models.GitlabApiParams{ - ConnectionId: data.Options.ConnectionId, - ProjectId: data.Options.ProjectId, - }, - Table: RAW_PIPELINE_TABLE, + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabPipelineProject]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(models.GitlabPipelineProject{}), + dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) }, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabPipelineCommit := inputRow.(*models.GitlabPipelineProject) - + Convert: func(gitlabPipelineCommit *models.GitlabPipelineProject) ([]interface{}, errors.Error) { domainPipelineCommit := &devops.CiCDPipelineCommit{ PipelineId: pipelineIdGen.Generate(data.Options.ConnectionId, gitlabPipelineCommit.PipelineId), CommitSha: gitlabPipelineCommit.Sha, diff --git a/backend/plugins/gitlab/tasks/pipeline_detail_convertor.go b/backend/plugins/gitlab/tasks/pipeline_detail_convertor.go index aba33b0e475..e808d782236 100644 --- a/backend/plugins/gitlab/tasks/pipeline_detail_convertor.go +++ b/backend/plugins/gitlab/tasks/pipeline_detail_convertor.go @@ -18,17 +18,16 @@ limitations under the License. package tasks import ( - "reflect" "time" "github.com/apache/incubator-devlake/core/errors" + "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/models/domainlayer" "github.com/apache/incubator-devlake/core/models/domainlayer/devops" "github.com/apache/incubator-devlake/core/models/domainlayer/didgen" "github.com/apache/incubator-devlake/core/plugin" - helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/gitlab/models" ) @@ -42,37 +41,33 @@ var ConvertDetailPipelineMeta = plugin.SubTaskMeta{ EnabledByDefault: true, Description: "Convert tool layer table gitlab_detail_pipeline into domain layer table pipeline", DomainTypes: []string{plugin.DOMAIN_TYPE_CICD}, - Dependencies: []*plugin.SubTaskMeta{&ConvertCommitsMeta}, + Dependencies: []*plugin.SubTaskMeta{&ExtractApiPipelineDetailsMeta}, } -func ConvertDetailPipelines(taskCtx plugin.SubTaskContext) errors.Error { - db := taskCtx.GetDal() - data := taskCtx.GetData().(*GitlabTaskData) +func ConvertDetailPipelines(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_PIPELINE_DETAILS_TABLE) - cursor, err := db.Cursor(dal.From(models.GitlabPipeline{}), - dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId)) - if err != nil { - return err - } - defer cursor.Close() + db := subtaskCtx.GetDal() pipelineIdGen := didgen.NewDomainIdGenerator(&models.GitlabPipeline{}) projectIdGen := didgen.NewDomainIdGenerator(&models.GitlabProject{}) - converter, err := helper.NewDataConverter(helper.DataConverterArgs{ - InputRowType: reflect.TypeOf(models.GitlabPipeline{}), - Input: cursor, - RawDataSubTaskArgs: helper.RawDataSubTaskArgs{ - Ctx: taskCtx, - Params: models.GitlabApiParams{ - ConnectionId: data.Options.ConnectionId, - ProjectId: data.Options.ProjectId, - }, - Table: RAW_PIPELINE_DETAILS_TABLE, + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.GitlabPipeline]{ + SubtaskCommonArgs: subtaskCommonArgs, + Input: func(stateManager *api.SubtaskStateManager) (dal.Rows, errors.Error) { + clauses := []dal.Clause{ + dal.From(models.GitlabPipeline{}), + dal.Where("project_id = ? and connection_id = ?", data.Options.ProjectId, data.Options.ConnectionId), + } + if stateManager.IsIncremental() { + since := stateManager.GetSince() + if since != nil { + clauses = append(clauses, dal.Where("updated_at >= ? ", since)) + } + } + return db.Cursor(clauses...) }, - Convert: func(inputRow interface{}) ([]interface{}, errors.Error) { - gitlabPipeline := inputRow.(*models.GitlabPipeline) - + Convert: func(gitlabPipeline *models.GitlabPipeline) ([]interface{}, errors.Error) { createdAt := time.Now() if gitlabPipeline.GitlabCreatedAt != nil { createdAt = *gitlabPipeline.GitlabCreatedAt diff --git a/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go b/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go index 34692dc54df..3e7c14aef0a 100644 --- a/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go +++ b/backend/plugins/gitlab/tasks/pipeline_detail_extractor.go @@ -18,8 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" - "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/models/domainlayer/devops" @@ -41,18 +39,12 @@ var ExtractApiPipelineDetailsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiPipelineDetailsMeta}, } -func ExtractApiPipelineDetails(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PIPELINE_DETAILS_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - gitlabApiPipeline := &ApiPipeline{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiPipeline)) - if err != nil { - return nil, err - } +func ExtractApiPipelineDetails(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_PIPELINE_DETAILS_TABLE) + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[ApiPipeline]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiPipeline *ApiPipeline, row *api.RawData) ([]interface{}, errors.Error) { gitlabPipeline := &models.GitlabPipeline{ GitlabId: gitlabApiPipeline.Id, ProjectId: data.Options.ProjectId, diff --git a/backend/plugins/gitlab/tasks/pipeline_extractor.go b/backend/plugins/gitlab/tasks/pipeline_extractor.go index d68035db169..0eb2450a514 100644 --- a/backend/plugins/gitlab/tasks/pipeline_extractor.go +++ b/backend/plugins/gitlab/tasks/pipeline_extractor.go @@ -18,8 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" - "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/common" "github.com/apache/incubator-devlake/core/plugin" @@ -69,17 +67,12 @@ var ExtractApiPipelinesMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiPipelinesMeta}, } -func ExtractApiPipelines(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_PIPELINE_TABLE) +func ExtractApiPipelines(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_PIPELINE_TABLE) - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - gitlabApiPipeline := &ApiPipeline{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiPipeline)) - if err != nil { - return nil, err - } + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[ApiPipeline]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiPipeline *ApiPipeline, row *api.RawData) ([]interface{}, errors.Error) { pipelineProject := convertApiPipelineToGitlabPipelineProject(gitlabApiPipeline, data.Options.ConnectionId, data.Options.ProjectId) return []interface{}{pipelineProject}, nil }, diff --git a/backend/plugins/gitlab/tasks/shared.go b/backend/plugins/gitlab/tasks/shared.go index 4051c93b57b..59ce8b921ef 100644 --- a/backend/plugins/gitlab/tasks/shared.go +++ b/backend/plugins/gitlab/tasks/shared.go @@ -155,10 +155,10 @@ func GetQuery(reqData *helper.RequestData) (url.Values, errors.Error) { return query, nil } -func CreateRawDataSubTaskArgs(taskCtx plugin.SubTaskContext, Table string) (*helper.RawDataSubTaskArgs, *GitlabTaskData) { - data := taskCtx.GetData().(*GitlabTaskData) +func CreateRawDataSubTaskArgs(subtaskCtx plugin.SubTaskContext, Table string) (*helper.RawDataSubTaskArgs, *GitlabTaskData) { + data := subtaskCtx.GetData().(*GitlabTaskData) rawDataSubTaskArgs := &helper.RawDataSubTaskArgs{ - Ctx: taskCtx, + Ctx: subtaskCtx, Params: models.GitlabApiParams{ ProjectId: data.Options.ProjectId, ConnectionId: data.Options.ConnectionId, @@ -168,15 +168,29 @@ func CreateRawDataSubTaskArgs(taskCtx plugin.SubTaskContext, Table string) (*hel return rawDataSubTaskArgs, data } +func CreateSubtaskCommonArgs(subtaskCtx plugin.SubTaskContext, table string) (*helper.SubtaskCommonArgs, *GitlabTaskData) { + data := subtaskCtx.GetData().(*GitlabTaskData) + args := &helper.SubtaskCommonArgs{ + SubTaskContext: subtaskCtx, + Table: table, + Params: models.GitlabApiParams{ + ConnectionId: data.Options.ConnectionId, + ProjectId: data.Options.ProjectId, + }, + } + return args, data +} + func GetMergeRequestsIterator(taskCtx plugin.SubTaskContext, apiCollector *helper.StatefulApiCollector) (*helper.DalCursorIterator, errors.Error) { db := taskCtx.GetDal() data := taskCtx.GetData().(*GitlabTaskData) clauses := []dal.Clause{ dal.Select("gmr.gitlab_id, gmr.iid"), dal.From("_tool_gitlab_merge_requests gmr"), + // collect only openning merge request's notes and commits to speed up the process dal.Where( - `gmr.project_id = ? and gmr.connection_id = ?`, - data.Options.ProjectId, data.Options.ConnectionId, + `gmr.project_id = ? and gmr.connection_id = ? AND state = ?`, + data.Options.ProjectId, data.Options.ConnectionId, "opened", ), } if apiCollector != nil { diff --git a/backend/plugins/gitlab/tasks/trigger_job_extractor.go b/backend/plugins/gitlab/tasks/trigger_job_extractor.go index f515b7b852e..8a1e7eaeb00 100644 --- a/backend/plugins/gitlab/tasks/trigger_job_extractor.go +++ b/backend/plugins/gitlab/tasks/trigger_job_extractor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" "time" "github.com/apache/incubator-devlake/core/errors" @@ -55,18 +54,12 @@ var ExtractApiTriggerJobsMeta = plugin.SubTaskMeta{ Dependencies: []*plugin.SubTaskMeta{&CollectApiTriggerJobsMeta}, } -func ExtractApiTriggerJobs(taskCtx plugin.SubTaskContext) errors.Error { - rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, RAW_TRIGGER_JOB_TABLE) - - extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{ - RawDataSubTaskArgs: *rawDataSubTaskArgs, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - gitlabApiTriggerJob := &ApiTriggerJob{} - err := errors.Convert(json.Unmarshal(row.Data, gitlabApiTriggerJob)) - if err != nil { - return nil, err - } +func ExtractApiTriggerJobs(subtaskCtx plugin.SubTaskContext) errors.Error { + subtaskCommonArgs, data := CreateSubtaskCommonArgs(subtaskCtx, RAW_TRIGGER_JOB_TABLE) + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[ApiTriggerJob]{ + SubtaskCommonArgs: subtaskCommonArgs, + Extract: func(gitlabApiTriggerJob *ApiTriggerJob, row *api.RawData) ([]interface{}, errors.Error) { gitlabPipeline, err := convertTriggerJob(gitlabApiTriggerJob, data.Options.ProjectId) if err != nil { return nil, err diff --git a/backend/plugins/jira/tasks/epic_extractor.go b/backend/plugins/jira/tasks/epic_extractor.go index cf1e7f28b89..89f2ef70cc6 100644 --- a/backend/plugins/jira/tasks/epic_extractor.go +++ b/backend/plugins/jira/tasks/epic_extractor.go @@ -18,12 +18,15 @@ limitations under the License. package tasks import ( + "encoding/json" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/log" "github.com/apache/incubator-devlake/core/plugin" "github.com/apache/incubator-devlake/helpers/pluginhelper/api" "github.com/apache/incubator-devlake/plugins/jira/models" + "github.com/apache/incubator-devlake/plugins/jira/tasks/apiv2models" ) var _ plugin.SubTaskEntryPoint = ExtractEpics @@ -61,7 +64,12 @@ func ExtractEpics(taskCtx plugin.SubTaskContext) errors.Error { Table: RAW_EPIC_TABLE, }, Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - return extractIssues(data, mappings, row, userFieldMap) + apiIssue := &apiv2models.Issue{} + err = errors.Convert(json.Unmarshal(row.Data, apiIssue)) + if err != nil { + return nil, err + } + return extractIssues(data, mappings, apiIssue, row, userFieldMap) }, }) if err != nil { diff --git a/backend/plugins/jira/tasks/issue_changelog_convertor.go b/backend/plugins/jira/tasks/issue_changelog_convertor.go index 4dc35e5c987..b27fc966681 100644 --- a/backend/plugins/jira/tasks/issue_changelog_convertor.go +++ b/backend/plugins/jira/tasks/issue_changelog_convertor.go @@ -78,7 +78,7 @@ func ConvertIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error { changelogIdGenerator := didgen.NewDomainIdGenerator(&models.JiraIssueChangelogItems{}) accountIdGen := didgen.NewDomainIdGenerator(&models.JiraAccount{}) - converter, err := api.NewStatefulDataConverter[IssueChangelogItemResult](&api.StatefulDataConverterArgs[IssueChangelogItemResult]{ + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[IssueChangelogItemResult]{ SubtaskCommonArgs: &api.SubtaskCommonArgs{ SubTaskContext: subtaskCtx, Table: RAW_ISSUE_TABLE, diff --git a/backend/plugins/jira/tasks/issue_changelog_extractor.go b/backend/plugins/jira/tasks/issue_changelog_extractor.go index 0cd9d4f65f7..762a12d1106 100644 --- a/backend/plugins/jira/tasks/issue_changelog_extractor.go +++ b/backend/plugins/jira/tasks/issue_changelog_extractor.go @@ -51,7 +51,7 @@ func ExtractIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error { if err != nil { return err } - extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs{ + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[apiv2models.Changelog]{ SubtaskCommonArgs: &api.SubtaskCommonArgs{ SubTaskContext: subtaskCtx, Table: RAW_CHANGELOG_TABLE, @@ -60,18 +60,13 @@ func ExtractIssueChangelogs(subtaskCtx plugin.SubTaskContext) errors.Error { BoardId: data.Options.BoardId, }, }, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { + Extract: func(changelog *apiv2models.Changelog, row *api.RawData) ([]interface{}, errors.Error) { // process input var input apiv2models.Input err := errors.Convert(json.Unmarshal(row.Input, &input)) if err != nil { return nil, err } - var changelog apiv2models.Changelog - err = errors.Convert(json.Unmarshal(row.Data, &changelog)) - if err != nil { - return nil, err - } // prepare output var result []interface{} cl, user := changelog.ToToolLayer(connectionId, input.IssueId, &input.UpdateTime) diff --git a/backend/plugins/jira/tasks/issue_convertor.go b/backend/plugins/jira/tasks/issue_convertor.go index 1c7305758c1..fb213a638dd 100644 --- a/backend/plugins/jira/tasks/issue_convertor.go +++ b/backend/plugins/jira/tasks/issue_convertor.go @@ -53,7 +53,7 @@ func ConvertIssues(subtaskCtx plugin.SubTaskContext) errors.Error { boardIdGen := didgen.NewDomainIdGenerator(&models.JiraBoard{}) boardId := boardIdGen.Generate(data.Options.ConnectionId, data.Options.BoardId) - converter, err := api.NewStatefulDataConverter[models.JiraIssue](&api.StatefulDataConverterArgs[models.JiraIssue]{ + converter, err := api.NewStatefulDataConverter(&api.StatefulDataConverterArgs[models.JiraIssue]{ SubtaskCommonArgs: &api.SubtaskCommonArgs{ SubTaskContext: subtaskCtx, Table: RAW_ISSUE_TABLE, @@ -84,6 +84,17 @@ func ConvertIssues(subtaskCtx plugin.SubTaskContext) errors.Error { } return db.Cursor(clauses...) }, + // not needed for now due to jira assignee and label are converted in FullSync(Delete+Insert) manner + // BeforeConvert: func(jiraIssue *models.JiraIssue, stateManager *api.SubtaskStateManager) errors.Error { + // issueId := issueIdGen.Generate(data.Options.ConnectionId, jiraIssue.IssueId) + // if err := db.Delete(&ticket.IssueAssignee{}, dal.Where("issue_id = ?", issueId)); err != nil { + // return err + // } + // if err := db.Delete(&ticket.IssueLabel{}, dal.Where("issue_id = ?", issueId)); err != nil { + // return err + // } + // return nil + // }, Convert: func(jiraIssue *models.JiraIssue) ([]interface{}, errors.Error) { var result []interface{} issue := &ticket.Issue{ diff --git a/backend/plugins/jira/tasks/issue_extractor.go b/backend/plugins/jira/tasks/issue_extractor.go index 686f23ff4c4..11277a0a486 100644 --- a/backend/plugins/jira/tasks/issue_extractor.go +++ b/backend/plugins/jira/tasks/issue_extractor.go @@ -18,7 +18,6 @@ limitations under the License. package tasks import ( - "encoding/json" "strconv" "strings" "time" @@ -62,7 +61,7 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) errors.Error { if err != nil { return err } - extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs{ + extractor, err := api.NewStatefulApiExtractor(&api.StatefulApiExtractorArgs[apiv2models.Issue]{ SubtaskCommonArgs: &api.SubtaskCommonArgs{ SubTaskContext: subtaskCtx, Table: RAW_ISSUE_TABLE, @@ -75,8 +74,27 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) errors.Error { "storyPointField": data.Options.ScopeConfig.StoryPointField, }, }, - Extract: func(row *api.RawData) ([]interface{}, errors.Error) { - return extractIssues(data, mappings, row, userFieldMap) + BeforeExtract: func(apiIssue *apiv2models.Issue, stateManager *api.SubtaskStateManager) errors.Error { + if stateManager.IsIncremental() { + err := db.Delete( + &models.JiraIssueLabel{}, + dal.Where("connection_id = ? AND issue_id = ?", data.Options.ConnectionId, apiIssue.ID), + ) + if err != nil { + return err + } + err = db.Delete( + &models.JiraIssueRelationship{}, + dal.Where("connection_id = ? AND issue_id = ?", data.Options.ConnectionId, apiIssue.ID), + ) + if err != nil { + return err + } + } + return nil + }, + Extract: func(apiIssue *apiv2models.Issue, row *api.RawData) ([]interface{}, errors.Error) { + return extractIssues(data, mappings, apiIssue, row, userFieldMap) }, }) if err != nil { @@ -85,13 +103,8 @@ func ExtractIssues(subtaskCtx plugin.SubTaskContext) errors.Error { return extractor.Execute() } -func extractIssues(data *JiraTaskData, mappings *typeMappings, row *api.RawData, userFieldMaps map[string]struct{}) ([]interface{}, errors.Error) { - var apiIssue apiv2models.Issue - err := errors.Convert(json.Unmarshal(row.Data, &apiIssue)) - if err != nil { - return nil, err - } - err = apiIssue.SetAllFields(row.Data) +func extractIssues(data *JiraTaskData, mappings *typeMappings, apiIssue *apiv2models.Issue, row *api.RawData, userFieldMaps map[string]struct{}) ([]interface{}, errors.Error) { + err := apiIssue.SetAllFields(row.Data) if err != nil { return nil, err } diff --git a/backend/server/api/blueprints/blueprints.go b/backend/server/api/blueprints/blueprints.go index 23383d4682f..841027424cc 100644 --- a/backend/server/api/blueprints/blueprints.go +++ b/backend/server/api/blueprints/blueprints.go @@ -166,6 +166,7 @@ func Patch(c *gin.Context) { // @Accept application/json // @Param blueprintId path string true "blueprintId" // @Param skipCollectors body models.TriggerSyncPolicy false "json" +// @Param fullSync body models.TriggerSyncPolicy false "json" // @Success 200 {object} models.Pipeline // @Failure 400 {object} shared.ApiBody "Bad Request" // @Failure 500 {object} shared.ApiBody "Internal Error" diff --git a/config-ui/src/routes/blueprint/detail/status-panel.tsx b/config-ui/src/routes/blueprint/detail/status-panel.tsx index 09d2fdf2529..c3de3c2ef2d 100644 --- a/config-ui/src/routes/blueprint/detail/status-panel.tsx +++ b/config-ui/src/routes/blueprint/detail/status-panel.tsx @@ -120,7 +120,7 @@ export const StatusPanel = ({ from, blueprint, pipelineId, onRefresh }: Props) = type="primary" disabled={!blueprint.enable} loading={operating} - onClick={() => handleRun({ skipCollectors: true })} + onClick={() => handleRun({ skipCollectors: true, fullSync: true })} > Re-transform Data From 7e1b853ff7b630020f80d951fafd194eb531163e Mon Sep 17 00:00:00 2001 From: Chaojie Yan Date: Fri, 27 Sep 2024 09:22:00 +0800 Subject: [PATCH 24/32] feat: keep source table name as destination table name (#8108) (#8109) --- backend/plugins/starrocks/tasks/tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/plugins/starrocks/tasks/tasks.go b/backend/plugins/starrocks/tasks/tasks.go index 2604f62e014..cc33db2826d 100644 --- a/backend/plugins/starrocks/tasks/tasks.go +++ b/backend/plugins/starrocks/tasks/tasks.go @@ -110,7 +110,7 @@ func ExportData(c plugin.SubTaskContext) errors.Error { SrcDb: db, DestDb: starrocksDb, SrcTableName: table, - DestTableName: strings.TrimLeft(table, "_"), + DestTableName: table, } columnMap, orderBy, skip, err := createTmpTableInStarrocks(&dc) if skip { From 94aaaf93d0301311feeee6f0883ab59e56a75a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Sat, 28 Sep 2024 00:51:31 +1200 Subject: [PATCH 25/32] feat: simplify the miller columns (#8112) --- config-ui/package.json | 4 +- .../data-scope-remote/search-local.tsx | 129 ++++++----------- .../data-scope-remote/search-remote.tsx | 135 ++++++++---------- .../components/data-scope-select/index.tsx | 95 +++++++----- .../webhook/components/selector-dialog.tsx | 19 +-- config-ui/yarn.lock | 20 +-- 6 files changed, 189 insertions(+), 213 deletions(-) diff --git a/config-ui/package.json b/config-ui/package.json index 6bf07198852..7e1305d7240 100644 --- a/config-ui/package.json +++ b/config-ui/package.json @@ -24,8 +24,8 @@ "dependencies": { "@ant-design/icons": "^5.4.0", "@fontsource/roboto": "^5.0.14", - "@mints/hooks": "^1.0.0-beta.2", - "@mints/miller-columns": "^2.0.0-beta.5", + "@mints/hooks": "^1.0.0-beta.9", + "@mints/miller-columns": "^2.0.0-beta.10", "@mui/icons-material": "^5.16.7", "@mui/material": "^5.16.7", "@mui/styled-engine-sc": "^6.0.0-alpha.18", diff --git a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx index 67b8f4a7f16..961ca68e918 100644 --- a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx +++ b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx @@ -16,11 +16,12 @@ * */ -import { useState, useReducer, useCallback } from 'react'; +import { useState, useReducer } from 'react'; import { CheckCircleFilled, SearchOutlined } from '@ant-design/icons'; import { Space, Tag, Button, Input, Modal } from 'antd'; -import { MillerColumns } from '@mints/miller-columns'; import { useDebounce } from '@mints/hooks'; +import type { IDType } from '@mints/miller-columns'; +import { MillerColumns } from '@mints/miller-columns'; import API from '@/api'; import { Block, Loading, Message } from '@/components'; @@ -76,43 +77,26 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, const searchDebounce = useDebounce(search, { wait: 500 }); - const request = useCallback( - async (groupId?: string | number, params?: any) => { - const res = await API.scope.remote(plugin, connectionId, { - groupId: groupId ?? null, - pageToken: params?.nextPageToken, - }); - - return { - data: res.children.map((it) => ({ - parentId: it.parentId, - id: it.id, - title: it.name ?? it.fullName, - canExpand: it.type === 'group', - original: it, - })), - hasMore: !!res.nextPageToken, - params: { - nextPageToken: res.nextPageToken, - }, - }; - }, - [plugin, connectionId, scope, searchDebounce], - ); + const request = async (groupId?: string | number, params?: any) => { + const res = await API.scope.remote(plugin, connectionId, { + groupId: groupId ?? null, + pageToken: params?.nextPageToken, + }); - const requestAll = useCallback( - async (groupId?: string | number) => { - return { - data: searchDebounce - ? scope - .filter((it) => it.title.includes(searchDebounce) && !it.canExpand) - .map((it) => ({ ...it, parentId: null })) - : scope.filter((it) => it.parentId === (groupId ?? null)), - hasMore: false, - }; - }, - [scope, searchDebounce], - ); + return { + data: res.children.map((it) => ({ + parentId: it.parentId, + id: it.id, + title: it.name ?? it.fullName, + canExpand: it.type === 'group', + original: it, + })), + hasMore: !!res.nextPageToken, + params: { + nextPageToken: res.nextPageToken, + }, + }; + }; const handleRequestAll = async () => { setOpen(false); @@ -145,6 +129,24 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, dispatch({ type: 'DONE' }); }; + const millerColumnsProps = { + bordered: true, + theme: { + colorPrimary: '#7497f7', + borderColor: '#dbe4fd', + }, + columnHeight: 300, + mode, + renderTitle: (id?: IDType) => + !id && + config.millerColumn?.firstColumnTitle && {config.millerColumn.firstColumnTitle}, + renderLoading: () => , + selectable: true, + disabledIds: disabledScope.map((it) => it.id), + selectedIds: selectedScope.map((it) => it.id), + onSelectedIds: (_: IDType[], data?: any) => onChange(data ?? []), + }; + return ( <> @@ -189,56 +191,19 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, )} - {status === 'idle' && ( + {status === 'idle' ? ( - !id && - config.millerColumn?.firstColumnTitle && ( - {config.millerColumn.firstColumnTitle} - ) - } - renderLoading={() => } - renderError={() => Something Error} - selectable - disabledIds={(disabledScope ?? []).map((it) => it.id)} - selectedIds={selectedScope.map((it) => it.id)} - onSelectedIds={(_, data) => onChange(data ?? [])} + columnCount={config.millerColumn?.columnCount ?? 1} /> - )} - {status === 'done' && ( + ) : ( <> } value={search} onChange={(e) => setSearch(e.target.value)} /> - !id && - config.millerColumn?.firstColumnTitle && ( - {config.millerColumn.firstColumnTitle} - ) - } - renderLoading={() => } - renderError={() => Something Error} - selectable - disabledIds={(disabledScope ?? []).map((it) => it.id)} - selectedIds={selectedScope.map((it) => it.id)} - onSelectedIds={(_, data) => onChange(data ?? [])} + {...millerColumnsProps} + loading={status === 'loading'} + items={searchDebounce ? scope.filter((it) => it.title.includes(searchDebounce) && !it.canExpand) : scope} /> )} diff --git a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx index 0510ad29a88..1841d3403b4 100644 --- a/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx +++ b/config-ui/src/plugins/components/data-scope-remote/search-remote.tsx @@ -16,11 +16,13 @@ * */ -import { useState, useCallback } from 'react'; +import { useState } from 'react'; import { SearchOutlined } from '@ant-design/icons'; import { Space, Tag, Input } from 'antd'; -import { MillerColumns } from '@mints/miller-columns'; +import { useRequest } from '@mints/hooks'; import { useDebounce } from '@mints/hooks'; +import type { IDType } from '@mints/miller-columns'; +import { MillerColumns } from '@mints/miller-columns'; import API from '@/api'; import { Block, Loading } from '@/components'; @@ -43,60 +45,62 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope const searchDebounce = useDebounce(search, { wait: 500 }); - const request = useCallback( - async (groupId?: string | number, params?: any) => { - let data = []; - let hasMore = false; - let newParams = {}; - - if (!searchDebounce) { - const res = await API.scope.remote(plugin, connectionId, { - groupId: groupId ?? null, - pageToken: params?.pageToken, - }); - - data = res.children.map((it) => ({ - parentId: it.parentId, - id: it.id, - title: it.name ?? it.fullName, - canExpand: it.type === 'group', - original: it, - })); + const { loading, data } = useRequest(async () => { + if (!searchDebounce) { + return []; + } + const res = await API.scope.searchRemote(plugin, connectionId, { + search: searchDebounce, + page: 1, + pageSize: 50, + }); + return res.children.map((it) => ({ + parentId: it.parentId, + id: it.id, + title: it.fullName ?? it.name, + canExpand: it.type === 'group', + original: it, + })); + }, [plugin, connectionId, searchDebounce]); - hasMore = !!res.nextPageToken; - newParams = { - pageToken: res.nextPageToken, - }; - } else { - const res = await API.scope.searchRemote(plugin, connectionId, { - search: searchDebounce, - page: params?.page ?? 1, - pageSize: 20, - }); + const request = async (groupId?: string | number, params?: any) => { + const res = await API.scope.remote(plugin, connectionId, { + groupId: groupId ?? null, + pageToken: params?.pageToken, + }); - data = res.children.map((it) => ({ - parentId: it.parentId, - id: it.id, - title: it.fullName ?? it.name, - canExpand: it.type === 'group', - original: it, - })); + return { + data: res.children.map((it) => ({ + parentId: it.parentId, + id: it.id, + title: it.name ?? it.fullName, + canExpand: it.type === 'group', + original: it, + })), + hasMore: !!res.nextPageToken, + params: { + pageToken: res.nextPageToken, + }, + }; + }; - hasMore = res.children.length === res.pageSize; - newParams = { - page: (params?.page ?? 0) + 1, - count: (params?.count ?? 0) + res.children.length, - }; - } - - return { - data, - hasMore, - params: newParams, - }; + const millerColumnsProps = { + bordered: true, + theme: { + colorPrimary: '#7497f7', + borderColor: '#dbe4fd', }, - [plugin, connectionId, searchDebounce], - ); + columnHeight: 300, + mode, + renderTitle: (id?: IDType) => + !id && + config.millerColumn?.firstColumnTitle && {config.millerColumn.firstColumnTitle}, + renderLoading: () => , + selectable: true, + disabledIds: disabledScope.map((it) => it.id), + selectedIds: selectedScope.map((it) => it.id), + onSelectedIds: (_: IDType[], data?: any) => onChange(data ?? []), + }; return ( <> @@ -125,28 +129,11 @@ export const SearchRemote = ({ mode, plugin, connectionId, config, disabledScope value={search} onChange={(e) => setSearch(e.target.value)} /> - - !id && - config.millerColumn?.firstColumnTitle && ( - {config.millerColumn.firstColumnTitle} - ) - } - renderLoading={() => } - selectable - disabledIds={disabledScope.map((it) => it.id)} - selectedIds={selectedScope.map((it) => it.id)} - onSelectedIds={(_, data) => onChange(data ?? [])} - /> + {searchDebounce ? ( + + ) : ( + + )} ); diff --git a/config-ui/src/plugins/components/data-scope-select/index.tsx b/config-ui/src/plugins/components/data-scope-select/index.tsx index d6913cee0a8..6bee1af1e61 100644 --- a/config-ui/src/plugins/components/data-scope-select/index.tsx +++ b/config-ui/src/plugins/components/data-scope-select/index.tsx @@ -19,12 +19,15 @@ import { useState, useEffect, useCallback } from 'react'; import { RedoOutlined, PlusOutlined } from '@ant-design/icons'; import { Flex, Button, Input, Space, Tag } from 'antd'; +import { useRequest } from '@mints/hooks'; +import type { IDType } from '@mints/miller-columns'; import { MillerColumns } from '@mints/miller-columns'; import { useDebounce } from '@mints/hooks'; import API from '@/api'; import { Loading, Block, ExternalLink, Message } from '@/components'; import { getPluginScopeId } from '@/plugins'; +import type { IDataScope } from '@/types'; interface Props { plugin: string; @@ -65,6 +68,25 @@ export const DataScopeSelect = ({ ); }, []); + const { loading, data } = useRequest(async () => { + if (!searchDebounce) { + return []; + } + const res = await API.scope.list(plugin, connectionId, { + page: 1, + pageSize: 50, + searchTerm: searchDebounce, + }); + + return res.scopes.map((it) => ({ + parentId: null, + id: getPluginScopeId(plugin, it.scope), + title: it.scope.fullName ?? it.scope.name, + canExpand: false, + original: it, + })); + }, [plugin, connectionId, searchDebounce, version]); + const request = useCallback( async (_?: string | number, params?: any) => { const res = await API.scope.list(plugin, connectionId, { @@ -87,11 +109,46 @@ export const DataScopeSelect = ({ }, }; }, - [plugin, connectionId, searchDebounce, version], + [plugin, connectionId], ); const handleSubmit = () => onSubmit?.(selectedIds); + const millerColumnsProps = { + bordered: true, + theme: { + colorPrimary: '#7497f7', + borderColor: '#dbe4fd', + }, + columnHeight: 200, + renderLoading: () => , + renderNoData: () => ( + + + + + + ), + selectable: true, + selectedIds, + onSelectedIds: ( + ids: IDType[], + data?: Array<{ + scope: IDataScope; + }>, + ) => { + setSelectedIds(ids); + setSelectedScope( + (data ?? []).map((it) => ({ + id: getPluginScopeId(plugin, it.scope), + name: it.scope.fullName ?? it.scope.name, + })), + ); + }, + }; + return (
setSearch(e.target.value)} /> - } - renderError={() => Something Error} - renderNoData={() => ( - - - - - - )} - selectable - selectedIds={selectedIds} - onSelectedIds={(ids, data) => { - setSelectedIds(ids); - setSelectedScope( - (data ?? []).map((it) => ({ - id: it.scope.id, - name: it.scope.name, - })), - ); - }} - /> + {searchDebounce ? ( + + ) : ( + + )}
diff --git a/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx b/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx index a0c972dee37..516298572a9 100644 --- a/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx +++ b/config-ui/src/plugins/register/webhook/components/selector-dialog.tsx @@ -16,7 +16,7 @@ * */ -import { useCallback, useState } from 'react'; +import { useState } from 'react'; import { Modal } from 'antd'; import { MillerColumns } from '@mints/miller-columns'; @@ -39,17 +39,6 @@ export const SelectorDialog = ({ open, saving, onCancel, onSubmit }: Props) => { const webhooks = useAppSelector(selectWebhooks); - const request = useCallback(async () => { - return { - data: webhooks.map((it) => ({ - parentId: null, - id: it.id, - title: it.name, - })), - hasMore: false, - }; - }, [webhooks]); - const handleSubmit = () => onSubmit(webhooks.filter((it) => selectedIds.includes(it.id))); return ( @@ -74,7 +63,11 @@ export const SelectorDialog = ({ open, saving, onCancel, onSubmit }: Props) => { colorPrimary: '#7497f7', borderColor: '#dbe4fd', }} - request={request} + items={webhooks.map((it) => ({ + parentId: null, + id: it.id, + title: it.name, + }))} columnHeight={160} renderLoading={() => } selectable diff --git a/config-ui/yarn.lock b/config-ui/yarn.lock index 9e36a73e38c..c7db434e486 100644 --- a/config-ui/yarn.lock +++ b/config-ui/yarn.lock @@ -2073,9 +2073,9 @@ __metadata: languageName: node linkType: hard -"@mints/hooks@npm:^1.0.0-beta.2": - version: 1.0.0-beta.2 - resolution: "@mints/hooks@npm:1.0.0-beta.2" +"@mints/hooks@npm:^1.0.0-beta.9": + version: 1.0.0-beta.9 + resolution: "@mints/hooks@npm:1.0.0-beta.9" dependencies: lodash: ^4.17.21 react: ^18.3.1 @@ -2083,13 +2083,13 @@ __metadata: peerDependencies: react: ^18.3.1 react-dom: ^18.3.1 - checksum: b11707b70aca8c931d247e18065046d7f5bbef4eee7e17bbae1ff1c85a4f90e830d6af0d3397bd8bec63fa81b5f44055363184b162b4cd90edc0316d4d53251b + checksum: 03f146f2e1881dee18383502dc7631f630c7b99fd7da67d54d37a7b3abac6518e0a302e34b968c72d27cb21ae0c45c39e34d668930881d3e1fd2fbb7dac34b85 languageName: node linkType: hard -"@mints/miller-columns@npm:^2.0.0-beta.5": - version: 2.0.0-beta.5 - resolution: "@mints/miller-columns@npm:2.0.0-beta.5" +"@mints/miller-columns@npm:^2.0.0-beta.10": + version: 2.0.0-beta.10 + resolution: "@mints/miller-columns@npm:2.0.0-beta.10" dependencies: "@fontsource/roboto": ^5.0.14 "@mui/material": ^5.16.7 @@ -2108,7 +2108,7 @@ __metadata: react-dom: ^18.2.0 react-infinite-scroll-component: ^6.1.0 styled-components: ^6.1.12 - checksum: 2ff5e7e942a1f5e592d7fe53d5522a59d72075604e80cfcf816d70d67ad33d3982b699770cdab01065bff19a219117b51017ea878ce5f015f120fb6623431839 + checksum: 94c3ba41210f2ccbddc413ef6c26e5615f11c5a3aac7954484d838d1b05713543def70b6714e79cfc396efea522f553b2d648b36af994bf66456a440836a1386 languageName: node linkType: hard @@ -3910,8 +3910,8 @@ __metadata: dependencies: "@ant-design/icons": ^5.4.0 "@fontsource/roboto": ^5.0.14 - "@mints/hooks": ^1.0.0-beta.2 - "@mints/miller-columns": ^2.0.0-beta.5 + "@mints/hooks": ^1.0.0-beta.9 + "@mints/miller-columns": ^2.0.0-beta.10 "@mui/icons-material": ^5.16.7 "@mui/material": ^5.16.7 "@mui/styled-engine-sc": ^6.0.0-alpha.18 From ec2a50f4c1952261dc12b29196ffb6c46092433f Mon Sep 17 00:00:00 2001 From: "Louis.z" Date: Sun, 29 Sep 2024 13:09:35 +0800 Subject: [PATCH 26/32] fix: improve the time filters in DORA dashboards (#8114) Co-authored-by: Startrekzky --- grafana/dashboards/DORA.json | 8 ++++---- grafana/dashboards/DORAByTeam.json | 2 +- grafana/dashboards/DORADebug.json | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/grafana/dashboards/DORA.json b/grafana/dashboards/DORA.json index 85ea67ac38c..3d3fdaa0983 100644 --- a/grafana/dashboards/DORA.json +++ b/grafana/dashboards/DORA.json @@ -962,7 +962,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1095,7 +1095,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hours'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hours'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1249,7 +1249,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1407,7 +1407,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n $__timeFilter(cm.month_timestamp)\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n $__timeFilter(cm.month_timestamp)\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n $__timeFilter(cm.month_timestamp)", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ diff --git a/grafana/dashboards/DORAByTeam.json b/grafana/dashboards/DORAByTeam.json index 972d11ee23e..863aaac35a1 100644 --- a/grafana/dashboards/DORAByTeam.json +++ b/grafana/dashboards/DORAByTeam.json @@ -1143,7 +1143,7 @@ "format": "table", "hide": false, "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN commits c on cdc.commit_sha = c.sha\n join user_accounts ua on c.author_id = ua.account_id\n join users u on ua.user_id = u.id\n join team_users tu on u.id = tu.user_id\n join teams t on tu.team_id = t.id\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n t.name in (${team})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n $__timeFilter(cm.month_timestamp)\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n join user_accounts ua on i.assignee_id = ua.account_id\n join users u on ua.user_id = u.id\n join team_users tu on u.id = tu.user_id\n join teams t on tu.team_id = t.id\n WHERE\n t.name in (${team})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n $__timeFilter(cm.month_timestamp)\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n $__timeFilter(cm.month_timestamp)", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN commits c on cdc.commit_sha = c.sha\n join user_accounts ua on c.author_id = ua.account_id\n join users u on ua.user_id = u.id\n join team_users tu on u.id = tu.user_id\n join teams t on tu.team_id = t.id\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n t.name in (${team})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n join user_accounts ua on i.assignee_id = ua.account_id\n join users u on ua.user_id = u.id\n join team_users tu on u.id = tu.user_id\n join teams t on tu.team_id = t.id\n WHERE\n t.name in (${team})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "sql": { "columns": [ diff --git a/grafana/dashboards/DORADebug.json b/grafana/dashboards/DORADebug.json index f547740bbd9..935b035c1da 100644 --- a/grafana/dashboards/DORADebug.json +++ b/grafana/dashboards/DORADebug.json @@ -557,7 +557,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1466,7 +1466,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hour'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hour'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -3210,7 +3210,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n $__timeFilter(cm.month_timestamp)\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.created_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n $__timeFilter(cm.month_timestamp)\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n $__timeFilter(cm.month_timestamp)", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.created_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -3711,7 +3711,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n $__timeFilter(cm.month_timestamp)", + "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ From 47a9fcd68b2135114ed9d85d409f34f28950541e Mon Sep 17 00:00:00 2001 From: Lynwee <1507509064@qq.com> Date: Mon, 30 Sep 2024 09:46:52 +0800 Subject: [PATCH 27/32] fix(zentao): make `gitcommited` a valiad action (#8115) --- backend/plugins/zentao/tasks/bug_commits_extractor.go | 4 ++-- backend/plugins/zentao/tasks/story_commits_extractor.go | 4 ++-- backend/plugins/zentao/tasks/task_commits_extractor.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/plugins/zentao/tasks/bug_commits_extractor.go b/backend/plugins/zentao/tasks/bug_commits_extractor.go index 6a634557ad0..66d17a395ec 100644 --- a/backend/plugins/zentao/tasks/bug_commits_extractor.go +++ b/backend/plugins/zentao/tasks/bug_commits_extractor.go @@ -60,8 +60,8 @@ func ExtractBugCommits(taskCtx plugin.SubTaskContext) errors.Error { if err != nil { return nil, errors.Default.WrapRaw(err) } - // only linked2revision action is valid - if res.Action != "linked2revision" { + // only linked2revision and gitcommited action is valid + if res.Action != "linked2revision" && res.Action != "gitcommited" { return nil, nil } diff --git a/backend/plugins/zentao/tasks/story_commits_extractor.go b/backend/plugins/zentao/tasks/story_commits_extractor.go index 4a5d133da53..91f1d3fa1ee 100644 --- a/backend/plugins/zentao/tasks/story_commits_extractor.go +++ b/backend/plugins/zentao/tasks/story_commits_extractor.go @@ -56,8 +56,8 @@ func ExtractStoryCommits(taskCtx plugin.SubTaskContext) errors.Error { return nil, errors.Default.WrapRaw(err) } - // only linked2revision action is valid - if res.Action != "linked2revision" { + // only linked2revision and gitcommited action is valid + if res.Action != "linked2revision" && res.Action != "gitcommited" { return nil, nil } diff --git a/backend/plugins/zentao/tasks/task_commits_extractor.go b/backend/plugins/zentao/tasks/task_commits_extractor.go index 5f52c3ebcf8..c2f2bf15771 100644 --- a/backend/plugins/zentao/tasks/task_commits_extractor.go +++ b/backend/plugins/zentao/tasks/task_commits_extractor.go @@ -56,8 +56,8 @@ func ExtractTaskCommits(taskCtx plugin.SubTaskContext) errors.Error { return nil, errors.Default.WrapRaw(err) } - // only linked2revision action is valid - if res.Action != "linked2revision" { + // only linked2revision and gitcommited action is valid + if res.Action != "linked2revision" && res.Action != "gitcommited" { return nil, nil } From 11db8e9bc80d7a70e5d2503ba0e640c71c7a6cca Mon Sep 17 00:00:00 2001 From: Lynwee <1507509064@qq.com> Date: Mon, 30 Sep 2024 10:30:14 +0800 Subject: [PATCH 28/32] feat: check pipelines' tokens before executing/creating pipeline (#8055) (#8069) * feat: check pipelines' tokens before executing/creating pipeline (#8055) * feat(pipeline): check pipelines' tokens before executing/creating pipeline * fix(framework): fix lint errors * fix(framework): fix lint errors * feat(github): check multi tokens when creating pipelines * feat(project): add token check result in project check API (#8099) * Dev 1 (#8100) * feat(project): add token check result in project check API * feat(project): update token check API response * Dev 1 (#8101) * feat(project): add token check result in project check API * feat(project): update token check API response * fix(project): fix api doc * fix(project): update project check api doc * fix(project): update check project api doc * feat: add connection token check before collect data * feat(blueprint): add new api to check connection tokens (#8102) * fix: adjust the api for connections token check * feat: add a component connection-form-modal * feat: add a component connection-name * fix: show connection form modal when connection token check failed * refactor: improve the component connection-name * fix: error check connection token failed list * refactor: extract the function in the panel to bp detail * fix: not call onCancel function when updating connection * fix: search local items error --------- Co-authored-by: mintsweet <0x1304570@gmail.com> --- backend/core/models/blueprint.go | 9 ++ backend/core/plugin/plugin_api.go | 4 + backend/core/plugin/plugin_blueprint.go | 10 ++ .../helpers/pluginhelper/api/misc_helpers.go | 10 ++ backend/plugins/ae/impl/impl.go | 5 + backend/plugins/azuredevops_go/impl/impl.go | 5 + backend/plugins/bamboo/impl/impl.go | 5 + backend/plugins/bitbucket/impl/impl.go | 5 + backend/plugins/bitbucket_server/impl/impl.go | 5 + backend/plugins/circleci/impl/impl.go | 5 + backend/plugins/customize/impl/impl.go | 4 + backend/plugins/dbt/impl/impl.go | 4 + backend/plugins/dora/impl/impl.go | 5 +- backend/plugins/feishu/impl/impl.go | 5 + backend/plugins/gitee/impl/impl.go | 5 + backend/plugins/gitextractor/impl/impl.go | 4 + backend/plugins/github/api/shared.go | 42 ++++++ backend/plugins/github/impl/impl.go | 4 + backend/plugins/gitlab/impl/impl.go | 5 + backend/plugins/icla/impl/impl.go | 4 + backend/plugins/issue_trace/impl/enricher.go | 5 +- backend/plugins/jenkins/impl/impl.go | 5 + backend/plugins/jira/impl/impl.go | 5 + backend/plugins/linker/impl/impl.go | 4 + backend/plugins/opsgenie/impl/impl.go | 5 + backend/plugins/org/impl/impl.go | 22 +++ backend/plugins/org/tasks/check_token.go | 75 ++++++++++ backend/plugins/org/tasks/task_data.go | 10 +- backend/plugins/pagerduty/impl/impl.go | 5 + backend/plugins/refdiff/impl/impl.go | 4 + backend/plugins/slack/impl/impl.go | 5 + backend/plugins/sonarqube/impl/impl.go | 5 + backend/plugins/starrocks/impl/impl.go | 4 + backend/plugins/tapd/impl/impl.go | 5 + backend/plugins/teambition/impl/impl.go | 5 + backend/plugins/trello/impl/impl.go | 5 + backend/plugins/webhook/impl/impl.go | 4 + backend/plugins/zentao/impl/impl.go | 5 + backend/server/api/blueprints/blueprints.go | 24 +++ backend/server/api/project/project.go | 8 +- backend/server/api/router.go | 1 + backend/server/services/blueprint.go | 93 ++++++++++++ .../services/blueprint_makeplan_v200.go | 15 ++ backend/server/services/project.go | 2 +- .../services/remote/models/plugin_remote.go | 1 + .../services/remote/plugin/plugin_impl.go | 5 + config-ui/package.json | 2 +- config-ui/src/api/blueprint/index.ts | 2 + config-ui/src/features/connections/index.ts | 1 - .../connection-form/connection-form-modal.tsx | 56 +++++++ .../{index.tsx => connection-form.tsx} | 0 .../components/connection-form}/index.ts | 3 +- .../components/connection-list/index.tsx | 40 +---- .../components/connection-name/index.tsx} | 77 +++++----- .../components/connection-name/styled.ts | 46 ++++++ .../data-scope-remote/search-local.tsx | 11 +- config-ui/src/plugins/components/index.ts | 1 + .../blueprint/detail/blueprint-detail.tsx | 140 ++++++++++++++++-- .../components/connection-check/index.tsx | 39 +++++ .../blueprint/detail/components/index.ts | 1 + .../blueprint/detail/configuration-panel.tsx | 57 ++----- .../routes/blueprint/detail/status-panel.tsx | 74 ++------- config-ui/src/routes/blueprint/home/index.tsx | 2 +- .../src/routes/connection/connection.tsx | 15 +- .../src/routes/connection/connections.tsx | 29 +--- config-ui/src/routes/connection/styled.ts | 16 -- config-ui/src/routes/project/home/index.tsx | 2 +- config-ui/yarn.lock | 10 +- 68 files changed, 827 insertions(+), 269 deletions(-) create mode 100644 backend/plugins/github/api/shared.go create mode 100644 backend/plugins/org/tasks/check_token.go create mode 100644 config-ui/src/plugins/components/connection-form/connection-form-modal.tsx rename config-ui/src/plugins/components/connection-form/{index.tsx => connection-form.tsx} (100%) rename config-ui/src/{features/connections/components => plugins/components/connection-form}/index.ts (91%) rename config-ui/src/{features/connections/components/name.tsx => plugins/components/connection-name/index.tsx} (53%) create mode 100644 config-ui/src/plugins/components/connection-name/styled.ts create mode 100644 config-ui/src/routes/blueprint/detail/components/connection-check/index.tsx diff --git a/backend/core/models/blueprint.go b/backend/core/models/blueprint.go index f30adec9f05..9dc46882204 100644 --- a/backend/core/models/blueprint.go +++ b/backend/core/models/blueprint.go @@ -92,3 +92,12 @@ type SyncPolicy struct { TimeAfter *time.Time `json:"timeAfter"` TriggerSyncPolicy } + +type ConnectionTokenCheckResult struct { + PluginName string `json:"pluginName" mapstructure:"pluginName"` + ConnectionID uint64 `json:"connectionId" mapstructure:"connectionId"` + Success bool `json:"success" mapstructure:"success"` + Message string `json:"message" mapstructure:"message"` +} + +type ApiBlueprintConnectionTokenCheck []ConnectionTokenCheckResult diff --git a/backend/core/plugin/plugin_api.go b/backend/core/plugin/plugin_api.go index f9195d2eed4..ea41a4895e8 100644 --- a/backend/core/plugin/plugin_api.go +++ b/backend/core/plugin/plugin_api.go @@ -73,6 +73,10 @@ type PluginApi interface { ApiResources() map[string]map[string]ApiResourceHandler } +type PluginTestConnectionAPI interface { + TestConnection(id uint64) errors.Error +} + const wrapResponseError = "WRAP_RESPONSE_ERROR" func WrapTestConnectionErrResp(basicRes context.BasicRes, err errors.Error) errors.Error { diff --git a/backend/core/plugin/plugin_blueprint.go b/backend/core/plugin/plugin_blueprint.go index b722bb9e2cf..a24513564b1 100644 --- a/backend/core/plugin/plugin_blueprint.go +++ b/backend/core/plugin/plugin_blueprint.go @@ -93,6 +93,16 @@ type ProjectMapper interface { MapProject(projectName string, scopes []Scope) (models.PipelinePlan, errors.Error) } +type ProjectTokenCheckerConnection struct { + PluginName string + ConnectionId uint64 +} + +// ProjectTokenChecker is implemented by the plugin org, which generate a task tp check all connection's tokens +type ProjectTokenChecker interface { + MakePipeline(skipCollectors bool, projectName string, scopes []ProjectTokenCheckerConnection) (models.PipelinePlan, errors.Error) +} + // CompositeDataSourcePluginBlueprintV200 is for unit test type CompositeDataSourcePluginBlueprintV200 interface { PluginMeta diff --git a/backend/helpers/pluginhelper/api/misc_helpers.go b/backend/helpers/pluginhelper/api/misc_helpers.go index e7315ceab5a..3dcf8778c7f 100644 --- a/backend/helpers/pluginhelper/api/misc_helpers.go +++ b/backend/helpers/pluginhelper/api/misc_helpers.go @@ -18,9 +18,11 @@ limitations under the License. package api import ( + "fmt" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models" + "github.com/apache/incubator-devlake/core/plugin" ) // CallDB wraps DB calls with this signature, and handles the case if the struct is wrapped in a models.DynamicTabler. @@ -31,3 +33,11 @@ func CallDB(f func(any, ...dal.Clause) errors.Error, x any, clauses ...dal.Claus } return f(x, clauses...) } + +func GenerateTestingConnectionApiResourceInput(connectionID uint64) *plugin.ApiResourceInput { + return &plugin.ApiResourceInput{ + Params: map[string]string{ + "connectionId": fmt.Sprintf("%d", connectionID), + }, + } +} diff --git a/backend/plugins/ae/impl/impl.go b/backend/plugins/ae/impl/impl.go index 389857e1f30..7356d9e0e2c 100644 --- a/backend/plugins/ae/impl/impl.go +++ b/backend/plugins/ae/impl/impl.go @@ -130,6 +130,11 @@ func (p AE) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p AE) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p AE) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/azuredevops_go/impl/impl.go b/backend/plugins/azuredevops_go/impl/impl.go index c567e49f57c..2aecfde5105 100644 --- a/backend/plugins/azuredevops_go/impl/impl.go +++ b/backend/plugins/azuredevops_go/impl/impl.go @@ -255,6 +255,11 @@ func (p Azuredevops) ApiResources() map[string]map[string]plugin.ApiResourceHand } } +func (p Azuredevops) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Azuredevops) MakeDataSourcePipelinePlanV200( connectionId uint64, scopes []*coreModels.BlueprintScope, diff --git a/backend/plugins/bamboo/impl/impl.go b/backend/plugins/bamboo/impl/impl.go index b90331df1ca..b7737770a72 100644 --- a/backend/plugins/bamboo/impl/impl.go +++ b/backend/plugins/bamboo/impl/impl.go @@ -216,6 +216,11 @@ func (p Bamboo) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Bamboo) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Bamboo) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/bitbucket/impl/impl.go b/backend/plugins/bitbucket/impl/impl.go index dd917790c71..4ff5bc5e9e7 100644 --- a/backend/plugins/bitbucket/impl/impl.go +++ b/backend/plugins/bitbucket/impl/impl.go @@ -211,6 +211,11 @@ func (p Bitbucket) MakeDataSourcePipelinePlanV200( return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors) } +func (p Bitbucket) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Bitbucket) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/bitbucket_server/impl/impl.go b/backend/plugins/bitbucket_server/impl/impl.go index 18b4a46795a..fe446d76ffa 100644 --- a/backend/plugins/bitbucket_server/impl/impl.go +++ b/backend/plugins/bitbucket_server/impl/impl.go @@ -170,6 +170,11 @@ func (p BitbucketServer) MakeDataSourcePipelinePlanV200( return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors) } +func (p BitbucketServer) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p BitbucketServer) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "connections/:connectionId/test": { diff --git a/backend/plugins/circleci/impl/impl.go b/backend/plugins/circleci/impl/impl.go index 8cca5895d9b..c08766a6d72 100644 --- a/backend/plugins/circleci/impl/impl.go +++ b/backend/plugins/circleci/impl/impl.go @@ -176,6 +176,11 @@ func (p Circleci) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Circleci) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Circleci) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/customize/impl/impl.go b/backend/plugins/customize/impl/impl.go index facb0515d97..59b967aa518 100644 --- a/backend/plugins/customize/impl/impl.go +++ b/backend/plugins/customize/impl/impl.go @@ -110,3 +110,7 @@ func (p Customize) ApiResources() map[string]map[string]plugin.ApiResourceHandle }, } } + +func (p Customize) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/dbt/impl/impl.go b/backend/plugins/dbt/impl/impl.go index 88eafa9f633..55b7c2918ed 100644 --- a/backend/plugins/dbt/impl/impl.go +++ b/backend/plugins/dbt/impl/impl.go @@ -74,3 +74,7 @@ func (p Dbt) RootPkgPath() string { func (p Dbt) Name() string { return "dbt" } + +func (p Dbt) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/dora/impl/impl.go b/backend/plugins/dora/impl/impl.go index 24609739811..0d41a94ebad 100644 --- a/backend/plugins/dora/impl/impl.go +++ b/backend/plugins/dora/impl/impl.go @@ -19,7 +19,6 @@ package impl import ( "encoding/json" - "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" coreModels "github.com/apache/incubator-devlake/core/models" @@ -168,3 +167,7 @@ func (p Dora) MakeMetricPluginPipelinePlanV200(projectName string, options json. } return plan, nil } + +func (p Dora) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/feishu/impl/impl.go b/backend/plugins/feishu/impl/impl.go index 92e0f1571c5..3158b5f1fef 100644 --- a/backend/plugins/feishu/impl/impl.go +++ b/backend/plugins/feishu/impl/impl.go @@ -132,6 +132,11 @@ func (p Feishu) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Feishu) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Feishu) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/gitee/impl/impl.go b/backend/plugins/gitee/impl/impl.go index 35be389e79b..b422fbafc05 100644 --- a/backend/plugins/gitee/impl/impl.go +++ b/backend/plugins/gitee/impl/impl.go @@ -187,6 +187,11 @@ func (p Gitee) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Gitee) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Gitee) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/gitextractor/impl/impl.go b/backend/plugins/gitextractor/impl/impl.go index 468e5173409..45c84ab6e17 100644 --- a/backend/plugins/gitextractor/impl/impl.go +++ b/backend/plugins/gitextractor/impl/impl.go @@ -122,3 +122,7 @@ func (p GitExtractor) Close(taskCtx plugin.TaskContext) errors.Error { func (p GitExtractor) RootPkgPath() string { return "github.com/apache/incubator-devlake/plugins/gitextractor" } + +func (p GitExtractor) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/github/api/shared.go b/backend/plugins/github/api/shared.go new file mode 100644 index 00000000000..61bb398015e --- /dev/null +++ b/backend/plugins/github/api/shared.go @@ -0,0 +1,42 @@ +/* +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 api + +import ( + "context" + "fmt" + "github.com/apache/incubator-devlake/core/errors" + "github.com/apache/incubator-devlake/core/plugin" +) + +func TestExistingConnectionForTokenCheck(input *plugin.ApiResourceInput) errors.Error { + connection, err := dsHelper.ConnApi.GetMergedConnection(input) + if err != nil { + return err + } + testConnectionResult, testConnectionErr := testExistingConnection(context.TODO(), connection.GithubConn) + if testConnectionErr != nil { + return testConnectionErr + } + for _, token := range testConnectionResult.Tokens { + if !token.Success { + return errors.Default.New(fmt.Sprintf("token %s failed with msg: %s", token.Token, token.Message)) + } + } + return nil +} diff --git a/backend/plugins/github/impl/impl.go b/backend/plugins/github/impl/impl.go index 52a772cf603..e030923706f 100644 --- a/backend/plugins/github/impl/impl.go +++ b/backend/plugins/github/impl/impl.go @@ -191,6 +191,10 @@ func (p Github) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Github) TestConnection(id uint64) errors.Error { + return api.TestExistingConnectionForTokenCheck(helper.GenerateTestingConnectionApiResourceInput(id)) +} + func (p Github) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/gitlab/impl/impl.go b/backend/plugins/gitlab/impl/impl.go index d292db691ed..46f63b52f9c 100644 --- a/backend/plugins/gitlab/impl/impl.go +++ b/backend/plugins/gitlab/impl/impl.go @@ -244,6 +244,11 @@ func (p Gitlab) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Gitlab) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Gitlab) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/icla/impl/impl.go b/backend/plugins/icla/impl/impl.go index 1f327f31318..2430741267e 100644 --- a/backend/plugins/icla/impl/impl.go +++ b/backend/plugins/icla/impl/impl.go @@ -104,6 +104,10 @@ func (p Icla) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return nil } +func (p Icla) TestConnection(id uint64) errors.Error { + return nil +} + func (p Icla) Close(taskCtx plugin.TaskContext) errors.Error { data, ok := taskCtx.GetData().(*tasks.IclaTaskData) if !ok { diff --git a/backend/plugins/issue_trace/impl/enricher.go b/backend/plugins/issue_trace/impl/enricher.go index 1506f2563dd..aeca45aded0 100644 --- a/backend/plugins/issue_trace/impl/enricher.go +++ b/backend/plugins/issue_trace/impl/enricher.go @@ -19,7 +19,6 @@ package impl import ( "encoding/json" - "github.com/apache/incubator-devlake/core/context" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" @@ -151,6 +150,10 @@ func (p IssueTrace) GetTablesInfo() []dal.Tabler { } } +func (p IssueTrace) TestConnection(id uint64) errors.Error { + return nil +} + func (p IssueTrace) MakeMetricPluginPipelinePlanV200(projectName string, options json.RawMessage) (coreModels.PipelinePlan, errors.Error) { op := &tasks.Options{} if options != nil && string(options) != "\"\"" { diff --git a/backend/plugins/jenkins/impl/impl.go b/backend/plugins/jenkins/impl/impl.go index 2a686037fd4..5a7f478b634 100644 --- a/backend/plugins/jenkins/impl/impl.go +++ b/backend/plugins/jenkins/impl/impl.go @@ -177,6 +177,11 @@ func (p Jenkins) MakeDataSourcePipelinePlanV200( return api.MakeDataSourcePipelinePlanV200(p.SubTaskMetas(), connectionId, scopes, skipCollectors) } +func (p Jenkins) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Jenkins) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/jira/impl/impl.go b/backend/plugins/jira/impl/impl.go index b7a62da20e1..51e623f32f9 100644 --- a/backend/plugins/jira/impl/impl.go +++ b/backend/plugins/jira/impl/impl.go @@ -285,6 +285,11 @@ func (p Jira) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Jira) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Jira) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/linker/impl/impl.go b/backend/plugins/linker/impl/impl.go index 917b22df9aa..27b9a6cef20 100644 --- a/backend/plugins/linker/impl/impl.go +++ b/backend/plugins/linker/impl/impl.go @@ -125,3 +125,7 @@ func (p Linker) MakeMetricPluginPipelinePlanV200(projectName string, options jso } return plan, nil } + +func (p Linker) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/opsgenie/impl/impl.go b/backend/plugins/opsgenie/impl/impl.go index 5785d53ff8a..7da8552e630 100644 --- a/backend/plugins/opsgenie/impl/impl.go +++ b/backend/plugins/opsgenie/impl/impl.go @@ -155,6 +155,11 @@ func (p Opsgenie) Close(taskCtx plugin.TaskContext) errors.Error { return nil } +func (p Opsgenie) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Opsgenie) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/org/impl/impl.go b/backend/plugins/org/impl/impl.go index cd4ffa7fda1..f0e6c4a0a0a 100644 --- a/backend/plugins/org/impl/impl.go +++ b/backend/plugins/org/impl/impl.go @@ -59,11 +59,33 @@ func (p Org) Name() string { func (p Org) SubTaskMetas() []plugin.SubTaskMeta { return []plugin.SubTaskMeta{ + tasks.TaskCheckTokenMeta, tasks.ConnectUserAccountsExactMeta, tasks.SetProjectMappingMeta, } } +func (p Org) MakePipeline(skipCollectors bool, projectName string, connections []plugin.ProjectTokenCheckerConnection) (coreModels.PipelinePlan, errors.Error) { + var plan coreModels.PipelinePlan + var stage coreModels.PipelineStage + + // construct task options for Org + options := make(map[string]interface{}) + if !skipCollectors { + options["projectConnections"] = connections + } + + stage = append(stage, &coreModels.PipelineTask{ + Plugin: p.Name(), + Subtasks: []string{ + tasks.TaskCheckTokenMeta.Name, + }, + Options: options, + }) + plan = append(plan, stage) + return plan, nil +} + func (p Org) MapProject(projectName string, scopes []plugin.Scope) (coreModels.PipelinePlan, errors.Error) { var plan coreModels.PipelinePlan var stage coreModels.PipelineStage diff --git a/backend/plugins/org/tasks/check_token.go b/backend/plugins/org/tasks/check_token.go new file mode 100644 index 00000000000..f147fe8e644 --- /dev/null +++ b/backend/plugins/org/tasks/check_token.go @@ -0,0 +1,75 @@ +/* +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 ( + "fmt" + "github.com/apache/incubator-devlake/core/errors" + "github.com/apache/incubator-devlake/core/plugin" + "golang.org/x/sync/errgroup" +) + +var TaskCheckTokenMeta = plugin.SubTaskMeta{ + Name: "checkTokens", + EntryPoint: checkProjectTokens, + EnabledByDefault: true, + Description: "set project mapping", + DomainTypes: []string{plugin.DOMAIN_TYPE_CROSS}, +} + +func checkProjectTokens(taskCtx plugin.SubTaskContext) errors.Error { + logger := taskCtx.GetLogger() + taskData := taskCtx.GetData().(*TaskData) + connections := taskData.Options.ProjectConnections + logger.Debug("connections %+v", connections) + if len(connections) == 0 { + return nil + } + + g := new(errgroup.Group) + for _, connection := range connections { + conn := connection + logger.Debug("check conn: %+v", conn) + g.Go(func() error { + if err := checkConnectionToken(conn.ConnectionId, conn.PluginName); err != nil { + return err + } + return nil + }) + } + if err := g.Wait(); err != nil { + return errors.Convert(err) + } + return nil +} + +func checkConnectionToken(connectionID uint64, pluginName string) errors.Error { + pluginEntry, err := plugin.GetPlugin(pluginName) + if err != nil { + return err + } + if v, ok := pluginEntry.(plugin.PluginTestConnectionAPI); ok { + if err := v.TestConnection(connectionID); err != nil { + return err + } + return nil + } else { + msg := fmt.Sprintf("plugin: %s doesn't impl test connection api", pluginName) + return errors.Default.New(msg) + } +} diff --git a/backend/plugins/org/tasks/task_data.go b/backend/plugins/org/tasks/task_data.go index ca2a9b3002d..c92954740a9 100644 --- a/backend/plugins/org/tasks/task_data.go +++ b/backend/plugins/org/tasks/task_data.go @@ -20,8 +20,14 @@ package tasks import "github.com/apache/incubator-devlake/core/plugin" type Options struct { - ConnectionId uint64 `json:"connectionId"` - ProjectMappings []ProjectMapping `json:"projectMappings"` + ConnectionId uint64 `json:"connectionId"` + ProjectMappings []ProjectMapping `json:"projectMappings"` + ProjectConnections []ProjectConnection `json:"projectConnections"` +} + +type ProjectConnection struct { + PluginName string + ConnectionId uint64 } // ProjectMapping represents the relations between project and scopes diff --git a/backend/plugins/pagerduty/impl/impl.go b/backend/plugins/pagerduty/impl/impl.go index b237b30e491..827df870126 100644 --- a/backend/plugins/pagerduty/impl/impl.go +++ b/backend/plugins/pagerduty/impl/impl.go @@ -138,6 +138,11 @@ func (p PagerDuty) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p PagerDuty) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p PagerDuty) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/refdiff/impl/impl.go b/backend/plugins/refdiff/impl/impl.go index b5572f6436a..e660b142497 100644 --- a/backend/plugins/refdiff/impl/impl.go +++ b/backend/plugins/refdiff/impl/impl.go @@ -110,3 +110,7 @@ func (p RefDiff) RootPkgPath() string { func (p RefDiff) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return nil } + +func (p RefDiff) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/slack/impl/impl.go b/backend/plugins/slack/impl/impl.go index 8b3de9142dc..9ac894373a5 100644 --- a/backend/plugins/slack/impl/impl.go +++ b/backend/plugins/slack/impl/impl.go @@ -131,6 +131,11 @@ func (p Slack) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Slack) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Slack) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/sonarqube/impl/impl.go b/backend/plugins/sonarqube/impl/impl.go index b6d2140324e..f0da8981282 100644 --- a/backend/plugins/sonarqube/impl/impl.go +++ b/backend/plugins/sonarqube/impl/impl.go @@ -170,6 +170,11 @@ func (p Sonarqube) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Sonarqube) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Sonarqube) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/starrocks/impl/impl.go b/backend/plugins/starrocks/impl/impl.go index 511b8c7ec02..de036bace19 100644 --- a/backend/plugins/starrocks/impl/impl.go +++ b/backend/plugins/starrocks/impl/impl.go @@ -67,3 +67,7 @@ func (s StarRocks) Name() string { func (s StarRocks) RootPkgPath() string { return "github.com/merico-dev/lake/plugins/starrocks" } + +func (s StarRocks) TestConnection(id uint64) errors.Error { + return nil +} diff --git a/backend/plugins/tapd/impl/impl.go b/backend/plugins/tapd/impl/impl.go index 2885a43379a..2e133d821d5 100644 --- a/backend/plugins/tapd/impl/impl.go +++ b/backend/plugins/tapd/impl/impl.go @@ -265,6 +265,11 @@ func (p Tapd) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Tapd) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Tapd) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/teambition/impl/impl.go b/backend/plugins/teambition/impl/impl.go index 662cace0fd7..728602d865c 100644 --- a/backend/plugins/teambition/impl/impl.go +++ b/backend/plugins/teambition/impl/impl.go @@ -169,6 +169,11 @@ func (p Teambition) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Teambition) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Teambition) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/trello/impl/impl.go b/backend/plugins/trello/impl/impl.go index b3a0f088d0d..fdcb10fdc24 100644 --- a/backend/plugins/trello/impl/impl.go +++ b/backend/plugins/trello/impl/impl.go @@ -151,6 +151,11 @@ func (p Trello) ScopeConfig() dal.Tabler { return &models.TrelloScopeConfig{} } +func (p Trello) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Trello) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/plugins/webhook/impl/impl.go b/backend/plugins/webhook/impl/impl.go index ada30478399..90e1f01986b 100644 --- a/backend/plugins/webhook/impl/impl.go +++ b/backend/plugins/webhook/impl/impl.go @@ -77,6 +77,10 @@ func (p Webhook) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Webhook) TestConnection(id uint64) errors.Error { + return nil +} + func (p Webhook) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "connections": { diff --git a/backend/plugins/zentao/impl/impl.go b/backend/plugins/zentao/impl/impl.go index 5aa74c96606..55a98165d4e 100644 --- a/backend/plugins/zentao/impl/impl.go +++ b/backend/plugins/zentao/impl/impl.go @@ -277,6 +277,11 @@ func (p Zentao) MigrationScripts() []plugin.MigrationScript { return migrationscripts.All() } +func (p Zentao) TestConnection(id uint64) errors.Error { + _, err := api.TestExistingConnection(helper.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p Zentao) ApiResources() map[string]map[string]plugin.ApiResourceHandler { return map[string]map[string]plugin.ApiResourceHandler{ "test": { diff --git a/backend/server/api/blueprints/blueprints.go b/backend/server/api/blueprints/blueprints.go index 841027424cc..2e6e315cb91 100644 --- a/backend/server/api/blueprints/blueprints.go +++ b/backend/server/api/blueprints/blueprints.go @@ -18,6 +18,7 @@ limitations under the License. package blueprints import ( + "github.com/spf13/cast" "net/http" "strconv" @@ -227,6 +228,29 @@ func GetBlueprintPipelines(c *gin.Context) { shared.ApiOutputSuccess(c, shared.ResponsePipelines{Pipelines: pipelines, Count: count}, http.StatusOK) } +// @Summary get connection token check by blueprint id +// @Description get connection token check by blueprint id +// @Tags framework/blueprints +// @Accept application/json +// @Param blueprintId path int true "blueprint id" +// @Success 200 {object} models.ApiBlueprintConnectionTokenCheck +// @Failure 400 {object} shared.ApiBody "Bad Request" +// @Failure 500 {object} shared.ApiBody "Internal Error" +// @Router /blueprints/{blueprintId}/connections-token-check [get] +func GetBlueprintConnectionTokenCheck(c *gin.Context) { + blueprintId, err := cast.ToUint64E(c.Param("blueprintId")) + if err != nil { + shared.ApiOutputError(c, errors.BadInput.Wrap(err, "bad blueprintID format supplied")) + return + } + resp, err := services.CheckBlueprintConnectionTokens(blueprintId) + if err != nil { + shared.ApiOutputError(c, errors.Default.Wrap(err, "error getting blue print connection token check")) + return + } + shared.ApiOutputSuccess(c, resp, http.StatusOK) +} + // @Summary delete blueprint by id // @Description delete blueprint by id // @Tags framework/blueprints diff --git a/backend/server/api/project/project.go b/backend/server/api/project/project.go index e826c71d170..fd5c14ebb5a 100644 --- a/backend/server/api/project/project.go +++ b/backend/server/api/project/project.go @@ -53,18 +53,17 @@ func GetProject(c *gin.Context) { shared.ApiOutputSuccess(c, projectOutput, http.StatusOK) } -// @Summary Get project exist check -// @Description Get project exist check +// @Summary Get project related check +// @Description Get project related check info, such existence, token validity // @Tags framework/projects // @Accept application/json // @Param projectName path string true "project name" -// @Success 200 {object} models.ApiOutputProject +// @Success 200 {object} models.ApiProjectCheck // @Failure 400 {string} errcode.Error "Bad Request" // @Failure 500 {string} errcode.Error "Internal Error" // @Router /projects/{projectName}/check [get] func GetProjectCheck(c *gin.Context) { projectName := c.Param("projectName") - projectOutputCheck := &models.ApiProjectCheck{} _, err := services.GetProject(projectName) if err != nil { @@ -72,7 +71,6 @@ func GetProjectCheck(c *gin.Context) { } else { projectOutputCheck.Exist = true } - shared.ApiOutputSuccess(c, projectOutputCheck, http.StatusOK) // //shared.ApiOutputSuccess(c, projectOutputCheck, http.StatusOK) } diff --git a/backend/server/api/router.go b/backend/server/api/router.go index 721517cf59a..226eb3035d3 100644 --- a/backend/server/api/router.go +++ b/backend/server/api/router.go @@ -59,6 +59,7 @@ func RegisterRouter(r *gin.Engine, basicRes context.BasicRes) { r.GET("/blueprints/:blueprintId", blueprints.Get) r.POST("/blueprints/:blueprintId/trigger", blueprints.Trigger) r.GET("/blueprints/:blueprintId/pipelines", blueprints.GetBlueprintPipelines) + r.GET("/blueprints/:blueprintId/connections-token-check", blueprints.GetBlueprintConnectionTokenCheck) r.POST("/tasks/:taskId/rerun", task.PostRerun) diff --git a/backend/server/services/blueprint.go b/backend/server/services/blueprint.go index 4d106674d24..aced9eeeace 100644 --- a/backend/server/services/blueprint.go +++ b/backend/server/services/blueprint.go @@ -20,6 +20,9 @@ package services import ( "encoding/json" "fmt" + "github.com/apache/incubator-devlake/core/log" + "github.com/apache/incubator-devlake/core/plugin" + "golang.org/x/sync/errgroup" "strings" "sync" @@ -114,6 +117,30 @@ func GetBlueprint(blueprintId uint64, shouldSanitize bool) (*models.Blueprint, e return blueprint, nil } +func CheckBlueprintConnectionTokens(blueprintId uint64) (*models.ApiBlueprintConnectionTokenCheck, errors.Error) { + blueprint, err := GetBlueprint(blueprintId, false) + if err != nil { + return nil, err + } + var ret models.ApiBlueprintConnectionTokenCheck + for _, connection := range blueprint.Connections { + pluginName := connection.PluginName + connectionId := connection.ConnectionId + connectionTokenResult := models.ConnectionTokenCheckResult{ + PluginName: pluginName, + ConnectionID: connectionId, + Success: true, + Message: "success", + } + if err := checkConnectionToken(logger, *connection); err != nil { + connectionTokenResult.Success = false + connectionTokenResult.Message = err.Error() + } + ret = append(ret, connectionTokenResult) + } + return &ret, nil +} + // GetBlueprintByProjectName returns the detail of a given ProjectName func GetBlueprintByProjectName(projectName string) (*models.Blueprint, errors.Error) { if projectName == "" { @@ -419,6 +446,11 @@ func TriggerBlueprint(id uint64, triggerSyncPolicy *models.TriggerSyncPolicy, sh } blueprint.SkipCollectors = triggerSyncPolicy.SkipCollectors blueprint.FullSync = triggerSyncPolicy.FullSync + + if err := checkBlueprintTokens(blueprint, triggerSyncPolicy); err != nil { + return nil, errors.Default.Wrap(err, "check blue print tokens") + } + pipeline, err := createPipelineByBlueprint(blueprint, &models.SyncPolicy{ SkipOnFail: false, TimeAfter: nil, @@ -434,3 +466,64 @@ func TriggerBlueprint(id uint64, triggerSyncPolicy *models.TriggerSyncPolicy, sh } return pipeline, nil } + +func needToCheckToken(triggerSyncPolicy *models.TriggerSyncPolicy) bool { + // case1: retransform + if triggerSyncPolicy.SkipCollectors && !triggerSyncPolicy.FullSync { + return false + } + // case2: collect data: triggerSyncPolicy.SkipCollectors == false && triggerSyncPolicy.FullSync == false + // case3: collect data with fullsync: triggerSyncPolicy.SkipCollectors == false && triggerSyncPolicy.FullSync == true + // case4: others + return true +} + +func checkBlueprintTokens(blueprint *models.Blueprint, triggerSyncPolicy *models.TriggerSyncPolicy) errors.Error { + if blueprint == nil { + return errors.Default.New("blueprint is nil") + } + if triggerSyncPolicy == nil { + return errors.Default.New("triggerSyncPolicy is nil") + } + + if !needToCheckToken(triggerSyncPolicy) { + return nil + } + + if len(blueprint.Connections) == 0 { + return nil + } + + g := new(errgroup.Group) + for _, connection := range blueprint.Connections { + conn := *connection + g.Go(func() error { + if err := checkConnectionToken(logger, conn); err != nil { + return err + } + return nil + }) + } + if err := g.Wait(); err != nil { + return errors.Convert(err) + } + + return nil +} + +func checkConnectionToken(logger log.Logger, connection models.BlueprintConnection) errors.Error { + pluginEntry, err := plugin.GetPlugin(connection.PluginName) + if err != nil { + return err + } + if v, ok := pluginEntry.(plugin.PluginTestConnectionAPI); ok { + if err := v.TestConnection(connection.ConnectionId); err != nil { + logger.Error(err, "plugin: %s, id: %d", connection.PluginName, connection.ConnectionId) + return err + } + return nil + } else { + msg := fmt.Sprintf("plugin: %s doesn't impl test connection api", connection.PluginName) + return errors.Default.New(msg) + } +} diff --git a/backend/server/services/blueprint_makeplan_v200.go b/backend/server/services/blueprint_makeplan_v200.go index 727e843de70..960465069bb 100644 --- a/backend/server/services/blueprint_makeplan_v200.go +++ b/backend/server/services/blueprint_makeplan_v200.go @@ -121,11 +121,25 @@ func GeneratePlanJsonV200( } } var planForProjectMapping coreModels.PipelinePlan + var planForProjectTokenChecker coreModels.PipelinePlan if projectName != "" { p, err := plugin.GetPlugin("org") if err != nil { return nil, errors.Default.Wrap(err, "get plugin org") } + if pluginBp, ok := p.(plugin.ProjectTokenChecker); ok { + var simpleConns []plugin.ProjectTokenCheckerConnection + for _, connection := range connections { + simpleConns = append(simpleConns, plugin.ProjectTokenCheckerConnection{ + PluginName: connection.PluginName, + ConnectionId: connection.ConnectionId, + }) + } + planForProjectTokenChecker, err = pluginBp.MakePipeline(skipCollectors, projectName, simpleConns) + if err != nil { + return nil, errors.Default.Wrap(err, "org token checker make pipeline") + } + } if pluginBp, ok := p.(plugin.ProjectMapper); ok { planForProjectMapping, err = pluginBp.MapProject(projectName, scopes) if err != nil { @@ -134,6 +148,7 @@ func GeneratePlanJsonV200( } } plan := SequentializePipelinePlans( + planForProjectTokenChecker, planForProjectMapping, ParallelizePipelinePlans(sourcePlans...), ParallelizePipelinePlans(metricPlans...), diff --git a/backend/server/services/project.go b/backend/server/services/project.go index 98c9600a076..614f10680ef 100644 --- a/backend/server/services/project.go +++ b/backend/server/services/project.go @@ -219,7 +219,7 @@ func PatchProject(name string, body map[string]interface{}) (*models.ApiOutputPr return nil, err } - // allowed to changed the name + // allowed to change the name if projectInput.Name == "" { projectInput.Name = name } diff --git a/backend/server/services/remote/models/plugin_remote.go b/backend/server/services/remote/models/plugin_remote.go index 98828363053..3c97d8021fb 100644 --- a/backend/server/services/remote/models/plugin_remote.go +++ b/backend/server/services/remote/models/plugin_remote.go @@ -30,4 +30,5 @@ type RemotePlugin interface { plugin.PluginModel plugin.PluginMigration plugin.PluginSource + plugin.PluginTestConnectionAPI } diff --git a/backend/server/services/remote/plugin/plugin_impl.go b/backend/server/services/remote/plugin/plugin_impl.go index 6242b160053..ea7e912c53e 100644 --- a/backend/server/services/remote/plugin/plugin_impl.go +++ b/backend/server/services/remote/plugin/plugin_impl.go @@ -230,6 +230,11 @@ func (p *remotePluginImpl) ApiResources() map[string]map[string]plugin.ApiResour return p.resources } +func (p *remotePluginImpl) TestConnection(id uint64) errors.Error { + _, err := p.resources["connections/:connectionId/test"]["POST"](api.GenerateTestingConnectionApiResourceInput(id)) + return err +} + func (p *remotePluginImpl) OpenApiSpec() string { return p.openApiSpec } diff --git a/config-ui/package.json b/config-ui/package.json index 7e1305d7240..d765f38340c 100644 --- a/config-ui/package.json +++ b/config-ui/package.json @@ -25,7 +25,7 @@ "@ant-design/icons": "^5.4.0", "@fontsource/roboto": "^5.0.14", "@mints/hooks": "^1.0.0-beta.9", - "@mints/miller-columns": "^2.0.0-beta.10", + "@mints/miller-columns": "^2.0.0-beta.11", "@mui/icons-material": "^5.16.7", "@mui/material": "^5.16.7", "@mui/styled-engine-sc": "^6.0.0-alpha.18", diff --git a/config-ui/src/api/blueprint/index.ts b/config-ui/src/api/blueprint/index.ts index 3876d3e20da..99460c088ba 100644 --- a/config-ui/src/api/blueprint/index.ts +++ b/config-ui/src/api/blueprint/index.ts @@ -43,3 +43,5 @@ type TriggerQuery = { export const trigger = (id: ID, data: TriggerQuery = { skipCollectors: false, fullSync: false }) => request(`/blueprints/${id}/trigger`, { method: 'post', data }); + +export const connectionsTokenCheck = (id: ID) => request(`/blueprints/${id}/connections-token-check`); diff --git a/config-ui/src/features/connections/index.ts b/config-ui/src/features/connections/index.ts index 8cf36b47644..513ab48a7f8 100644 --- a/config-ui/src/features/connections/index.ts +++ b/config-ui/src/features/connections/index.ts @@ -16,5 +16,4 @@ * */ -export * from './components'; export * from './slice'; diff --git a/config-ui/src/plugins/components/connection-form/connection-form-modal.tsx b/config-ui/src/plugins/components/connection-form/connection-form-modal.tsx new file mode 100644 index 00000000000..cf14c156435 --- /dev/null +++ b/config-ui/src/plugins/components/connection-form/connection-form-modal.tsx @@ -0,0 +1,56 @@ +/* + * 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. + * + */ + +import { Modal } from 'antd'; + +import { ConnectionName } from '../connection-name'; +import { ConnectionForm } from '../connection-form'; + +interface Props { + plugin: string; + connectionId?: ID; + open: boolean; + onCancel: () => void; + onSuccess?: (id: ID) => void; +} + +export const ConnectionFormModal = ({ plugin, connectionId, open, onCancel, onSuccess }: Props) => { + const handleSuccess = (id: ID) => { + onSuccess?.(id); + onCancel(); + }; + + return ( + `Manage Connections: ${pluginName}`} + /> + } + footer={null} + onCancel={() => onCancel()} + > + + + ); +}; diff --git a/config-ui/src/plugins/components/connection-form/index.tsx b/config-ui/src/plugins/components/connection-form/connection-form.tsx similarity index 100% rename from config-ui/src/plugins/components/connection-form/index.tsx rename to config-ui/src/plugins/components/connection-form/connection-form.tsx diff --git a/config-ui/src/features/connections/components/index.ts b/config-ui/src/plugins/components/connection-form/index.ts similarity index 91% rename from config-ui/src/features/connections/components/index.ts rename to config-ui/src/plugins/components/connection-form/index.ts index 113c17b4abd..14f1daa900e 100644 --- a/config-ui/src/features/connections/components/index.ts +++ b/config-ui/src/plugins/components/connection-form/index.ts @@ -16,4 +16,5 @@ * */ -export * from './name'; +export * from './connection-form-modal'; +export * from './connection-form'; diff --git a/config-ui/src/plugins/components/connection-list/index.tsx b/config-ui/src/plugins/components/connection-list/index.tsx index 4f06306397b..4ab9cd43f8b 100644 --- a/config-ui/src/plugins/components/connection-list/index.tsx +++ b/config-ui/src/plugins/components/connection-list/index.tsx @@ -16,35 +16,18 @@ * */ -import { useState, useMemo } from 'react'; +import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { EyeOutlined, EditOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'; import { theme, Table, Button, Modal, message } from 'antd'; -import styled from 'styled-components'; import { selectConnections, removeConnection } from '@/features/connections'; import { Message } from '@/components'; import { useAppDispatch, useAppSelector } from '@/hooks'; -import { getPluginConfig, ConnectionStatus, ConnectionForm } from '@/plugins'; +import { ConnectionStatus, ConnectionFormModal } from '@/plugins'; import { WebHookConnection } from '@/plugins/register/webhook'; import { operator } from '@/utils'; -const ModalTitle = styled.div` - display: flex; - align-items: center; - - .icon { - display: inline-flex; - margin-right: 8px; - width: 24px; - - & > svg { - width: 100%; - height: 100%; - } - } -`; - interface Props { plugin: string; onCreate: () => void; @@ -57,8 +40,6 @@ export const ConnectionList = ({ plugin, onCreate }: Props) => { const [conflict, setConflict] = useState([]); const [errorMsg, setErrorMsg] = useState(''); - const pluginConfig = useMemo(() => getPluginConfig(plugin), [plugin]); - const { token: { colorPrimary }, } = theme.useToken(); @@ -159,22 +140,7 @@ export const ConnectionList = ({ plugin, onCreate }: Props) => { Create a New Connection {modalType === 'update' && ( - - {pluginConfig.icon({ color: colorPrimary })} - Manage Connections: {pluginConfig.name} - - } - footer={null} - onCancel={hanldeHideModal} - > - - + )} {modalType === 'delete' && ( svg { - width: 100%; - height: 100%; - } - } - - .name { - max-width: 240px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } -`; +import * as S from './styled'; interface Props { plugin: string; - connectionId: ID; + connectionId?: ID; + customName?: (pluginName: string) => string; + onClick?: () => void; } -export const ConnectionName = ({ plugin, connectionId }: Props) => { +const Name = ({ plugin, connectionId }: Required>) => { + const connection = useAppSelector((state) => selectConnection(state, `${plugin}-${connectionId}`)); + const webhook = useAppSelector((state) => selectWebhook(state, connectionId)); + + return ( + {connection ? connection.name : webhook ? webhook.name : `${plugin}/connection/${connectionId}`} + ); +}; + +export const ConnectionName = ({ plugin, connectionId, customName, onClick }: Props) => { const { token: { colorPrimary }, } = theme.useToken(); - - const connection = useAppSelector((state) => selectConnection(state, `${plugin}-${connectionId}`)); - const webhook = useAppSelector((state) => selectWebhook(state, connectionId)); const config = getPluginConfig(plugin); - const name = connection ? connection.name : webhook ? webhook.name : `${plugin}/connection/${connectionId}`; + if (!connectionId) { + return ( + + {config.icon({ color: colorPrimary })} + {config.name} + + ); + } + + if (customName) { + return ( + + {config.icon({ color: colorPrimary })} + {customName(config.name)} + + ); + } return ( - - {config.icon({ color: colorPrimary })} - - {name} - - + + {config.icon({ color: colorPrimary })} + + ); }; diff --git a/config-ui/src/plugins/components/connection-name/styled.ts b/config-ui/src/plugins/components/connection-name/styled.ts new file mode 100644 index 00000000000..d8d2c0a44f0 --- /dev/null +++ b/config-ui/src/plugins/components/connection-name/styled.ts @@ -0,0 +1,46 @@ +/* + * 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. + * + */ + +import styled from 'styled-components'; + +export const Wrapper = styled.div` + display: flex; + align-items: center; + + span + span { + margin-left: 4px; + } +`; + +export const Icon = styled.span` + display: inline-block; + width: 24px; + height: 24px; + + & > svg { + width: 100%; + height: 100%; + } +`; + +export const Name = styled.span` + max-width: 240px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +`; diff --git a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx index 961ca68e918..73e4bc1d050 100644 --- a/config-ui/src/plugins/components/data-scope-remote/search-local.tsx +++ b/config-ui/src/plugins/components/data-scope-remote/search-local.tsx @@ -203,7 +203,16 @@ export const SearchLocal = ({ mode, plugin, connectionId, config, disabledScope, it.title.includes(searchDebounce) && !it.canExpand) : scope} + items={ + searchDebounce + ? scope + .filter((it) => it.title.includes(searchDebounce) && !it.canExpand) + .map((it) => ({ + ...it, + parentId: null, + })) + : scope + } /> )} diff --git a/config-ui/src/plugins/components/index.ts b/config-ui/src/plugins/components/index.ts index 4cbfa01e5d7..99285c8415c 100644 --- a/config-ui/src/plugins/components/index.ts +++ b/config-ui/src/plugins/components/index.ts @@ -19,6 +19,7 @@ export * from './check-matched-items'; export * from './connection-form'; export * from './connection-list'; +export * from './connection-name'; export * from './connection-select'; export * from './connection-status'; export * from './data-scope-remote'; diff --git a/config-ui/src/routes/blueprint/detail/blueprint-detail.tsx b/config-ui/src/routes/blueprint/detail/blueprint-detail.tsx index 3cc5321f97a..c46d19fd150 100644 --- a/config-ui/src/routes/blueprint/detail/blueprint-detail.tsx +++ b/config-ui/src/routes/blueprint/detail/blueprint-detail.tsx @@ -16,20 +16,39 @@ * */ -import { useEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; -import { Tabs } from 'antd'; +import { useState, useEffect, useReducer } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { WarningOutlined } from '@ant-design/icons'; +import { theme, Tabs, Modal } from 'antd'; import API from '@/api'; import { PageLoading } from '@/components'; import { useRefreshData } from '@/hooks'; +import { operator } from '@/utils'; import { FromEnum } from '../types'; +import { ConnectionCheck } from './components'; import { ConfigurationPanel } from './configuration-panel'; import { StatusPanel } from './status-panel'; import * as S from './styled'; +type ConnectionFailed = { + open: boolean; + failedList?: Array<{ plugin: string; connectionId: ID }>; +}; + +function reducer(state: ConnectionFailed, action: { type: string; failedList?: ConnectionFailed['failedList'] }) { + switch (action.type) { + case 'open': + return { open: true, failedList: action.failedList }; + case 'close': + return { open: false, failedList: [] }; + default: + return state; + } +} + interface Props { id: ID; from: FromEnum; @@ -38,8 +57,18 @@ interface Props { export const BlueprintDetail = ({ id, from }: Props) => { const [version, setVersion] = useState(1); const [activeKey, setActiveKey] = useState('status'); + const [operating, setOperating] = useState(false); + + const [{ open, failedList }, dispatch] = useReducer(reducer, { + open: false, + }); const { state } = useLocation(); + const navigate = useNavigate(); + + const { + token: { orange5 }, + } = theme.useToken(); useEffect(() => { setActiveKey(state?.activeKey ?? 'status'); @@ -50,12 +79,71 @@ export const BlueprintDetail = ({ id, from }: Props) => { return [bpRes, pipelineRes.pipelines[0]]; }, [version]); - const handlRefresh = () => { - setVersion((v) => v + 1); + const handleDelete = async () => { + const [success] = await operator(() => API.blueprint.remove(blueprint.id), { + setOperating, + formatMessage: () => 'Delete blueprint successful.', + }); + + if (success) { + navigate('/advanced/blueprints'); + } }; - const handleChangeActiveKey = (activeKey: string) => { - setActiveKey(activeKey); + const handleUpdate = async (payload: any) => { + const [success] = await operator( + () => + API.blueprint.update(blueprint.id, { + ...blueprint, + ...payload, + }), + { + setOperating, + formatMessage: () => + from === FromEnum.project ? 'Update project successful.' : 'Update blueprint successful.', + }, + ); + + if (success) { + setVersion((v) => v + 1); + } + }; + + const handleTrigger = async (payload?: { skipCollectors?: boolean; fullSync?: boolean }) => { + const { skipCollectors, fullSync } = payload ?? { skipCollectors: false, fullSync: false }; + + if (!skipCollectors) { + const [success, res] = await operator(() => API.blueprint.connectionsTokenCheck(blueprint.id), { + hideToast: true, + setOperating, + }); + + if (success && res.length) { + const connectionFailed = res + .filter((it: any) => !it.success) + .map((it: any) => { + return { + plugin: it.pluginName, + connectionId: it.connectionId, + }; + }); + + if (connectionFailed.length) { + dispatch({ type: 'open', failedList: connectionFailed }); + return; + } + } + } + + const [success] = await operator(() => API.blueprint.trigger(blueprint.id, { skipCollectors, fullSync }), { + setOperating, + formatMessage: () => 'Trigger blueprint successful.', + }); + + if (success) { + setVersion((v) => v + 1); + setActiveKey('status'); + } }; if (!ready || !data) { @@ -72,7 +160,15 @@ export const BlueprintDetail = ({ id, from }: Props) => { key: 'status', label: 'Status', children: ( - + ), }, { @@ -82,15 +178,37 @@ export const BlueprintDetail = ({ id, from }: Props) => { ), }, ]} activeKey={activeKey} - onChange={handleChangeActiveKey} + onChange={setActiveKey} /> + + + Invalid Token(s) Detected + + } + width={820} + footer={null} + onCancel={() => dispatch({ type: 'close' })} + > +

There are invalid tokens in the following connections. Please update them before re-syncing the data.

+
    + {(failedList ?? []).map(({ plugin, connectionId }) => ( +
  • + +
  • + ))} +
+
); }; diff --git a/config-ui/src/routes/blueprint/detail/components/connection-check/index.tsx b/config-ui/src/routes/blueprint/detail/components/connection-check/index.tsx new file mode 100644 index 00000000000..4ab322c5ae2 --- /dev/null +++ b/config-ui/src/routes/blueprint/detail/components/connection-check/index.tsx @@ -0,0 +1,39 @@ +/* + * 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. + * + */ + +import { useState } from 'react'; +import { Flex } from 'antd'; + +import { ConnectionName, ConnectionFormModal } from '@/plugins'; + +interface Props { + plugin: string; + connectionId: ID; +} + +export const ConnectionCheck = ({ plugin, connectionId }: Props) => { + const [open, setOpen] = useState(false); + + return ( + + - + setOpen(true)} /> + setOpen(false)} /> + + ); +}; diff --git a/config-ui/src/routes/blueprint/detail/components/index.ts b/config-ui/src/routes/blueprint/detail/components/index.ts index ab8f3f607d0..5ce0fcf9802 100644 --- a/config-ui/src/routes/blueprint/detail/components/index.ts +++ b/config-ui/src/routes/blueprint/detail/components/index.ts @@ -18,4 +18,5 @@ export * from './add-connection-dialog'; export * from './advanced-editor'; +export * from './connection-check'; export * from './update-policy-dialog'; diff --git a/config-ui/src/routes/blueprint/detail/configuration-panel.tsx b/config-ui/src/routes/blueprint/detail/configuration-panel.tsx index 479214d1401..095c7f0ead9 100644 --- a/config-ui/src/routes/blueprint/detail/configuration-panel.tsx +++ b/config-ui/src/routes/blueprint/detail/configuration-panel.tsx @@ -21,13 +21,11 @@ import { Link } from 'react-router-dom'; import { FormOutlined, PlusOutlined } from '@ant-design/icons'; import { Flex, Table, Button } from 'antd'; -import API from '@/api'; import { NoData } from '@/components'; import { getCron } from '@/config'; -import { ConnectionName } from '@/features/connections'; -import { getPluginConfig } from '@/plugins'; +import { getPluginConfig, ConnectionName } from '@/plugins'; import { IBlueprint, IBPMode } from '@/types'; -import { formatTime, operator } from '@/utils'; +import { formatTime } from '@/utils'; import { FromEnum } from '../types'; import { validRawPlan } from '../utils'; @@ -38,14 +36,14 @@ import * as S from './styled'; interface Props { from: FromEnum; blueprint: IBlueprint; - onRefresh: () => void; - onChangeTab: (tab: string) => void; + operating: boolean; + onUpdate: (payload: any) => void; + onTrigger: (payload?: { skipCollectors?: boolean; fullSync?: boolean }) => void; } -export const ConfigurationPanel = ({ from, blueprint, onRefresh, onChangeTab }: Props) => { +export const ConfigurationPanel = ({ from, blueprint, operating, onUpdate, onTrigger }: Props) => { const [type, setType] = useState<'policy' | 'add-connection'>(); const [rawPlan, setRawPlan] = useState(''); - const [operating, setOperating] = useState(false); useEffect(() => { setRawPlan(JSON.stringify(blueprint.plan, null, ' ')); @@ -80,41 +78,6 @@ export const ConfigurationPanel = ({ from, blueprint, onRefresh, onChangeTab }: setType('add-connection'); }; - const handleUpdate = async (payload: any) => { - const [success] = await operator( - () => - API.blueprint.update(blueprint.id, { - ...blueprint, - ...payload, - }), - { - setOperating, - formatMessage: () => - from === FromEnum.project ? 'Update project successful.' : 'Update blueprint successful.', - }, - ); - - if (success) { - onRefresh(); - handleCancel(); - } - }; - - const handleRun = async () => { - const [success] = await operator( - () => API.blueprint.trigger(blueprint.id, { skipCollectors: false, fullSync: false }), - { - setOperating, - formatMessage: () => 'Trigger blueprint successful.', - }, - ); - - if (success) { - onRefresh(); - onChangeTab('status'); - } - }; - return (
@@ -213,7 +176,7 @@ export const ConfigurationPanel = ({ from, blueprint, onRefresh, onChangeTab }: ))} - @@ -229,7 +192,7 @@ export const ConfigurationPanel = ({ from, blueprint, onRefresh, onChangeTab }: - - handleUpdate({ enable })} + onChange={(enable) => onUpdate({ enable })} /> Blueprint Enabled @@ -221,7 +173,7 @@ export const StatusPanel = ({ from, blueprint, pipelineId, onRefresh }: Props) = loading: operating, }} onCancel={handleResetType} - onOk={handleDelete} + onOk={onDelete} > diff --git a/config-ui/src/routes/blueprint/home/index.tsx b/config-ui/src/routes/blueprint/home/index.tsx index f8f3c2a44cf..82876123ba7 100644 --- a/config-ui/src/routes/blueprint/home/index.tsx +++ b/config-ui/src/routes/blueprint/home/index.tsx @@ -25,8 +25,8 @@ import dayjs from 'dayjs'; import API from '@/api'; import { PageHeader, Block, TextTooltip, IconButton } from '@/components'; import { getCronOptions, cronPresets, getCron } from '@/config'; -import { ConnectionName } from '@/features/connections'; import { useRefreshData } from '@/hooks'; +import { ConnectionName } from '@/plugins'; import { IBlueprint, IBPMode } from '@/types'; import { formatTime, operator } from '@/utils'; diff --git a/config-ui/src/routes/connection/connection.tsx b/config-ui/src/routes/connection/connection.tsx index 4670a1839a1..61bdfac79c2 100644 --- a/config-ui/src/routes/connection/connection.tsx +++ b/config-ui/src/routes/connection/connection.tsx @@ -28,6 +28,7 @@ import { selectConnection } from '@/features/connections'; import { useAppSelector, useRefreshData } from '@/hooks'; import { ConnectionStatus, + ConnectionName, DataScopeRemote, getPluginConfig, getPluginScopeId, @@ -37,8 +38,6 @@ import { import { IConnection } from '@/types'; import { operator } from '@/utils'; -import * as S from './styled'; - const brandName = import.meta.env.DEVLAKE_BRAND_NAME ?? 'DevLake'; export const Connection = () => { @@ -312,12 +311,7 @@ export const Connection = () => { centered style={{ width: 820 }} footer={null} - title={ - - {pluginConfig.icon({ color: colorPrimary })} - Add Data Scope: {name} - - } + title={ `Add Data Scope`} />} onCancel={handleHideDialog} > { centered footer={null} title={ - - {pluginConfig.icon({ color: colorPrimary })} - Associate Scope Config - + `Associate Scope Config`} /> } onCancel={handleHideDialog} > diff --git a/config-ui/src/routes/connection/connections.tsx b/config-ui/src/routes/connection/connections.tsx index 1148d994a9d..5cd68006a6f 100644 --- a/config-ui/src/routes/connection/connections.tsx +++ b/config-ui/src/routes/connection/connections.tsx @@ -23,7 +23,7 @@ import { chunk } from 'lodash'; import { selectPlugins, selectAllConnections, selectWebhooks } from '@/features/connections'; import { useAppSelector } from '@/hooks'; -import { getPluginConfig, ConnectionList, ConnectionForm } from '@/plugins'; +import { getPluginConfig, ConnectionName, ConnectionList, ConnectionFormModal } from '@/plugins'; import * as S from './styled'; @@ -155,12 +155,7 @@ export const Connections = () => { open width={820} centered - title={ - - {pluginConfig.icon({ color: colorPrimary })} - Manage Connections: {pluginConfig.name} - - } + title={ `Manage Connections: ${pluginName}`} />} footer={null} onCancel={handleHideDialog} > @@ -168,24 +163,12 @@ export const Connections = () => { )} {type === 'form' && pluginConfig && ( - - {pluginConfig.icon({ color: colorPrimary })} - Manage Connections: {pluginConfig.name} - - } - footer={null} onCancel={handleHideDialog} - > - handleSuccessAfter(pluginConfig.plugin, id)} - /> - + onSuccess={(id) => handleSuccessAfter(pluginConfig.plugin, id)} + /> )} ); diff --git a/config-ui/src/routes/connection/styled.ts b/config-ui/src/routes/connection/styled.ts index 6aa45c94808..066113c3a9c 100644 --- a/config-ui/src/routes/connection/styled.ts +++ b/config-ui/src/routes/connection/styled.ts @@ -111,19 +111,3 @@ export const Wrapper = styled.div<{ theme: string }>` } } `; - -export const ModalTitle = styled.div` - display: flex; - align-items: center; - - .icon { - display: inline-flex; - margin-right: 8px; - width: 24px; - - & > svg { - width: 100%; - height: 100%; - } - } -`; diff --git a/config-ui/src/routes/project/home/index.tsx b/config-ui/src/routes/project/home/index.tsx index 60ea6abf56e..eac2c22e68b 100644 --- a/config-ui/src/routes/project/home/index.tsx +++ b/config-ui/src/routes/project/home/index.tsx @@ -24,11 +24,11 @@ import { Flex, Table, Button, Modal, Input } from 'antd'; import API from '@/api'; import { PageHeader, Block, IconButton } from '@/components'; import { getCron } from '@/config'; -import { ConnectionName } from '@/features/connections'; import { useRefreshData } from '@/hooks'; import { OnboardTour } from '@/routes/onboard/components'; import { formatTime, operator } from '@/utils'; import { PipelineStatus } from '@/routes/pipeline'; +import { ConnectionName } from '@/plugins'; import { IBlueprint } from '@/types'; export const ProjectHomePage = () => { diff --git a/config-ui/yarn.lock b/config-ui/yarn.lock index c7db434e486..ca316b4a431 100644 --- a/config-ui/yarn.lock +++ b/config-ui/yarn.lock @@ -2087,9 +2087,9 @@ __metadata: languageName: node linkType: hard -"@mints/miller-columns@npm:^2.0.0-beta.10": - version: 2.0.0-beta.10 - resolution: "@mints/miller-columns@npm:2.0.0-beta.10" +"@mints/miller-columns@npm:^2.0.0-beta.11": + version: 2.0.0-beta.11 + resolution: "@mints/miller-columns@npm:2.0.0-beta.11" dependencies: "@fontsource/roboto": ^5.0.14 "@mui/material": ^5.16.7 @@ -2108,7 +2108,7 @@ __metadata: react-dom: ^18.2.0 react-infinite-scroll-component: ^6.1.0 styled-components: ^6.1.12 - checksum: 94c3ba41210f2ccbddc413ef6c26e5615f11c5a3aac7954484d838d1b05713543def70b6714e79cfc396efea522f553b2d648b36af994bf66456a440836a1386 + checksum: a2408f665aae4f037c265b18cac976b7b77ec2216e93ae24fdb8f77603ff7411efbb5398f30a6a1128e2df4e31b8ebb3b99efb9a0f2f502fec96394bde1f2259 languageName: node linkType: hard @@ -3911,7 +3911,7 @@ __metadata: "@ant-design/icons": ^5.4.0 "@fontsource/roboto": ^5.0.14 "@mints/hooks": ^1.0.0-beta.9 - "@mints/miller-columns": ^2.0.0-beta.10 + "@mints/miller-columns": ^2.0.0-beta.11 "@mui/icons-material": ^5.16.7 "@mui/material": ^5.16.7 "@mui/styled-engine-sc": ^6.0.0-alpha.18 From 95734dea8a79d6daa4ec501faad2eac5b57e5495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Mon, 30 Sep 2024 21:20:10 +1300 Subject: [PATCH 29/32] fix: limit the wrapper width to 960 (#8120) --- config-ui/src/routes/layout/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-ui/src/routes/layout/layout.tsx b/config-ui/src/routes/layout/layout.tsx index 9e5b519f2f3..2591722f5b5 100644 --- a/config-ui/src/routes/layout/layout.tsx +++ b/config-ui/src/routes/layout/layout.tsx @@ -126,7 +126,7 @@ export const Layout = () => { ))} -
+
From 94fb75fa02264418dff2064ac250dcd47152a150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Mon, 30 Sep 2024 21:20:31 +1300 Subject: [PATCH 30/32] fix: rewriting to remove warnings (#8119) --- config-ui/{.eslintrc.js => .eslintrc.cjs} | 0 config-ui/{.prettierrc.js => .prettierrc.cjs} | 0 config-ui/README.md | 1 + config-ui/package.json | 1 + config-ui/public/onboard/step-1/github.md | 2 +- config-ui/public/onboard/step-3/azuredevops.md | 2 +- config-ui/src/index.css | 3 +-- config-ui/src/main.tsx | 7 ++++--- .../src/plugins/components/scope-config-form/index.tsx | 2 +- 9 files changed, 10 insertions(+), 8 deletions(-) rename config-ui/{.eslintrc.js => .eslintrc.cjs} (100%) rename config-ui/{.prettierrc.js => .prettierrc.cjs} (100%) diff --git a/config-ui/.eslintrc.js b/config-ui/.eslintrc.cjs similarity index 100% rename from config-ui/.eslintrc.js rename to config-ui/.eslintrc.cjs diff --git a/config-ui/.prettierrc.js b/config-ui/.prettierrc.cjs similarity index 100% rename from config-ui/.prettierrc.js rename to config-ui/.prettierrc.cjs diff --git a/config-ui/README.md b/config-ui/README.md index e1a4d3e851f..6171b21f9ac 100644 --- a/config-ui/README.md +++ b/config-ui/README.md @@ -14,6 +14,7 @@ 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. --> + # DevLake - Configuration UI The **Config-UI Application** is a **React.js** SPA (Single-Page-Application) that manages the setup and configuration of a **DevLake** Instance. diff --git a/config-ui/package.json b/config-ui/package.json index d765f38340c..9a69135161b 100644 --- a/config-ui/package.json +++ b/config-ui/package.json @@ -3,6 +3,7 @@ "private": true, "version": "0.0.0", "packageManager": "yarn@3.4.1", + "type": "module", "scripts": { "start": "vite", "build": "vite build", diff --git a/config-ui/public/onboard/step-1/github.md b/config-ui/public/onboard/step-1/github.md index 7ce5e9d8166..e08d8ad9258 100644 --- a/config-ui/public/onboard/step-1/github.md +++ b/config-ui/public/onboard/step-1/github.md @@ -22,7 +22,7 @@ limitations under the License. ![1](/onboard/assets/github/1.png) 2. What is the turnaround time for your Code Review process? - + ![2](/onboard/assets/github/2.png) 3. How effective is your CI/CD pipeline? diff --git a/config-ui/public/onboard/step-3/azuredevops.md b/config-ui/public/onboard/step-3/azuredevops.md index 8a17a63c77a..90dee2b01b8 100644 --- a/config-ui/public/onboard/step-3/azuredevops.md +++ b/config-ui/public/onboard/step-3/azuredevops.md @@ -31,4 +31,4 @@ Yes, data transformations can be applied by setting up a Scope Config for the se ##### Q4. How often is the data synchronized? -Data synchronization occurs daily. This frequency can be modified on the project details page as needed. \ No newline at end of file +Data synchronization occurs daily. This frequency can be modified on the project details page as needed. diff --git a/config-ui/src/index.css b/config-ui/src/index.css index a2d32515dd1..6ddcf4c6416 100644 --- a/config-ui/src/index.css +++ b/config-ui/src/index.css @@ -71,7 +71,6 @@ p { height: 100vh; } - .ant-tour-title { padding-right: 28px; -} \ No newline at end of file +} diff --git a/config-ui/src/main.tsx b/config-ui/src/main.tsx index d3b35c690ac..d463e53cbd3 100644 --- a/config-ui/src/main.tsx +++ b/config-ui/src/main.tsx @@ -16,7 +16,7 @@ * */ -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; import { RouterProvider } from 'react-router-dom'; import { ConfigProvider } from 'antd'; @@ -27,7 +27,9 @@ import { store } from './app/store'; import { router } from './app/routrer'; import './index.css'; -ReactDOM.render( +const root = createRoot(document.getElementById('root') as HTMLElement); + +root.render( } /> , - document.getElementById('root'), ); diff --git a/config-ui/src/plugins/components/scope-config-form/index.tsx b/config-ui/src/plugins/components/scope-config-form/index.tsx index d4f4c04f49e..9a954c18895 100644 --- a/config-ui/src/plugins/components/scope-config-form/index.tsx +++ b/config-ui/src/plugins/components/scope-config-form/index.tsx @@ -150,7 +150,7 @@ export const ScopeConfigForm = ({ title="Data Entities" description={ <> - Select the data entities you wish to collect for the Data Scope. + Select the data entities you wish to collect for the Data Scope. Learn about data entities } From 88a26a2db0fb47d66ec89433793fcf6d268047b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Tue, 8 Oct 2024 22:35:31 +1300 Subject: [PATCH 31/32] feat: adjust the menu (#8133) --- config-ui/src/app/routrer.tsx | 23 ++--------------------- config-ui/src/routes/layout/config.tsx | 12 +++--------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/config-ui/src/app/routrer.tsx b/config-ui/src/app/routrer.tsx index f59b0a58a97..2ee79bfb919 100644 --- a/config-ui/src/app/routrer.tsx +++ b/config-ui/src/app/routrer.tsx @@ -30,11 +30,8 @@ import { ProjectGeneralSettings, ProjectWebhook, ProjectAdditionalSettings, - BlueprintHomePage, - BlueprintDetailPage, BlueprintConnectionDetailPage, Pipelines, - Pipeline, ApiKeys, NotFound, } from '@/routes'; @@ -112,31 +109,15 @@ export const router = createBrowserRouter( path: 'advanced', children: [ { - path: 'blueprints', - element: , - }, - { - path: 'blueprints/:id', - element: , - }, - { - path: 'blueprints/:bid/:unique', - element: , + path: 'keys', + element: , }, { path: 'pipelines', element: , }, - { - path: 'pipeline/:id', - element: , - }, ], }, - { - path: 'keys', - element: , - }, ], }, ], diff --git a/config-ui/src/routes/layout/config.tsx b/config-ui/src/routes/layout/config.tsx index 8e2b9a6d247..069798c1dcb 100644 --- a/config-ui/src/routes/layout/config.tsx +++ b/config-ui/src/routes/layout/config.tsx @@ -20,7 +20,6 @@ import { AppstoreOutlined, ProjectOutlined, ExperimentOutlined, - KeyOutlined, DashboardOutlined, FileSearchOutlined, ApiOutlined, @@ -54,20 +53,15 @@ export const menuItems: MenuItem[] = [ icon: , children: [ { - key: '/advanced/blueprints', - label: 'Blueprints', + key: '/advanced/keys', + label: 'API Keys', }, { key: '/advanced/pipelines', - label: 'Pipelines', + label: 'Pipeline Results', }, ], }, - { - key: '/keys', - label: 'API Keys', - icon: , - }, ]; const getMenuMatchs = (items: MenuItem[], parentKey?: string) => { From 0b8c8ea251917e6d04c1b168dd91f4a8fa0dc716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E6=B9=9B?= <0x1304570@gmail.com> Date: Tue, 8 Oct 2024 22:35:54 +1300 Subject: [PATCH 32/32] refactor: remove the environment variable copyright hide (#8134) --- config-ui/env.example | 1 - config-ui/src/routes/layout/layout.tsx | 26 ++++++++++---------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/config-ui/env.example b/config-ui/env.example index 078e902a541..723a06fd3b5 100644 --- a/config-ui/env.example +++ b/config-ui/env.example @@ -19,7 +19,6 @@ # DEVLAKE_PATH_PREFIX= # DEVLAKE_TITLE_CUSTOM= # DEVLAKE_COLOR_CUSTOM= -# DEVLAKE_COPYRIGHT_HIDE= # All plugins are loaded by default, optional plugins can be loaded # eg. DEVLAKE_PLUGINS=github,gitlab diff --git a/config-ui/src/routes/layout/layout.tsx b/config-ui/src/routes/layout/layout.tsx index 2591722f5b5..b33b563ed17 100644 --- a/config-ui/src/routes/layout/layout.tsx +++ b/config-ui/src/routes/layout/layout.tsx @@ -113,28 +113,22 @@ export const Layout = () => { background: 'transparent', }} > - {headerItems - .filter((item) => - import.meta.env.DEVLAKE_COPYRIGHT_HIDE ? !['Dashboards', 'GitHub', 'Slack'].includes(item.label) : true, - ) - .map((item, i, arr) => ( - - {item.icon} - {item.label} - {i !== arr.length - 1 && } - - ))} + {headerItems.map((item, i, arr) => ( + + {item.icon} + {item.label} + {i !== arr.length - 1 && } + + ))}
- {!import.meta.env.DEVLAKE_COPYRIGHT_HIDE && ( -
-

Apache 2.0 License

-
- )} +