mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
fix: fall back from github contents rate limits
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
multica-agent
parent
e8887aab13
commit
aba8f58eac
@@ -181,8 +181,10 @@ async function* installFromGithub(
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (lastError && isRetryableGithubCandidateError(lastError)) continue;
|
||||
if (lastError) break;
|
||||
if (lastError) {
|
||||
if (shouldTryNextGithubRefCandidate(lastError)) continue;
|
||||
if (!isRetryableGithubCandidateError(lastError)) break;
|
||||
}
|
||||
}
|
||||
|
||||
const tarballUrl = githubTarballUrl(parsed.owner, parsed.repo, candidate.ref);
|
||||
@@ -199,13 +201,13 @@ async function* installFromGithub(
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!lastError || !isRetryableGithubCandidateError(lastError)) break;
|
||||
if (!lastError || !shouldTryNextGithubRefCandidate(lastError)) break;
|
||||
}
|
||||
|
||||
yield {
|
||||
kind: 'error',
|
||||
message: lastError
|
||||
? `${lastError}. Tried GitHub archive URL(s): ${triedUrls.join(', ')}`
|
||||
? `GitHub install failed: ${lastError}. Tried GitHub fetch URL(s): ${triedUrls.join(', ')}`
|
||||
: `GitHub source ${opts.source} did not produce an installable archive`,
|
||||
warnings: [],
|
||||
};
|
||||
@@ -264,7 +266,19 @@ function githubContentsUrl(owner: string, repo: string, subpath: string, ref: st
|
||||
}
|
||||
|
||||
function isRetryableGithubCandidateError(message: string): boolean {
|
||||
return /^Fetch failed: 404\b/.test(message) || /^Subpath .+ not found inside archive$/.test(message);
|
||||
return /^Fetch failed: 404\b/.test(message)
|
||||
|| isGithubRateLimitError(message)
|
||||
|| /^Subpath .+ not found inside archive$/.test(message);
|
||||
}
|
||||
|
||||
function shouldTryNextGithubRefCandidate(message: string): boolean {
|
||||
return /^Fetch failed: 404\b/.test(message)
|
||||
|| /^Subpath .+ not found inside archive$/.test(message);
|
||||
}
|
||||
|
||||
function isGithubRateLimitError(message: string): boolean {
|
||||
return /^Fetch failed: 429\b/.test(message)
|
||||
|| /^Fetch failed: 403\b/.test(message);
|
||||
}
|
||||
|
||||
async function* installFromGithubContents(
|
||||
|
||||
@@ -169,6 +169,77 @@ describe('archive installer', () => {
|
||||
expect(row).toEqual({ source_kind: 'github', source });
|
||||
});
|
||||
|
||||
it.each([
|
||||
[403, 'Forbidden', '{"message":"API rate limit exceeded for 127.0.0.1"}'],
|
||||
[429, 'Too Many Requests', 'too many requests'],
|
||||
])('falls back to codeload when GitHub contents returns %i for a plugin subpath', async (status, statusText, body) => {
|
||||
const tarball = await buildFixtureTarball({
|
||||
rootPrefix: 'open-design-main',
|
||||
pluginSubpath: 'plugins/community/import-smoke-test',
|
||||
});
|
||||
const urlsSeen: string[] = [];
|
||||
const contentsUrl =
|
||||
'https://api.github.com/repos/nexu-io/open-design/contents/plugins/community/import-smoke-test?ref=main';
|
||||
const tarballUrl = 'https://codeload.github.com/nexu-io/open-design/tar.gz/main';
|
||||
const fetcher: ArchiveFetcher = async (u) => {
|
||||
urlsSeen.push(u);
|
||||
if (u === contentsUrl) {
|
||||
return makeResponse(body, status, statusText);
|
||||
}
|
||||
if (u === tarballUrl) return makeResponse(tarball);
|
||||
return makeResponse('not found', 404, 'Not Found');
|
||||
};
|
||||
|
||||
let success = false;
|
||||
let error: string | undefined;
|
||||
const source = 'github:nexu-io/open-design@main/plugins/community/import-smoke-test';
|
||||
for await (const ev of installPlugin(db, {
|
||||
source,
|
||||
roots: { userPluginsRoot: pluginsRoot },
|
||||
fetcher,
|
||||
})) {
|
||||
if (ev.kind === 'success') success = true;
|
||||
if (ev.kind === 'error') error = ev.message;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
throw new Error(`install failed: ${error}`);
|
||||
}
|
||||
expect(urlsSeen).toEqual([contentsUrl, tarballUrl]);
|
||||
const row = db.prepare(`SELECT source_kind, source FROM installed_plugins WHERE id = 'sample-plugin'`).get();
|
||||
expect(row).toEqual({ source_kind: 'github', source });
|
||||
});
|
||||
|
||||
it('reports both GitHub contents and codeload URLs when subpath fallback fails', async () => {
|
||||
const urlsSeen: string[] = [];
|
||||
const contentsUrl =
|
||||
'https://api.github.com/repos/nexu-io/open-design/contents/plugins/community/import-smoke-test?ref=main';
|
||||
const tarballUrl = 'https://codeload.github.com/nexu-io/open-design/tar.gz/main';
|
||||
const fetcher: ArchiveFetcher = async (u) => {
|
||||
urlsSeen.push(u);
|
||||
if (u === contentsUrl) {
|
||||
return makeResponse('too many requests', 429, 'Too Many Requests');
|
||||
}
|
||||
if (u === tarballUrl) return makeResponse('server unavailable', 503, 'Service Unavailable');
|
||||
return makeResponse('not found', 404, 'Not Found');
|
||||
};
|
||||
|
||||
let error: string | undefined;
|
||||
const source = 'github:nexu-io/open-design@main/plugins/community/import-smoke-test';
|
||||
for await (const ev of installPlugin(db, {
|
||||
source,
|
||||
roots: { userPluginsRoot: pluginsRoot },
|
||||
fetcher,
|
||||
})) {
|
||||
if (ev.kind === 'error') error = ev.message;
|
||||
}
|
||||
|
||||
expect(urlsSeen).toEqual([contentsUrl, tarballUrl]);
|
||||
expect(error).toContain('GitHub install failed');
|
||||
expect(error).toContain('Fetch failed: 503 Service Unavailable');
|
||||
expect(error).toContain(`Tried GitHub fetch URL(s): ${contentsUrl}, ${tarballUrl}`);
|
||||
});
|
||||
|
||||
it('extracts a https://*.tgz source (records source_kind=url)', async () => {
|
||||
const tarball = await buildFixtureTarball({ rootPrefix: 'sample-plugin-1.0.0' });
|
||||
let success = false;
|
||||
|
||||
Reference in New Issue
Block a user