Skip to content

Commit fdaf4f2

Browse files
authored
[tool-162]-Added filling user junk dimension (#345)
* Added filling user junk dimension * Removed console.logs * Fixed lint * Removed unneeded argument * Replaced if-else with switch-case * Fixed Zod Error * Fixed typo
1 parent 91f6516 commit fdaf4f2

File tree

2 files changed

+90
-20
lines changed

2 files changed

+90
-20
lines changed

packages/functions/transform/src/merge-request-metrics.ts

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,74 @@ type MapUsersToJunksArgs = {
282282
reviewers: transform.ForgeUser['id'][]
283283
}
284284

285+
function addUnique(newElement: number, currentArray: number[]) {
286+
if (!currentArray.includes(newElement)) {
287+
currentArray.push(newElement);
288+
}
289+
}
290+
291+
async function getId(actorId: number, db: TransformDatabase) {
292+
return await db.select({
293+
id: transform.forgeUsers.id,
294+
}).from(transform.forgeUsers)
295+
.where(eq(transform.forgeUsers.externalId, actorId)).get();
296+
}
297+
298+
async function getUserIds(timelineEvents: TimelineEventData[], extractDb: ExtractDatabase, transformDb: TransformDatabase) {
299+
const reviewers: number[] = [];
300+
const approvers: number[] = [];
301+
const committers: number[] = [];
302+
let mergedBy;
303+
304+
for (const timelineEvent of timelineEvents) {
305+
switch (timelineEvent.type) {
306+
case 'reviewed':
307+
if (!timelineEvent.actorId) {
308+
break;
309+
}
310+
const reviewer = await getId(timelineEvent.actorId, transformDb);
311+
if (reviewer) {
312+
addUnique(reviewer.id, reviewers);
313+
if (timelineEvent.data && ((timelineEvent.data as extract.ReviewedEvent).state === 'approved')) {
314+
addUnique(reviewer?.id, approvers);
315+
}
316+
}
317+
break;
318+
case 'committed':
319+
const data = timelineEvent.data as extract.CommittedEvent;
320+
const extractUserExternalId = await extractDb.select({
321+
id: extract.members.externalId,
322+
}).from(extract.members)
323+
.where(or(
324+
eq(extract.members.username, data.committerName),
325+
eq(extract.members.name, data.committerName))
326+
).get();
327+
if (extractUserExternalId) {
328+
const committer = await getId(extractUserExternalId.id, transformDb);
329+
if (committer) {
330+
addUnique(committer.id, committers);
331+
}
332+
}
333+
break;
334+
case 'merged':
335+
if (!timelineEvent.actorId) {
336+
break;
337+
}
338+
mergedBy = await getId(timelineEvent.actorId, transformDb);
339+
break;
340+
default:
341+
break;
342+
}
343+
}
344+
345+
return {
346+
mergedBy: mergedBy?.id,
347+
approvers,
348+
committers,
349+
reviewers,
350+
};
351+
}
352+
285353
function mapUsersToJunk({ author, mergedBy, approvers, committers, reviewers }: MapUsersToJunksArgs, nullForgeUserId: number) {
286354
return {
287355
author: author || nullForgeUserId,
@@ -475,12 +543,12 @@ type calcTimelineArgs = {
475543
}
476544

477545
export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap: Map<TimelineMapKey, MergeRequestNoteData | TimelineEventData>, { authorExternalId }: calcTimelineArgs) {
546+
547+
const committedEvents = timelineMapKeys.filter(key => key.type === 'committed');
548+
committedEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
478549

479-
const commitedEvents = timelineMapKeys.filter(key => key.type === 'committed');
480-
commitedEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
481-
482-
const firstCommitEvent = commitedEvents[0] || null;
483-
const lastCommitEvent = commitedEvents[commitedEvents.length - 1] || null;
550+
const firstCommitEvent = committedEvents[0] || null;
551+
const lastCommitEvent = committedEvents[committedEvents.length - 1] || null;
484552

485553
const startedCodingAt = firstCommitEvent ? firstCommitEvent.timestamp : null;
486554

@@ -503,7 +571,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
503571
reviewedEventsBeforeLastCommitEvent.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
504572
const firstReviewedEventBeforeLastCommitEvent = reviewedEventsBeforeLastCommitEvent[0];
505573
if (firstReviewedEventBeforeLastCommitEvent) {
506-
return [...commitedEvents].reverse().find(event => event.timestamp < firstReviewedEventBeforeLastCommitEvent.timestamp)?.timestamp || null;
574+
return [...committedEvents].reverse().find(event => event.timestamp < firstReviewedEventBeforeLastCommitEvent.timestamp)?.timestamp || null;
507575
}
508576

509577
return lastCommitEvent.timestamp;
@@ -520,7 +588,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
520588
const firstReviewedEventAfterLastReadyForReviewEvent = reviewedEventsAfterLastReadyForReviewEvent[0]
521589

522590
if (firstReviewedEventAfterLastReadyForReviewEvent) {
523-
const temp = [...commitedEvents].reverse().find(
591+
const temp = [...committedEvents].reverse().find(
524592
event => event.timestamp > lastReadyForReviewEvent.timestamp
525593
&& event.timestamp < firstReviewedEventAfterLastReadyForReviewEvent.timestamp
526594

@@ -610,7 +678,7 @@ function runTimeline(mergeRequestData: MergeRequestData, timelineEvents: Timelin
610678
});
611679

612680
// TODO: can this be optimized with the map ?
613-
const approved = timelineEvents.find(ev => ev.type === 'reviewed' && (JSON.parse(ev.data as string) as extract.ReviewedEvent).state === 'approved') !== undefined;
681+
const approved = timelineEvents.find(ev => ev.type === 'reviewed' && (ev.data as extract.ReviewedEvent).state === 'approved') !== undefined;
614682

615683
return {
616684
startedCodingAt,
@@ -643,6 +711,8 @@ export async function run(extractMergeRequestId: number, ctx: RunContext) {
643711

644712
const timeline = runTimeline(extractData.mergeRequest, extractData.timelineEvents, extractData.notes);
645713

714+
const users = await getUserIds(extractData.timelineEvents, ctx.extractDatabase, ctx.transformDatabase);
715+
646716
const {
647717
dateId: nullDateId,
648718
userId: nullUserId,
@@ -672,10 +742,10 @@ export async function run(extractMergeRequestId: number, ctx: RunContext) {
672742
eq(transform.forgeUsers.externalId, extractData.mergeRequest.authorExternalId || 0),
673743
eq(transform.forgeUsers.forgeType, extractData.repository.forgeType),
674744
)).get())?.id || null, // TODO: ???
675-
mergedBy: null,
676-
approvers: [],
677-
committers: [],
678-
reviewers: [],
745+
mergedBy: users.mergedBy,
746+
approvers: users.approvers,
747+
committers: users.committers,
748+
reviewers: users.reviewers,
679749
}, nullUserId);
680750

681751
const { id: transformRepositoryId } = await upsertRepository(ctx.transformDatabase, extractData.repository).get();

packages/integrations/source-control/src/github/index.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,10 @@ export class GitHubSourceControl implements SourceControl {
366366
timestamp: new Date(assignedEvent.created_at),
367367
actorName: assignedEvent.actor.login,
368368
actorId: assignedEvent.actor.id,
369-
data: JSON.stringify({
369+
data: {
370370
assigneeId: assignedEvent.assignee.id,
371371
assigneeName: assignedEvent.assignee.login,
372-
}),
372+
},
373373
} satisfies NewTimelineEvents;
374374
case 'committed':
375375
const committedEvent = singleEvent as components["schemas"]["timeline-committed-event"]
@@ -380,11 +380,11 @@ export class GitHubSourceControl implements SourceControl {
380380
timestamp: new Date(committedEvent.author.date),
381381
actorName: committedEvent.author.name,
382382
actorEmail: committedEvent.author.email,
383-
data: JSON.stringify({
383+
data: {
384384
committerEmail: committedEvent.committer.email,
385385
committerName: committedEvent.committer.name,
386386
committedDate: new Date(committedEvent.committer.date),
387-
}),
387+
},
388388
} satisfies NewTimelineEvents;
389389
case 'review_requested':
390390
case 'review_request_removed':
@@ -396,10 +396,10 @@ export class GitHubSourceControl implements SourceControl {
396396
timestamp: new Date(requestedEvent.created_at),
397397
actorName: requestedEvent.actor.login,
398398
actorId: requestedEvent.actor.id,
399-
data: JSON.stringify({
399+
data: {
400400
requestedReviewerId: requestedEvent.requested_reviewer?.id,
401401
requestedReviewerName: requestedEvent.requested_reviewer?.login,
402-
}),
402+
},
403403
} satisfies NewTimelineEvents;
404404
case 'reviewed':
405405
const reviewedEvent = singleEvent as components["schemas"]["timeline-reviewed-event"]
@@ -410,9 +410,9 @@ export class GitHubSourceControl implements SourceControl {
410410
timestamp: new Date(reviewedEvent.submitted_at as string),
411411
actorName: reviewedEvent.user.login,
412412
actorId: reviewedEvent.user.id,
413-
data: JSON.stringify({
413+
data: {
414414
state: reviewedEvent.state,
415-
}),
415+
},
416416
} satisfies NewTimelineEvents;
417417
default:
418418
const generalEvent = singleEvent as components["schemas"]["state-change-issue-event"];

0 commit comments

Comments
 (0)