Skip to content

Commit 93fb639

Browse files
committed
.
1 parent 7853ed0 commit 93fb639

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

supabase/functions/autograder-create-submission/index.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,18 +640,26 @@ async function handleRequest(req: Request, scope: Sentry.Scope) {
640640
let userRoles: Database["public"]["Tables"]["user_roles"]["Row"] | undefined;
641641
const classId = initialCheckRun.class_id ?? repoData.assignments.class_id;
642642
if (classId && !isPawtograderTriggered) {
643-
const { data: user } = await adminSupabase
643+
const { data: user, error: userError } = await adminSupabase
644644
.from("users")
645645
.select("user_id")
646-
.eq("github_username", decoded.actor)
646+
.ilike("github_username", decoded.actor)
647647
.maybeSingle();
648+
if (userError) {
649+
Sentry.captureException(userError, scope);
650+
throw new UserVisibleError(`Failed to lookup user: ${userError.message}`);
651+
}
648652
if (user) {
649-
const { data: userRolesData } = await adminSupabase
653+
const { data: userRolesData, error: userRolesError } = await adminSupabase
650654
.from("user_roles")
651655
.select("*")
652656
.eq("user_id", user.user_id)
653657
.eq("class_id", classId)
654658
.maybeSingle();
659+
if (userRolesError) {
660+
Sentry.captureException(userRolesError, scope);
661+
throw new UserVisibleError(`Failed to lookup user role: ${userRolesError.message}`);
662+
}
655663
userRoles = userRolesData ?? undefined;
656664
}
657665
}

supabase/functions/autograder-submit-feedback/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ function detectRateLimitType(error: unknown): {
6060
}
6161

6262
if (status === 403 || status === 429) {
63-
const retryAfter = headers?.["retry-after"]
64-
? parseInt(headers["retry-after"], 10)
65-
: undefined;
63+
const retryAfter = headers?.["retry-after"] ? parseInt(headers["retry-after"], 10) : undefined;
6664
const remaining = headers?.["x-ratelimit-remaining"];
6765
if (remaining === "0") {
6866
return { type: "primary", retryAfter: retryAfter ?? 60 };

supabase/functions/github-repo-webhook/index.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ function detectRateLimitType(error: unknown): {
6565
}
6666

6767
if (status === 403 || status === 429) {
68-
const retryAfter = headers?.["retry-after"]
69-
? parseInt(headers["retry-after"], 10)
70-
: undefined;
68+
const retryAfter = headers?.["retry-after"] ? parseInt(headers["retry-after"], 10) : undefined;
7169
const remaining = headers?.["x-ratelimit-remaining"];
7270
if (remaining === "0") {
7371
return { type: "primary", retryAfter: retryAfter ?? 60 };
@@ -345,11 +343,11 @@ async function handlePushToStudentRepo(
345343
maybeCrash("push.student.for_each_commit.before_lookup");
346344

347345
// Check circuit breaker before making GitHub API calls - fail fast if rate limited
348-
// Check both org-level and create_repo method-specific circuit breakers
349-
const circuitStatus = await checkCircuitBreakerOpen(adminSupabase, org, "create_repo", scope);
346+
// Check both org-level and triggerWorkflow method-specific circuit breakers
347+
const circuitStatus = await checkCircuitBreakerOpen(adminSupabase, org, "triggerWorkflow", scope);
350348
if (circuitStatus.isOpen) {
351349
const openUntil = circuitStatus.openUntil ? new Date(circuitStatus.openUntil).toLocaleString() : "unknown";
352-
const scopeInfo = circuitStatus.circuitScope === "org_method" ? ` (method: create_repo)` : "";
350+
const scopeInfo = circuitStatus.circuitScope === "org_method" ? ` (method: triggerWorkflow)` : "";
353351
throw new Error(
354352
`Circuit breaker open for org ${org}${scopeInfo}: GitHub API operations temporarily unavailable. ` +
355353
`Reason: ${circuitStatus.reason || "Rate limit or error threshold exceeded"}. ` +

supabase/migrations/20260218120000_make_check_run_id_nullable.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@
77
ALTER TABLE repository_check_runs
88
DROP CONSTRAINT IF EXISTS repository_check_runs_repository_id_check_run_id_sha_key;
99

10+
-- Dedupe: remove duplicate (repository_id, sha) rows before adding unique constraint.
11+
-- Keep the row with smallest id (earliest) per (repository_id, sha).
12+
-- First, update submissions that reference duplicate rows to point to the canonical row.
13+
WITH dups AS (
14+
SELECT id,
15+
FIRST_VALUE(id) OVER (PARTITION BY repository_id, sha ORDER BY id ASC) AS canonical_id
16+
FROM public.repository_check_runs
17+
)
18+
UPDATE public.submissions s
19+
SET repository_check_run_id = d.canonical_id
20+
FROM dups d
21+
WHERE s.repository_check_run_id = d.id
22+
AND d.id != d.canonical_id;
23+
24+
-- Delete duplicate rows, keeping only the canonical (smallest id) per (repository_id, sha).
25+
WITH ranked AS (
26+
SELECT id,
27+
ROW_NUMBER() OVER (PARTITION BY repository_id, sha ORDER BY id ASC) AS rn
28+
FROM public.repository_check_runs
29+
)
30+
DELETE FROM public.repository_check_runs
31+
WHERE id IN (SELECT id FROM ranked WHERE rn > 1);
32+
1033
-- Add unique constraint on (repository_id, sha) for idempotency
1134
ALTER TABLE repository_check_runs
1235
ADD CONSTRAINT repository_check_runs_repository_id_sha_key UNIQUE (repository_id, sha);

0 commit comments

Comments
 (0)