Skip to content

Commit 050ad7d

Browse files
joanagmaiaemlimlf
andauthored
chore: improve error messages (CM-855) (CM-561) (#3713)
Signed-off-by: Efren Lim <elim@linuxfoundation.org> Co-authored-by: emlimlf <52259294+emlimlf@users.noreply.github.com>
1 parent c0ecbbc commit 050ad7d

14 files changed

Lines changed: 526 additions & 84 deletions

File tree

backend/src/database/repositories/githubReposRepository.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default class GithubReposRepository {
8181
)
8282
throw new Error400(
8383
options.language,
84-
'errors.integrations.githubRepoAlreadyMapped',
84+
'errors.integrations.repoAlreadyMapped',
8585
row.url,
8686
integrationId,
8787
row.integrationId,

backend/src/database/repositories/gitlabReposRepository.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import trim from 'lodash/trim'
22
import { QueryTypes } from 'sequelize'
33

4-
import { DEFAULT_TENANT_ID } from '@crowd/common'
4+
import { DEFAULT_TENANT_ID, Error400 } from '@crowd/common'
55
import { RedisCache } from '@crowd/redis'
66

77
import { IRepositoryOptions } from './IRepositoryOptions'
@@ -51,6 +51,35 @@ export default class GitlabReposRepository {
5151
}
5252

5353
static async updateMapping(integrationId, mapping, options: IRepositoryOptions) {
54+
const transaction = SequelizeRepository.getTransaction(options)
55+
56+
// Check for repositories already mapped to other integrations
57+
for (const url of Object.keys(mapping)) {
58+
const existingRows = await options.database.sequelize.query(
59+
`SELECT * FROM "gitlabRepos" WHERE url = :url AND "deletedAt" IS NULL`,
60+
{
61+
replacements: { url },
62+
type: QueryTypes.SELECT,
63+
transaction,
64+
},
65+
)
66+
67+
for (const row of existingRows as any[]) {
68+
if (!row.deletedAt && row.integrationId !== integrationId) {
69+
options.log.warn(
70+
`Trying to update gitlab repo ${row.url} mapping with integrationId ${integrationId} but it is already mapped to integration ${row.integrationId}!`,
71+
)
72+
73+
throw new Error400(
74+
options.language,
75+
'errors.integrations.repoAlreadyMapped',
76+
row.url,
77+
integrationId,
78+
row.integrationId,
79+
)
80+
}
81+
}
82+
}
5483
await GitlabReposRepository.bulkInsert(
5584
'gitlabRepos',
5685
['tenantId', 'integrationId', 'segmentId', 'url'],

backend/src/database/repositories/segmentRepository.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,35 @@ class SegmentRepository extends RepositoryBase<
401401
return this.findById(records[0].id)
402402
}
403403

404+
async findByName(name: string, level: SegmentLevel) {
405+
const transaction = this.transaction
406+
407+
let findByNameQuery = `SELECT * FROM segments WHERE name = :name AND "tenantId" = :tenantId`
408+
409+
if (level === SegmentLevel.SUB_PROJECT) {
410+
findByNameQuery += ` and "parentSlug" is not null and "grandparentSlug" is not null`
411+
} else if (level === SegmentLevel.PROJECT) {
412+
findByNameQuery += ` and "parentSlug" is not null and "grandparentSlug" is null`
413+
} else if (level === SegmentLevel.PROJECT_GROUP) {
414+
findByNameQuery += ` and "parentSlug" is null and "grandparentSlug" is null`
415+
}
416+
417+
const records = await this.options.database.sequelize.query(findByNameQuery, {
418+
replacements: {
419+
name,
420+
tenantId: this.options.currentTenant.id,
421+
},
422+
type: QueryTypes.SELECT,
423+
transaction,
424+
})
425+
426+
if (records.length === 0) {
427+
return null
428+
}
429+
430+
return this.findById(records[0].id)
431+
}
432+
404433
async findInIds(ids: string[]): Promise<SegmentData[]> {
405434
if (ids.length === 0) {
406435
return []

backend/src/services/integrationService.ts

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { request } from '@octokit/request'
44
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
55
import lodash from 'lodash'
66
import moment from 'moment'
7-
import { Transaction } from 'sequelize'
7+
import { QueryTypes, Transaction } from 'sequelize'
88

99
import { EDITION, Error400, Error404, Error542, encryptData } from '@crowd/common'
1010
import { CommonIntegrationService, getGithubInstallationToken } from '@crowd/common_services'
@@ -1391,6 +1391,38 @@ export default class IntegrationService {
13911391
options,
13921392
)
13931393

1394+
// Check for repositories already mapped to other integrations
1395+
const seq = SequelizeRepository.getSequelize({ ...(options || this.options), transaction })
1396+
const urls = remotes.map((r) => r.url)
1397+
1398+
const existingRows = await seq.query(
1399+
`
1400+
SELECT url, "integrationId" FROM git.repositories
1401+
WHERE url IN (:urls) AND "deletedAt" IS NULL
1402+
`,
1403+
{
1404+
replacements: { urls },
1405+
type: QueryTypes.SELECT,
1406+
transaction,
1407+
},
1408+
)
1409+
1410+
for (const row of existingRows as any[]) {
1411+
if (row.integrationId !== integration.id) {
1412+
this.options.log.warn(
1413+
`Trying to update git repo ${row.url} mapping with integrationId ${integration.id} but it is already mapped to integration ${row.integrationId}!`,
1414+
)
1415+
1416+
throw new Error400(
1417+
(options || this.options).language,
1418+
'errors.integrations.repoAlreadyMapped',
1419+
row.url,
1420+
integration.id,
1421+
row.integrationId,
1422+
)
1423+
}
1424+
}
1425+
13941426
// upsert repositories to git.repositories in order to be processed by git-integration V2
13951427
const qx = SequelizeRepository.getQueryExecutor({
13961428
...(options || this.options),
@@ -1681,6 +1713,54 @@ export default class IntegrationService {
16811713
host = orgUrl
16821714
}
16831715

1716+
const stripGit = (url: string) => {
1717+
if (url.endsWith('.git')) {
1718+
return url.slice(0, -4)
1719+
}
1720+
return url
1721+
}
1722+
1723+
// Build full repository URLs from orgURL and repo names
1724+
const remotes = integrationData.remote.repoNames.map((repoName) => {
1725+
const fullUrl = stripGit(`${integrationData.remote.orgURL}/${repoName}`)
1726+
return { url: fullUrl, forkedFrom: null }
1727+
})
1728+
1729+
// Check for conflicts with existing Gerrit integrations
1730+
for (const remote of remotes) {
1731+
const existingGerritIntegrations = await this.options.database.sequelize.query(
1732+
`SELECT id, settings FROM integrations
1733+
WHERE platform = 'gerrit' AND "deletedAt" IS NULL`,
1734+
{
1735+
type: QueryTypes.SELECT,
1736+
transaction,
1737+
},
1738+
)
1739+
1740+
for (const existingIntegration of existingGerritIntegrations as any[]) {
1741+
const settings = existingIntegration.settings
1742+
if (settings?.remote?.repoNames && settings?.remote?.orgURL) {
1743+
const existingRemotes = settings.remote.repoNames.map((repoName) =>
1744+
stripGit(`${settings.remote.orgURL}/${repoName}`),
1745+
)
1746+
1747+
if (existingRemotes.includes(remote.url)) {
1748+
this.options.log.warn(
1749+
`Trying to map Gerrit repository ${remote.url} with integrationId ${integration?.id || connectionId} but it is already mapped to integration ${existingIntegration.id}!`,
1750+
)
1751+
1752+
throw new Error400(
1753+
this.options.language,
1754+
'errors.integrations.repoAlreadyMapped',
1755+
remote.url,
1756+
integration?.id || connectionId,
1757+
existingIntegration.id,
1758+
)
1759+
}
1760+
}
1761+
}
1762+
}
1763+
16841764
const res = await IntegrationService.getGerritServerRepos(orgUrl)
16851765
if (integrationData.remote.enableAllRepos) {
16861766
integrationData.remote.repoNames = res
@@ -1711,13 +1791,6 @@ export default class IntegrationService {
17111791
)
17121792

17131793
if (integrationData.remote.enableGit) {
1714-
const stripGit = (url: string) => {
1715-
if (url.endsWith('.git')) {
1716-
return url.slice(0, -4)
1717-
}
1718-
return url
1719-
}
1720-
17211794
const segmentOptions: IRepositoryOptions = {
17221795
...this.options,
17231796
transaction,
@@ -1728,12 +1801,6 @@ export default class IntegrationService {
17281801
],
17291802
}
17301803

1731-
// Build full repository URLs from orgURL and repo names
1732-
const remotes = integrationData.remote.repoNames.map((repoName) => {
1733-
const fullUrl = stripGit(`${integrationData.remote.orgURL}/${repoName}`)
1734-
return { url: fullUrl, forkedFrom: null }
1735-
})
1736-
17371804
await this.gitConnectOrUpdate(
17381805
{
17391806
remotes,

0 commit comments

Comments
 (0)