mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-10-20 14:47:18 +02:00
fix: cover streamed access errors without alerting on outages
This commit is contained in:
1 parent
85b9a50d4d
commit
2b20abe0a5
5 files changed
+128
-45
No files matched your search
+6
-38
@@ -1,3 +1,4 @@
|
||||
import { isGitHubRateLimitError, OctokitRequestErrorLike } from "./github-rate-limit";
|
||||
import { refreshLegacyToken } from "./legacy-token-refresh";
|
||||
import { notifyOwnerAccessProblem } from "./owner-notifications";
|
||||
import AnonymizedRepositoryModel from "./model/anonymizedRepositories/anonymizedRepositories.model";
|
||||
@@ -17,35 +18,7 @@ import { measureStage } from "./request-monitoring";
|
||||
|
||||
const logger = createLogger("github");
|
||||
|
||||
// Octokit RequestError shape (subset we care about for rate-limit detection).
|
||||
interface OctokitRequestErrorLike {
|
||||
status?: number;
|
||||
message?: string;
|
||||
response?: {
|
||||
headers?: Record<string, string | undefined>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect GitHub rate-limit / abuse responses (primary 5k/h or undocumented
|
||||
* "secondary" limits) and rewrap them as a translatable AnonymousError so
|
||||
* the UI can show a friendly message instead of a raw HttpError stack. The
|
||||
* GitHub `x-github-request-id` header is preserved in `detail` so users can
|
||||
* cite it if they reach out to GitHub Support.
|
||||
*/
|
||||
export function isGitHubRateLimitError(err: unknown): boolean {
|
||||
if (!err || typeof err !== "object") return false;
|
||||
const e = err as OctokitRequestErrorLike;
|
||||
const msg = (e.message ?? "").toLowerCase();
|
||||
// Primary limits return 403 with "x-ratelimit-remaining: 0"; secondary
|
||||
// limits return 403 (sometimes 429) with "secondary rate limit" in the
|
||||
// body. Match on either signal so we catch both.
|
||||
const status = e.status ?? 0;
|
||||
if (status !== 403 && status !== 429) return false;
|
||||
if (msg.includes("rate limit") || msg.includes("abuse")) return true;
|
||||
const remaining = e.response?.headers?.["x-ratelimit-remaining"];
|
||||
return remaining === "0";
|
||||
}
|
||||
export { isGitHubRateLimitError } from "./github-rate-limit";
|
||||
|
||||
function rateLimitDetail(err: OctokitRequestErrorLike): string {
|
||||
const headers = err.response?.headers ?? {};
|
||||
@@ -299,15 +272,10 @@ export async function checkToken(token: string, ownerId?: string) {
|
||||
else await oct.users.getAuthenticated();
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof AnonymousError &&
|
||||
err.message === "github_rate_limit_exceeded"
|
||||
) {
|
||||
throw err;
|
||||
}
|
||||
if (ownerId && (err as { status?: number }).status === 401) {
|
||||
void notifyOwnerAccessProblem(ownerId, "token_expired");
|
||||
}
|
||||
// Only a confirmed invalid credential permits fallback. Network failures,
|
||||
// permission failures and rate limits must retain their original meaning.
|
||||
if ((err as { status?: number })?.status !== 401) throw err;
|
||||
if (ownerId) void notifyOwnerAccessProblem(ownerId, "token_expired");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user