feat: implement github profile sync and manual refresh endpoint#149
feat: implement github profile sync and manual refresh endpoint#149bishopBethel merged 3 commits intodevasignhq:mainfrom
Conversation
Merge Score: 85/100🟢 The PR successfully implements GitHub profile synchronization and adds a manual refresh endpoint. The database migration and tests are well-structured. However, the manual sync endpoint should return the actual database state to prevent overwriting the frontend's email with Code Suggestions (3)Medium Priority (2)
Reasoning: If the public GitHub profile does not expose an email, Suggested Code: const [updatedUser] = await db.update(users)
.set({
avatarUrl: githubUser.avatar_url,
...(githubUser.email ? { email: githubUser.email } : {}),
publicRepos: githubUser.public_repos || 0,
updatedAt: new Date(),
})
.where(eq(users.id, user.id))
.returning();
return c.json({
success: true,
avatarUrl: updatedUser.avatarUrl,
email: updatedUser.email,
publicRepos: updatedUser.publicRepos,
});
Reasoning: The unauthenticated GitHub API is limited to 60 requests per hour per IP. If multiple users sync their profiles, the server will quickly hit this limit. Using a server-side GitHub token (if available) increases this limit to 5,000 requests per hour. Additionally, handling 404 (username changed) and 403 (rate limit exceeded) provides better error messages to the client. Suggested Code: async getUserProfileByUsername(username: string): Promise<GitHubUser> {
const headers: Record<string, string> = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': 'Devasign-API',
};
if (process.env.GITHUB_TOKEN) {
headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
}
const response = await fetch(`https://api.github.com/users/${username}`, {
headers,
});
if (!response.ok) {
if (response.status === 404) {
throw new Error('GitHub user not found. If your username changed, please log in again.');
}
if (response.status === 403 && response.headers.get('x-ratelimit-remaining') === '0') {
throw new Error('GitHub API rate limit exceeded. Please try again later.');
}
throw new Error(`GitHub API error: ${response.statusText}`);
}
return await response.json() as GitHubUser;
}Low Priority (1)
Reasoning: Since Suggested Code: update: vi.fn(() => ({
set: vi.fn(() => ({
where: vi.fn(() => ({
returning: vi.fn(() => [{
avatarUrl: 'https://synced.avatar.url',
email: 'test@example.com',
publicRepos: 42
}])
})),
})),
})),📊 Review Metadata
|
Updated Merge Score: 95/100🟢 The author successfully addressed all concerns from the previous review. The manual sync endpoint now correctly returns the updated database state using Code Suggestions (1)Low Priority (1)
Reasoning: Although the user is authenticated, if the database update fails to match a row (e.g., due to a deleted user or race condition), Suggested Code: if (!updatedUser) {
return c.json({ error: 'User not found in database' }, 404);
}
// Return updated attributes
return c.json({
success: true,
avatarUrl: updatedUser.avatarUrl,
email: updatedUser.email,
publicRepos: updatedUser.publicRepos,
});📊 Review Metadata
|
Updated Merge Score: 100/100🟢 The author successfully addressed the final edge case from the previous review by adding a null check for Code SuggestionsGreat job! No specific suggestions at this time. 📊 Review Metadata
|
closes #117