Skip to content

Commit a16c07d

Browse files
authored
Added actor and subject to mr event data (#375)
* Added actor and subject to mr event data * Combined two similar functions * Renamed function * Added check for duplicate elements in user query * Added committe_at value to the merge request metrics * Extracted getting committed date to separete function * Changed variable name * Removed unneeded variable
1 parent 487f491 commit a16c07d

File tree

1 file changed

+217
-8
lines changed

1 file changed

+217
-8
lines changed

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

Lines changed: 217 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as extract from '@acme/extract-schema';
22
import * as transform from '@acme/transform-schema';
3-
import { sql, eq, or, and, type ExtractTablesWithRelations, inArray } from "drizzle-orm";
3+
import { sql, eq, or, and, type ExtractTablesWithRelations, inArray, type SQL } from "drizzle-orm";
44
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
55
import { isCodeGen } from './is-codegen';
66
import { parseHunks } from './parse-hunks';
@@ -244,6 +244,35 @@ function getDateIdOrNullDateId(dmy: DMY | null, datesData: {
244244
};
245245
}
246246

247+
function getUserIdOrNullUserId(userIdentifier: string | number | null, forgeUsersData: {
248+
id: number;
249+
name: string;
250+
externalId: number;
251+
}[], nullUserId: number) {
252+
if (userIdentifier === null) {
253+
return {
254+
id: nullUserId,
255+
}
256+
}
257+
let user;
258+
if (typeof userIdentifier === 'number') {
259+
user = forgeUsersData.find(({ externalId }) => externalId === userIdentifier);
260+
} else {
261+
user = forgeUsersData.find(({ name }) => name === userIdentifier);
262+
}
263+
if (!user) {
264+
return {
265+
id: nullUserId,
266+
};
267+
}
268+
269+
return {
270+
id: user.id,
271+
name: user.name,
272+
externalId: user.externalId,
273+
};
274+
}
275+
247276
async function selectDates(db: TransformDatabase, dates: selectDatesArgs, nullDateId: number) {
248277

249278
const { dates: transformDates } = transform;
@@ -778,6 +807,153 @@ async function selectEventDates<K>(db: TransformDatabase, dates: { key: K, dmy:
778807
return dates.map(d => ({ key: d.key, dateId: getDateIdOrNullDateId(d.dmy, datesData, nullDateId) }));
779808
}
780809

810+
async function selectForgeUsers<K>(db: TransformDatabase, users: { key: K, userId: number | null, type: string, data: unknown }[], nullUserId: number, isActor: boolean) {
811+
const { forgeUsers: transformForgeUsers } = transform;
812+
const userQuery: (SQL<unknown> | undefined)[] = [];
813+
const uniqueUserQuery = new Map();
814+
815+
if (isActor) {
816+
users.forEach(u => {
817+
if (u.type === 'committed') {
818+
const committerName = (u.data as extract.CommittedEvent).committerName;
819+
if (!uniqueUserQuery.has(committerName)) {
820+
uniqueUserQuery.set(committerName, committerName);
821+
userQuery.push(eq(transformForgeUsers.name, committerName));
822+
}
823+
} else if (u.userId !== null) {
824+
if (!uniqueUserQuery.has(u.userId)) {
825+
uniqueUserQuery.set(u.userId, u.userId);
826+
userQuery.push(eq(transformForgeUsers.externalId, u.userId))
827+
}
828+
}
829+
})
830+
} else {
831+
users.forEach(u => {
832+
switch (u.type) {
833+
case 'assigned':
834+
const assigneeId = (u.data as extract.AssignedEvent).assigneeId;
835+
if (!uniqueUserQuery.has(assigneeId)) {
836+
uniqueUserQuery.set(assigneeId, assigneeId);
837+
userQuery.push(eq(transformForgeUsers.externalId, assigneeId));
838+
}
839+
break;
840+
case 'unassigned':
841+
const unassigneeId = (u.data as extract.AssignedEvent).assigneeId;
842+
if (!uniqueUserQuery.has(unassigneeId)) {
843+
uniqueUserQuery.set(unassigneeId, unassigneeId);
844+
userQuery.push(eq(transformForgeUsers.externalId, unassigneeId));
845+
}
846+
break;
847+
case 'review_requested':
848+
const requestedReviewerId = (u.data as extract.ReviewRequestedEvent).requestedReviewerId;
849+
if (!uniqueUserQuery.has(requestedReviewerId)) {
850+
uniqueUserQuery.set(requestedReviewerId, requestedReviewerId);
851+
userQuery.push(eq(transformForgeUsers.externalId, requestedReviewerId));
852+
}
853+
break;
854+
case 'review_request_removed':
855+
const requestedReviewerRemovedId = (u.data as extract.ReviewRequestedEvent).requestedReviewerId;
856+
if (!uniqueUserQuery.has(requestedReviewerRemovedId)) {
857+
uniqueUserQuery.set(requestedReviewerRemovedId, requestedReviewerRemovedId);
858+
userQuery.push(eq(transformForgeUsers.externalId, requestedReviewerRemovedId));
859+
}
860+
break;
861+
default:
862+
break;
863+
}
864+
});
865+
}
866+
867+
const forgeUsersData = await db.select({
868+
id: transformForgeUsers.id,
869+
externalId: transformForgeUsers.externalId,
870+
name: transformForgeUsers.name,
871+
}).from(transformForgeUsers)
872+
.where(
873+
or(
874+
...userQuery
875+
)
876+
)
877+
.all();
878+
879+
return users.map(u => {
880+
let userIdentifier;
881+
if (isActor) {
882+
if (u.type === 'committed') {
883+
userIdentifier = (u.data as extract.CommittedEvent).committerName;
884+
} else {
885+
userIdentifier = u.userId;
886+
}
887+
} else {
888+
switch (u.type) {
889+
case 'assigned':
890+
userIdentifier = (u.data as extract.AssignedEvent).assigneeId;
891+
break;
892+
case 'unassigned':
893+
userIdentifier = (u.data as extract.UnassignedEvent).assigneeId;
894+
break;
895+
case 'review_requested':
896+
userIdentifier = (u.data as extract.ReviewRequestedEvent).requestedReviewerId;
897+
break;
898+
case 'review_request_removed':
899+
userIdentifier = (u.data as extract.ReviewRequestRemovedEvent).requestedReviewerId;
900+
break;
901+
default:
902+
userIdentifier = null;
903+
break;
904+
}
905+
}
906+
return {
907+
key: u.key,
908+
userId: getUserIdOrNullUserId(userIdentifier, forgeUsersData, nullUserId),
909+
}
910+
});
911+
}
912+
913+
async function selectCommittedDates(db: TransformDatabase, users: { key: { type: string, timestamp: Date }, type: string, data: unknown }[], nullDateId: number) {
914+
const { dates: transformDates } = transform;
915+
const committedDates: DMY[] = [];
916+
const uniqueDateQuery = new Map();
917+
918+
users.forEach(u => {
919+
if (u.type === 'committed') {
920+
const committedDate = new Date((u.data as extract.CommittedEvent).committedDate);
921+
if (!uniqueDateQuery.has(committedDate)) {
922+
uniqueDateQuery.set(committedDate, committedDate);
923+
const committedDateDMY = getDMY(committedDate);
924+
committedDates.push(committedDateDMY as DMY);
925+
}
926+
}
927+
})
928+
929+
const dmyQuery = committedDates.map(d => getDMYQuery(d));
930+
931+
const datesData = await db.select({
932+
id: transformDates.id,
933+
year: transformDates.year,
934+
month: transformDates.month,
935+
day: transformDates.day,
936+
week: transformDates.week,
937+
}).from(transformDates)
938+
.where(
939+
or(
940+
...dmyQuery
941+
)
942+
)
943+
.all();
944+
945+
return users.map(u => {
946+
let committedDate: Date | null = null;
947+
if (u.type === 'committed') {
948+
committedDate = new Date((u.data as extract.CommittedEvent).committedDate);
949+
}
950+
return {
951+
key: u.key,
952+
committedDateId: getDateIdOrNullDateId(getDMY(committedDate), datesData, nullDateId)
953+
}
954+
});
955+
}
956+
781957
async function upsertMergeRequestEvents(
782958
tx: SQLiteTransaction<"async", ResultSet, Record<string, unknown>, ExtractTablesWithRelations<Record<string, unknown>>>,
783959
db: TransformDatabase,
@@ -796,8 +972,45 @@ async function upsertMergeRequestEvents(
796972
nullDateId
797973
);
798974

975+
const transformForgeUserActors = await selectForgeUsers(
976+
db,
977+
timelineEvents.map(t => ({
978+
key: { type: t.type, timestamp: t.timestamp },
979+
userId: t.actorId,
980+
type: t.type,
981+
data: t.data
982+
})),
983+
nullUserId,
984+
true
985+
);
986+
987+
const transformForgeUserSubjects = await selectForgeUsers(
988+
db,
989+
timelineEvents.map(t => ({
990+
key: { type: t.type, timestamp: t.timestamp },
991+
type: t.type,
992+
data: t.data,
993+
userId: null
994+
})),
995+
nullUserId,
996+
false
997+
);
998+
999+
const transformCommittedDates = await selectCommittedDates(
1000+
db,
1001+
timelineEvents.map(t => ({
1002+
key: { type: t.type, timestamp: t.timestamp },
1003+
type: t.type,
1004+
data: t.data
1005+
})),
1006+
nullDateId,
1007+
);
1008+
7991009
const events = timelineEvents.map(timelineEvent => {
8001010
const td = transformDates.find(td => td.key.type === timelineEvent.type && td.key.timestamp.getTime() === timelineEvent.timestamp.getTime());
1011+
const tfua = transformForgeUserActors.find(tfu => tfu.key.type === timelineEvent.type && tfu.key.timestamp.getTime() === timelineEvent.timestamp.getTime());
1012+
const tfus = transformForgeUserSubjects.find(tfu => tfu.key.type === timelineEvent.type && tfu.key.timestamp.getTime() === timelineEvent.timestamp.getTime());
1013+
const tcd = transformCommittedDates.find(tfu => tfu.key.type === timelineEvent.type && tfu.key.timestamp.getTime() === timelineEvent.timestamp.getTime());
8011014

8021015
let type: transform.MergeRequestEventType;
8031016

@@ -819,18 +1032,14 @@ async function upsertMergeRequestEvents(
8191032
type = 'unknown';
8201033
break;
8211034
}
822-
823-
824-
825-
8261035
return {
8271036
mergeRequest: mergeRequestId,
8281037
mergeRequestEventType: type,
8291038
timestamp: timelineEvent.timestamp,
8301039
occuredOn: td?.dateId.id ? td.dateId.id : nullDateId,
831-
commitedAt: nullDateId,
832-
actor: nullUserId,
833-
subject: nullUserId,
1040+
commitedAt: tcd?.committedDateId.id ? tcd.committedDateId.id : nullDateId,
1041+
actor: tfua?.userId.id ? tfua.userId.id : nullUserId,
1042+
subject: tfus?.userId.id ? tfus.userId.id : nullUserId,
8341043
repository: repositoryId,
8351044
reviewState: 'unknown',
8361045
} satisfies transform.NewMergeRequestEvent;

0 commit comments

Comments
 (0)