Skip to content

Commit f582c4d

Browse files
authored
Merge pull request #580 from Kamlesh72/bug/teams-same-org
Resolved multi team similar repo issue
2 parents df80d3a + 26d4796 commit f582c4d

File tree

3 files changed

+102
-123
lines changed

3 files changed

+102
-123
lines changed

web-server/pages/api/integrations/selected.ts

Lines changed: 0 additions & 91 deletions
This file was deleted.

web-server/pages/api/resources/orgs/[org_id]/teams/v2.ts

Lines changed: 101 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
} from 'ramda';
77
import * as yup from 'yup';
88

9-
import { getSelectedReposForOrg } from '@/api/integrations/selected';
109
import { syncReposForOrg } from '@/api/internal/[org_id]/sync_repos';
1110
import {
1211
getOnBoardingState,
@@ -22,8 +21,12 @@ import {
2221
} from '@/constants/integrations';
2322
import { getTeamV2Mock } from '@/mocks/teams';
2423
import { BaseTeam } from '@/types/api/teams';
25-
import { OnboardingStep, ReqRepoWithProvider } from '@/types/resources';
26-
import { db, getFirstRow } from '@/utils/db';
24+
import {
25+
OnboardingStep,
26+
RepoWithMultipleWorkflows,
27+
ReqRepoWithProvider
28+
} from '@/types/resources';
29+
import { db, dbRaw, getFirstRow } from '@/utils/db';
2730
import groupBy from '@/utils/objectArray';
2831

2932
const repoSchema = yup.object().shape({
@@ -84,17 +87,16 @@ endpoint.handle.GET(getSchema, async (req, res) => {
8487
.orderBy('name', 'asc');
8588

8689
const teams = await getQuery;
87-
const reposWithWorkflows = await getSelectedReposForOrg(
90+
const teamReposMap = await getTeamReposMap(
8891
org_id,
8992
providers?.length
9093
? (providers as Integration[])
9194
: [Integration.GITHUB, Integration.GITLAB]
92-
).then((res) => res.flat());
95+
);
9396

9497
res.send({
9598
teams: teams,
96-
teamReposMap: ramdaGroupBy(prop('team_id'), reposWithWorkflows),
97-
reposWithWorkflows
99+
teamReposMap
98100
});
99101
});
100102

@@ -134,7 +136,7 @@ endpoint.handle.POST(postSchema, async (req, res) => {
134136

135137
const providers = Array.from(new Set(orgReposList.map((r) => r.provider)));
136138
await updateReposWorkflows(org_id, orgReposList);
137-
const reposWithWorkflows = await getSelectedReposForOrg(
139+
const teamReposMap = await getTeamReposMap(
138140
org_id,
139141
providers as Integration[]
140142
);
@@ -143,7 +145,7 @@ endpoint.handle.POST(postSchema, async (req, res) => {
143145

144146
res.send({
145147
team,
146-
teamReposMap: ramdaGroupBy(prop('team_id'), reposWithWorkflows)
148+
teamReposMap
147149
});
148150
});
149151

@@ -177,14 +179,14 @@ endpoint.handle.PATCH(patchSchema, async (req, res) => {
177179

178180
const providers = Array.from(new Set(orgReposList.map((r) => r.provider)));
179181

180-
const reposWithWorkflows = await getSelectedReposForOrg(
182+
const teamReposMap = await getTeamReposMap(
181183
org_id,
182184
providers as Integration[]
183185
);
184186
syncReposForOrg();
185187
res.send({
186188
team,
187-
teamReposMap: ramdaGroupBy(prop('team_id'), reposWithWorkflows)
189+
teamReposMap
188190
});
189191
});
190192

@@ -193,12 +195,49 @@ endpoint.handle.DELETE(deleteSchema, async (req, res) => {
193195
return res.send(getTeamV2Mock);
194196
}
195197

196-
const data = await db('Team')
197-
.update('is_deleted', true)
198-
.where('id', req.payload.id)
199-
.orderBy('name', 'asc')
200-
.returning('*')
201-
.then(getFirstRow);
198+
const data = await dbRaw.transaction(async (trx) => {
199+
const deletedTeamRow = await trx('Team')
200+
.update({
201+
is_deleted: true,
202+
updated_at: new Date()
203+
})
204+
.where('id', req.payload.id)
205+
.orderBy('name', 'asc')
206+
.returning('*')
207+
.then(getFirstRow);
208+
209+
// 1. Mark inactive and Get Repo Ids of this deleted team. Ex: [ '123', '456', '789' ]
210+
const deletedTeamRepoIds: string[] = await trx('TeamRepos')
211+
.update({
212+
is_active: false,
213+
updated_at: new Date()
214+
})
215+
.where('team_id', req.payload.id)
216+
.andWhere('is_active', true)
217+
.returning('org_repo_id')
218+
.then((result) => result.map((row) => row.org_repo_id));
219+
220+
// 2. Get Repo Ids which are still used across other teams. Ex: [ '456', '789' ]
221+
const activeRepoIds: string[] = await trx('TeamRepos')
222+
.where('is_active', true)
223+
.whereIn('org_repo_id', deletedTeamRepoIds)
224+
.distinct('org_repo_id')
225+
.then((result) => result.map((row) => row.org_repo_id));
226+
227+
// 3. Repo Ids which are nowhere used. Ex: [ '123' ]
228+
const orgRepoIdsToBeInactivate = deletedTeamRepoIds.filter(
229+
(id) => !activeRepoIds.includes(id)
230+
);
231+
232+
await trx('OrgRepo')
233+
.update({
234+
is_active: false,
235+
updated_at: new Date()
236+
})
237+
.whereIn('id', orgRepoIdsToBeInactivate);
238+
239+
return deletedTeamRow;
240+
});
202241

203242
res.send(data);
204243
});
@@ -302,3 +341,48 @@ const updateReposWorkflows = async (
302341
}
303342
}
304343
};
344+
345+
const getTeamReposMap = async (org_id: ID, providers: Integration[]) => {
346+
const baseQuery = db(Table.OrgRepo)
347+
.where('org_id', org_id)
348+
.andWhere('OrgRepo.is_active', true)
349+
.whereIn('OrgRepo.provider', providers);
350+
351+
const teamJoin = baseQuery
352+
.leftJoin({ tr: Table.TeamRepos }, 'OrgRepo.id', 'tr.org_repo_id')
353+
.andWhere('tr.is_active', true);
354+
355+
const workflowJoin = teamJoin.leftJoin(
356+
{ rw: Table.RepoWorkflow },
357+
function () {
358+
this.on('OrgRepo.id', 'rw.org_repo_id').andOn(
359+
'rw.is_active',
360+
'tr.is_active'
361+
);
362+
}
363+
);
364+
365+
const dbRepos: RepoWithMultipleWorkflows[] = await workflowJoin
366+
.select('OrgRepo.*')
367+
.select(
368+
dbRaw.raw(
369+
"COALESCE(json_agg(rw.*) FILTER (WHERE rw.id IS NOT NULL), '[]') as repo_workflows"
370+
)
371+
)
372+
.select('tr.deployment_type', 'tr.team_id')
373+
.groupBy('OrgRepo.id', 'tr.deployment_type', 'tr.team_id');
374+
375+
const repoWithWorkflows = dbRepos.map((repo) => {
376+
const updatedWorkflows = repo.repo_workflows.map((workflow) => ({
377+
name: workflow.name,
378+
value: workflow.provider_workflow_id
379+
}));
380+
381+
return {
382+
...repo,
383+
repo_workflows: updatedWorkflows
384+
};
385+
});
386+
387+
return ramdaGroupBy(prop('team_id'), repoWithWorkflows);
388+
};

web-server/src/slices/repos.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ import { Integration } from '@/constants/integrations';
88
import { RootState } from '@/store/index';
99
import { LoadedOrg } from '@/types/github';
1010
import { StateFetchConfig } from '@/types/redux';
11-
import {
12-
BaseRepo,
13-
RepoUniqueDetails,
14-
RepoWithMultipleWorkflows
15-
} from '@/types/resources';
11+
import { BaseRepo, RepoUniqueDetails } from '@/types/resources';
1612
import { addFetchCasesToReducer } from '@/utils/redux';
1713

1814
type RepoSelectionMap = Record<BaseRepo['parent'], RepoUniqueDetails[]>;
@@ -155,13 +151,3 @@ export const fetchReposForOrgFromProvider = createAsyncThunk(
155151
);
156152
}
157153
);
158-
159-
export const fetchSelectedRepos = createAsyncThunk(
160-
'repos/fetchSelectedRepos',
161-
async (params: { orgId: ID; provider: Integration }) => {
162-
return await handleApi<RepoWithMultipleWorkflows[]>(
163-
`/integrations/selected`,
164-
{ params: { org_id: params.orgId, provider: params.provider } }
165-
);
166-
}
167-
);

0 commit comments

Comments
 (0)