Skip to content

Commit 0bc7c6e

Browse files
authored
feat: sync people's bio and location (#94)
* fix: npm vulnerabilities * feat: sync profile bio & location * fix: pr review * fix: review comment * fix: review comment
1 parent e3dabeb commit 0bc7c6e

File tree

25 files changed

+9924
-14199
lines changed

25 files changed

+9924
-14199
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- AlterTable
2+
ALTER TABLE "GitProfile" ADD COLUMN "bio" TEXT,
3+
ADD COLUMN "location" TEXT;

apps/api/prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ model GitProfile {
113113
handle String
114114
name String
115115
avatar String?
116+
bio String?
117+
location String?
116118
workspaceMemberships WorkspaceMembership[]
117119
118120
user User? @relation(fields: [userId], references: [id])

apps/api/src/app/auth/services/auth.service.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ const getLoginState = (redirectTo: string = "/") => {
7878
export const createOrSyncProfile = async (
7979
githubUser: Pick<
8080
GithubUser,
81-
"node_id" | "login" | "name" | "email" | "avatar_url"
81+
"node_id" | "login" | "name" | "email" | "avatar_url" | "bio" | "location"
8282
>
8383
): Promise<
8484
GitProfile & {
8585
user: User;
8686
workspaceMemberships: WorkspaceMembership[];
8787
}
8888
> => {
89-
const { login, name, email, avatar_url, node_id } = githubUser;
89+
const { login, name, email, avatar_url, node_id, bio, location } = githubUser;
9090

9191
const handle = login;
9292

@@ -101,6 +101,8 @@ export const createOrSyncProfile = async (
101101
handle,
102102
name: name || handle,
103103
avatar: avatar_url,
104+
bio: bio || null,
105+
location: location || null,
104106
user: {
105107
upsert: {
106108
update: {
@@ -120,6 +122,8 @@ export const createOrSyncProfile = async (
120122
name: name || handle,
121123
gitUserId: node_id,
122124
handle,
125+
bio: bio || null,
126+
location: location || null,
123127
user: {
124128
create: {
125129
slug: createUserSlug(GitProvider.GITHUB, handle),
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { GitProfile } from "@prisma/client";
2+
import { getPrisma } from "../../../prisma";
3+
import { UpsertGitProfileInput } from "./git-profile.types";
4+
5+
export const upsertGitProfile = async (
6+
input: UpsertGitProfileInput
7+
): Promise<GitProfile> => {
8+
const data = {
9+
...input,
10+
avatar: input.avatar ?? undefined,
11+
};
12+
13+
return getPrisma().gitProfile.upsert({
14+
where: {
15+
gitProvider_gitUserId: {
16+
gitUserId: input.gitUserId,
17+
gitProvider: input.gitProvider,
18+
},
19+
},
20+
create: data,
21+
update: data,
22+
});
23+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { GitProvider } from "@prisma/client";
2+
3+
export interface UpsertGitProfileInput {
4+
gitProvider: GitProvider;
5+
gitUserId: string;
6+
handle: string;
7+
name: string;
8+
avatar?: string | null;
9+
bio?: string | null;
10+
location?: string | null;
11+
}

apps/api/src/app/github/services/github-code-review.service.ts

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,9 @@ import { ResourceNotFoundException } from "../../errors/exceptions/resource-not-
2424
import { SweetQueue, addJob } from "../../../bull-mq/queues";
2525
import { findWorkspaceByGitInstallationId } from "../../workspaces/services/workspace.service";
2626
import { parseISO } from "date-fns";
27-
28-
interface Author {
29-
id: string;
30-
login: string;
31-
name: string;
32-
avatarUrl: string;
33-
}
27+
import { upsertGitProfile } from "../../gitProfile/services/git-profile.service";
28+
import { GitHubUser } from "./github-user.types";
29+
import { gitHubUserToGitProfileData } from "./github-user.service";
3430

3531
interface ReviewData {
3632
gitProfileId: number;
@@ -46,7 +42,7 @@ type ReviewDataWithId = ReviewData & {
4642
interface ReviewRequestData {
4743
createdAt: Date;
4844
deletedAt: Date | null;
49-
author: Author;
45+
author: GitHubUser;
5046
}
5147

5248
export const syncCodeReviews = async (
@@ -131,13 +127,16 @@ const fetchPullRequestReviews = async (
131127
const reviewEvents: ReviewDataWithId[] = [];
132128
const gitProfiles = new Map<string, GitProfile>();
133129

134-
const getGitProfileId = async (author: Author) => {
135-
if (gitProfiles.has(author.id)) {
136-
return gitProfiles.get(author.id)!.id;
130+
const getGitProfileId = async (author: GitHubUser) => {
131+
if (gitProfiles.has(author.nodeId)) {
132+
return gitProfiles.get(author.nodeId)!.id;
137133
}
138134

139-
const gitProfile = await upsertGitProfile(author);
140-
gitProfiles.set(author.id, gitProfile);
135+
const gitProfile = await upsertGitProfile(
136+
gitHubUserToGitProfileData(author)
137+
);
138+
139+
gitProfiles.set(author.nodeId, gitProfile);
141140

142141
return gitProfile.id;
143142
};
@@ -154,6 +153,8 @@ const fetchPullRequestReviews = async (
154153
login
155154
name
156155
avatarUrl
156+
bio
157+
location
157158
}
158159
}
159160
}
@@ -166,6 +167,8 @@ const fetchPullRequestReviews = async (
166167
login
167168
name
168169
avatarUrl
170+
bio
171+
location
169172
}
170173
}
171174
}
@@ -201,6 +204,8 @@ const fetchPullRequestReviews = async (
201204
login
202205
name
203206
avatarUrl
207+
bio
208+
location
204209
}
205210
}
206211
comments {
@@ -336,10 +341,12 @@ const getReviewRequests = (nodes: any[]): ReviewRequestData[] => {
336341
createdAt: new Date(node.createdAt),
337342
deletedAt: null,
338343
author: {
339-
id: reviewerId,
344+
nodeId: reviewerId,
340345
login: node.requestedReviewer.login,
341346
name: node.requestedReviewer.name,
342347
avatarUrl: node.requestedReviewer.avatarUrl,
348+
bio: node.requestedReviewer.bio,
349+
location: node.requestedReviewer.location,
343350
},
344351
});
345352
}
@@ -356,10 +363,12 @@ const getReviewRequests = (nodes: any[]): ReviewRequestData[] => {
356363
if (reviewRequest) {
357364
reviewRequest.deletedAt = new Date(node.createdAt);
358365
reviewRequest.author = {
359-
id: reviewerId,
366+
nodeId: reviewerId,
360367
login: node.requestedReviewer.login,
361368
name: node.requestedReviewer.name,
362369
avatarUrl: node.requestedReviewer.avatarUrl,
370+
bio: node.requestedReviewer.bio,
371+
location: node.requestedReviewer.location,
363372
};
364373
}
365374
}
@@ -376,7 +385,9 @@ const upsertCodeReviewRequests = async (
376385
logger.debug("upsertCodeReviewRequests", { pullRequest, reviewRequests });
377386

378387
return parallel(10, reviewRequests, async (reviewRequest) => {
379-
const gitProfile = await upsertGitProfile(reviewRequest.author);
388+
const gitProfile = await upsertGitProfile(
389+
gitHubUserToGitProfileData(reviewRequest.author)
390+
);
380391

381392
const data = {
382393
workspaceId: pullRequest.workspaceId,
@@ -481,25 +492,6 @@ const updatePullRequestTracking = async (
481492
});
482493
};
483494

484-
const upsertGitProfile = async (author: Author) => {
485-
return getPrisma().gitProfile.upsert({
486-
where: {
487-
gitProvider_gitUserId: {
488-
gitProvider: GitProvider.GITHUB,
489-
gitUserId: author.id,
490-
},
491-
},
492-
update: {},
493-
create: {
494-
gitProvider: GitProvider.GITHUB,
495-
gitUserId: author.id,
496-
handle: author.login,
497-
name: author.name ? author.name : author.login,
498-
avatar: author.avatarUrl,
499-
},
500-
});
501-
};
502-
503495
const findPullRequest = async (
504496
workspaceId: number,
505497
gitPullRequestId: string

apps/api/src/app/github/services/github-installation.service.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { logger } from "../../../lib/logger";
1616
import { getInstallationOctoKit, octokit } from "../../../lib/octokit";
1717
import { addDays, endOfDay } from "date-fns";
1818
import { ResourceNotFoundException } from "../../errors/exceptions/resource-not-found.exception";
19+
import { upsertGitProfile } from "../../gitProfile/services/git-profile.service";
20+
import { gitHubUserToGitProfileData } from "./github-user.service";
1921

2022
export const syncGitHubInstallation = async (
2123
gitInstallation: GitHubInstallation,
@@ -26,7 +28,15 @@ export const syncGitHubInstallation = async (
2628
gitUser,
2729
});
2830

29-
const gitProfile = await upsertGitProfile(gitUser);
31+
const gitProfile = await upsertGitProfile(
32+
gitHubUserToGitProfileData({
33+
nodeId: gitUser.node_id,
34+
avatarUrl: gitUser.avatar_url,
35+
bio: undefined,
36+
location: undefined,
37+
...gitUser,
38+
})
39+
);
3040
const workspace = await upsertWorkspace(gitInstallation, gitProfile);
3141
const installation = await upsertInstallation(gitInstallation, workspace.id);
3242

@@ -155,28 +165,6 @@ const upsertWorkspace = async (
155165
});
156166
};
157167

158-
const upsertGitProfile = async (gitUser: GitHubUser): Promise<GitProfile> => {
159-
const gitUserId = gitUser.node_id.toString();
160-
161-
const data = {
162-
gitUserId,
163-
gitProvider: GitProvider.GITHUB,
164-
handle: gitUser.login,
165-
name: gitUser.name || gitUser.login,
166-
avatar: gitUser.avatar_url,
167-
};
168-
169-
const gitProfile = await getPrisma().gitProfile.upsert({
170-
where: {
171-
gitProvider_gitUserId: { gitUserId, gitProvider: GitProvider.GITHUB },
172-
},
173-
create: data,
174-
update: data,
175-
});
176-
177-
return gitProfile;
178-
};
179-
180168
const connectUserToWorkspace = async (
181169
gitProfile: GitProfile,
182170
workspace: Workspace

apps/api/src/app/github/services/github-member.service.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
1-
import { GitProfile, GitProvider } from "@prisma/client";
1+
import { GitProfile } from "@prisma/client";
22
import {
33
GITHUB_MAX_PAGE_LIMIT,
44
getInstallationGraphQLOctoKit,
55
} from "../../../lib/octokit";
66
import { getPrisma } from "../../../prisma";
77
import { parallel } from "radash";
88
import { ResourceNotFoundException } from "../../errors/exceptions/resource-not-found.exception";
9+
import { upsertGitProfile } from "../../gitProfile/services/git-profile.service";
910
import { logger } from "../../../lib/logger";
1011
import { findWorkspaceByGitInstallationId } from "../../workspaces/services/workspace.service";
12+
import { gitHubUserToGitProfileData } from "./github-user.service";
13+
import { GitHubUser } from "./github-user.types";
1114

1215
type GitOrganizationMember = {
1316
id: string;
1417
login: string;
1518
role: string;
1619
name?: string;
1720
avatarUrl?: string;
21+
bio?: string;
22+
location?: string;
1823
};
1924

20-
type MemberData = Omit<
21-
GitProfile,
22-
"id" | "userId" | "createdAt" | "updatedAt"
23-
> & {
25+
type MemberData = GitHubUser & {
2426
role: string;
2527
};
2628

@@ -41,12 +43,8 @@ export const syncOrganizationMembers = async (
4143
);
4244

4345
const membersData: MemberData[] = gitHubMembers.map((member) => ({
44-
gitProvider: GitProvider.GITHUB,
45-
gitUserId: member.id,
46-
handle: member.login,
47-
name: member.name || member.login,
48-
avatar: member.avatarUrl || null,
49-
role: member.role,
46+
nodeId: member.id,
47+
...member,
5048
}));
5149

5250
const workspaceGitProfiles = await upsertGitProfiles(
@@ -79,8 +77,7 @@ const fetchGitHubOrganizationMembers = async (
7977
gitInstallationId: number,
8078
organizationName: string
8179
): Promise<GitOrganizationMember[]> => {
82-
const fireGraphQLRequest =
83-
await getInstallationGraphQLOctoKit(gitInstallationId);
80+
const fireGraphQLRequest = getInstallationGraphQLOctoKit(gitInstallationId);
8481

8582
const members: any[] = [];
8683
let hasNextPage = true;
@@ -101,6 +98,8 @@ const fetchGitHubOrganizationMembers = async (
10198
login
10299
name
103100
avatarUrl
101+
bio
102+
location
104103
}
105104
edges {
106105
role
@@ -150,16 +149,9 @@ const upsertGitProfiles = async (
150149
return parallel(10, membersData, async (memberData) => {
151150
const { role, ...member } = memberData;
152151

153-
const gitProfile = await getPrisma().gitProfile.upsert({
154-
where: {
155-
gitProvider_gitUserId: {
156-
gitProvider: GitProvider.GITHUB,
157-
gitUserId: member.gitUserId,
158-
},
159-
},
160-
create: member,
161-
update: member,
162-
});
152+
const gitProfile = await upsertGitProfile(
153+
gitHubUserToGitProfileData(member)
154+
);
163155

164156
await getPrisma(workspaceId).workspaceMembership.upsert({
165157
where: {

0 commit comments

Comments
 (0)