Skip to content

Commit 8754258

Browse files
Feat/refactoring transform (#346)
* refactoring * i dunno * update tests * fix expected test results * fix tests * add sortedTimelineMapKeys --------- Co-authored-by: dejan-crocoder <dejan@crocoder.dev>
1 parent fdaf4f2 commit 8754258

File tree

2 files changed

+378
-350
lines changed

2 files changed

+378
-350
lines changed

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

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -540,25 +540,44 @@ function setupTimeline(timelineEvents: TimelineEventData[], notes: MergeRequestN
540540

541541
type calcTimelineArgs = {
542542
authorExternalId: extract.MergeRequest['authorExternalId'],
543+
createdAt: extract.MergeRequest['createdAt'] | null,
543544
}
544545

545-
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());
549546

550-
const firstCommitEvent = committedEvents[0] || null;
551-
const lastCommitEvent = committedEvents[committedEvents.length - 1] || null;
547+
function getStartedCodingAt(timelineMapKeys: TimelineMapKey[], createdAt: Date | null) {
548+
const firstCommitEvent = timelineMapKeys.find(key => key.type === 'committed');
549+
550+
if (!firstCommitEvent) return null;
551+
552+
if (!createdAt) {
553+
return firstCommitEvent.timestamp;
554+
}
555+
556+
return firstCommitEvent.timestamp < createdAt ? firstCommitEvent.timestamp : createdAt;
557+
}
552558

553-
const startedCodingAt = firstCommitEvent ? firstCommitEvent.timestamp : null;
559+
function getMergedAt(timelineMapKeys: TimelineMapKey[]) {
560+
const firstMergedEvent = timelineMapKeys.find(key => key.type === 'merged');
554561

555-
const mergedEvents = timelineMapKeys.filter(key => key.type === 'merged');
556-
mergedEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
562+
if (firstMergedEvent) {
563+
return firstMergedEvent.timestamp;
564+
}
565+
566+
return null;
567+
}
568+
569+
export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap: Map<TimelineMapKey, MergeRequestNoteData | TimelineEventData>, { authorExternalId, createdAt }: calcTimelineArgs) {
570+
571+
const sortedTimelineMapKeys = [...timelineMapKeys]
572+
sortedTimelineMapKeys.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
573+
574+
const committedEvents = sortedTimelineMapKeys.filter(key => key.type === 'committed');
575+
const lastCommitEvent = committedEvents[committedEvents.length - 1] || null;
557576

558-
const mergedAt = mergedEvents[0]?.timestamp || null;
577+
const startedCodingAt = getStartedCodingAt(committedEvents, createdAt);
578+
const mergedAt = getMergedAt(sortedTimelineMapKeys);
559579

560-
const readyForReviewEvents = timelineMapKeys.filter(key => key.type === 'ready_for_review' || key.type === 'review_requested');
561-
readyForReviewEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
580+
const readyForReviewEvents = sortedTimelineMapKeys.filter(key => key.type === 'ready_for_review' || key.type === 'review_requested');
562581
const lastReadyForReviewEvent = readyForReviewEvents[readyForReviewEvents.length - 1] || null;
563582

564583
const startedPickupAt = (() => {
@@ -567,8 +586,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
567586
}
568587
if (lastReadyForReviewEvent === null && lastCommitEvent) {
569588
// problematic code: everything below is problematic
570-
const reviewedEventsBeforeLastCommitEvent = timelineMapKeys.filter(key => key.type === 'reviewed' && key.timestamp < lastCommitEvent.timestamp);
571-
reviewedEventsBeforeLastCommitEvent.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
589+
const reviewedEventsBeforeLastCommitEvent = sortedTimelineMapKeys.filter(key => key.type === 'reviewed' && key.timestamp < lastCommitEvent.timestamp);
572590
const firstReviewedEventBeforeLastCommitEvent = reviewedEventsBeforeLastCommitEvent[0];
573591
if (firstReviewedEventBeforeLastCommitEvent) {
574592
return [...committedEvents].reverse().find(event => event.timestamp < firstReviewedEventBeforeLastCommitEvent.timestamp)?.timestamp || null;
@@ -578,13 +596,12 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
578596
}
579597
if (lastReadyForReviewEvent && lastCommitEvent) {
580598
// problematic code: there could be a commit between last commit and lastReadyForReviewEvent
581-
const reviewedEventsAfterLastReadyForReviewEvent = timelineMapKeys.filter(
599+
const reviewedEventsAfterLastReadyForReviewEvent = sortedTimelineMapKeys.filter(
582600
key =>
583601
key.type === 'reviewed'
584602
&& key.timestamp > lastReadyForReviewEvent.timestamp
585603
&& key.timestamp < lastCommitEvent.timestamp
586604
);
587-
reviewedEventsAfterLastReadyForReviewEvent.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
588605
const firstReviewedEventAfterLastReadyForReviewEvent = reviewedEventsAfterLastReadyForReviewEvent[0]
589606

590607
if (firstReviewedEventAfterLastReadyForReviewEvent) {
@@ -617,6 +634,7 @@ export function calculateTimeline(timelineMapKeys: TimelineMapKey[], timelineMap
617634
continue;
618635
}
619636

637+
// Edge-case: what if note is before first review event ?
620638
const afterStartedPickupAt = startedPickupAt ? noteEvent.timestamp > startedPickupAt : true;
621639
const beforeMergedEvent = mergedAt ? noteEvent.timestamp < mergedAt : true;
622640
const isAuthorReviewer = eventData.authorExternalId === authorExternalId;
@@ -674,6 +692,7 @@ function runTimeline(mergeRequestData: MergeRequestData, timelineEvents: Timelin
674692
timelineMapKeys,
675693
timelineMap,
676694
{
695+
createdAt: mergeRequestData.openedAt,
677696
authorExternalId: mergeRequestData.authorExternalId,
678697
});
679698

0 commit comments

Comments
 (0)