chore: update src/lib/graphql/resolvers.ts

swadhinbiswas committed 8 months ago
8fa6908
1 parent 8461836
commit 8fa6908
1 file changed
+69 -7
Showing 1 changed file+69-7
▼src/lib/graphql/resolvers.ts
+69-7
7
7
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
8
8
import { eq, and, like, desc, sql, count } from "drizzle-orm";
9
9
import { logger } from "@/lib/logger";
10
+import { compareBranches, getCommit, mergeBranch } from "@/lib/git";
11
+import { resolveRepoPath } from "@/lib/git-storage";
12
+import { canWriteRepo } from "@/lib/permissions";
13
+import { evaluateGates } from "@/lib/ci-gates";
14
+import { closeLinkedIssuesOnMerge } from "@/lib/pr-issue-linking";
10
15
11
16
// Context type for resolvers
12
17
export interface GraphQLContext {
209
214
};
210
215
},
211
216
212
- stargazerCount: () => 0, // Stars table not yet implemented
217
+ stargazerCount: async (
218
+ repo: typeof schema.repositories.$inferSelect,
219
+ _: unknown,
220
+ ctx: GraphQLContext
221
+ ) => {
222
+ const result = await ctx.db
223
+ .select({ count: count() })
224
+ .from(schema.repositoryStars)
225
+ .where(eq(schema.repositoryStars.repositoryId, repo.id));
226
+ return result[0]?.count || 0;
227
+ },
213
228
214
229
forkCount: async (
215
230
repo: typeof schema.repositories.$inferSelect,
429
444
});
430
445
if (!repo) throw new Error("Repository not found");
431
446
447
+ const repoPath = await resolveRepoPath(repo.diskPath);
448
+ const headCommit = await getCommit(repoPath, input.headRefName);
449
+ if (!headCommit) throw new Error(`Head branch ${input.headRefName} not found`);
450
+
451
+ const baseCommit = await getCommit(repoPath, input.baseRefName);
452
+ if (!baseCommit) throw new Error(`Base branch ${input.baseRefName} not found`);
453
+
454
+ const { diffs } = await compareBranches(repoPath, input.baseRefName, input.headRefName);
455
+ const additions = diffs.reduce((sum, diff) => sum + diff.additions, 0);
456
+ const deletions = diffs.reduce((sum, diff) => sum + diff.deletions, 0);
457
+ const changedFiles = diffs.length;
458
+
432
459
// Get next PR number
433
460
const result = await ctx.db
434
461
.select({ count: count() })
447
474
authorId: ctx.userId,
448
475
headBranch: input.headRefName,
449
476
baseBranch: input.baseRefName,
450
- headSha: "0000000000000000000000000000000000000000", // Placeholder - would fetch from git
451
- baseSha: "0000000000000000000000000000000000000000", // Placeholder
477
+ headSha: headCommit.sha,
478
+ baseSha: baseCommit.sha,
452
479
isDraft: input.draft,
453
480
state: "open",
481
+ additions,
482
+ deletions,
483
+ changedFiles,
454
484
createdAt: new Date(),
455
485
updatedAt: new Date(),
456
486
});
476
506
477
507
if (pr.state !== "open") throw new Error("Pull request is not open");
478
508
479
- // In a real implementation, this would trigger a git merge or enqueue
480
- // For now, we update the DB state
509
+ const repo = await ctx.db.query.repositories.findFirst({
510
+ where: eq(schema.repositories.id, pr.repositoryId),
511
+ });
512
+ if (!repo) throw new Error("Repository not found");
513
+
514
+ if (!(await canWriteRepo(ctx.userId, repo, { isAdmin: ctx.user?.isAdmin ?? undefined }))) {
515
+ throw new Error("Access denied");
516
+ }
517
+
518
+ const gateResult = await evaluateGates(pr.id);
519
+ if (!gateResult.canMerge) {
520
+ const failed = gateResult.results
521
+ .filter((r) => !r.passed)
522
+ .map((r) => r.message)
523
+ .join("; ");
524
+ throw new Error(`Merge blocked: ${failed}`);
525
+ }
526
+
527
+ const commitTitle = input.commitTitle || `Merge pull request #${pr.number} from ${pr.headBranch}`;
528
+ const mergeMessage = input.commitBody
529
+ ? `${commitTitle}\n\n${input.commitBody}`
530
+ : commitTitle;
531
+
532
+ const repoPath = await resolveRepoPath(repo.diskPath);
533
+ const mergeResult = await mergeBranch(repoPath, pr.baseBranch, pr.headBranch, mergeMessage);
534
+ if (!mergeResult.success) {
535
+ throw new Error(mergeResult.message || "Merge failed");
536
+ }
537
+
538
+ const now = new Date();
481
539
await ctx.db.update(schema.pullRequests)
482
540
.set({
483
541
state: "merged",
484
542
isMerged: true,
485
- mergedAt: new Date(),
543
+ mergedAt: now,
486
544
mergedById: ctx.userId,
545
+ mergeCommitSha: mergeResult.sha || null,
546
+ mergeSha: mergeResult.sha || null,
487
547
mergeMethod: input.mergeMethod?.toLowerCase() || "merge",
488
- updatedAt: new Date(),
548
+ updatedAt: now,
489
549
})
490
550
.where(eq(schema.pullRequests.id, input.pullRequestId));
491
551
552
+ await closeLinkedIssuesOnMerge(pr.id, ctx.userId);
553
+
492
554
const updatedPr = await ctx.db.query.pullRequests.findFirst({
493
555
where: eq(schema.pullRequests.id, input.pullRequestId),
494
556
});
495
557