From 829e1ea1dc88a9dee6bb3a0f43fbaf58ceaf3f71 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 10 Mar 2026 12:10:36 -0700 Subject: [PATCH] Add detailed logging for Gitea API errors to diagnose 401 issues. Extracts token presence/length, response status, failed URL, and response body (first 500 chars) into structured logs. This will help identify whether token is missing, invalid, or if Gitea is rejecting for another reason. Co-Authored-By: Claude Haiku 4.5 --- packages/spike/src/gitea/api.ts | 40 ++++++++++++++++----------------- packages/spike/src/log.ts | 1 + 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/spike/src/gitea/api.ts b/packages/spike/src/gitea/api.ts index aa30477..d5b59a8 100644 --- a/packages/spike/src/gitea/api.ts +++ b/packages/spike/src/gitea/api.ts @@ -1,18 +1,33 @@ +import { log } from "../log" import type { Gitea } from "./types" const giteaUrl = "https://git.nose.space" -export async function fetchPR(fullname: string, prNumber: number): Promise { - const url = `${giteaUrl}/api/v1/repos/${fullname}/pulls/${prNumber}` +function tokenPrefix(): string { + const token = process.env.GITEA_API_TOKEN + if (!token) return "MISSING" + return `${token.slice(0, 4)}...${token.slice(-4)} (${token.length} chars)` +} + +async function giteaFetch(url: string): Promise { const response = await fetch(url, { headers: { Authorization: `token ${process.env.GITEA_API_TOKEN}`, }, }) + if (!response.ok) { + const body = await response.text() + log({ type: "gitea-api-error", status: response.status, url, body: body.slice(0, 500), tokenPrefix: tokenPrefix() }) throw new Error(`Gitea API error: ${response.status} ${response.statusText}`) } + return response +} + +export async function fetchPR(fullname: string, prNumber: number): Promise { + const url = `${giteaUrl}/api/v1/repos/${fullname}/pulls/${prNumber}` + const response = await giteaFetch(url) return response.json() as Promise } @@ -20,16 +35,8 @@ export async function fetchReviewComments( fullname: string, prNumber: number ): Promise { - // First, fetch all reviews const reviewsUrl = `${giteaUrl}/api/v1/repos/${fullname}/pulls/${prNumber}/reviews` - const reviewsResponse = await fetch(reviewsUrl, { - headers: { - Authorization: `token ${process.env.GITEA_API_TOKEN}`, - }, - }) - if (!reviewsResponse.ok) { - throw new Error(`Gitea API error: ${reviewsResponse.status} ${reviewsResponse.statusText}`) - } + const reviewsResponse = await giteaFetch(reviewsUrl) const reviews = (await reviewsResponse.json()) as Array<{ id: number @@ -40,21 +47,12 @@ export async function fetchReviewComments( comments_count: number }> - // For each review, fetch its comments const allComments: Gitea.ReviewComment[] = [] for (const review of reviews) { if (review.comments_count === 0) continue const commentsUrl = `${giteaUrl}/api/v1/repos/${fullname}/pulls/${prNumber}/reviews/${review.id}/comments` - const commentsResponse = await fetch(commentsUrl, { - headers: { - Authorization: `token ${process.env.GITEA_API_TOKEN}`, - }, - }) - - if (!commentsResponse.ok) { - throw new Error(`Gitea API error fetching review ${review.id} comments: ${commentsResponse.status} ${commentsResponse.statusText}`) - } + const commentsResponse = await giteaFetch(commentsUrl) const comments = (await commentsResponse.json()) as Gitea.ReviewComment[] allComments.push(...comments) } diff --git a/packages/spike/src/log.ts b/packages/spike/src/log.ts index 3647924..863cb9c 100644 --- a/packages/spike/src/log.ts +++ b/packages/spike/src/log.ts @@ -16,6 +16,7 @@ export type LogEvent = | { type: "crash-log-found" } | { type: "startup"; detail: string } | { type: "discord-ready" } + | { type: "gitea-api-error"; status: number; url: string; body: string; tokenPrefix: string } | { type: "error"; error: unknown; context?: string } export type StoredLogEvent = LogEvent & { ts: string }