Skip to content

Commit 710e00e

Browse files
authored
use github release artifacts instead of cloning repos when available (#9147)
1 parent 4ef46e4 commit 710e00e

1 file changed

Lines changed: 39 additions & 22 deletions

File tree

packages/cli/src/config/extensions/github.ts

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ export function parseGitHubRepoForReleases(source: string): {
103103
return { owner, repo };
104104
}
105105

106-
async function fetchFromGithub(
106+
async function fetchReleaseFromGithub(
107107
owner: string,
108108
repo: string,
109109
ref?: string,
110-
): Promise<{ assets: Asset[]; tag_name: string }> {
110+
): Promise<GithubReleaseData> {
111111
const endpoint = ref ? `releases/tags/${ref}` : 'releases/latest';
112112
const url = `https://api.github.com/repos/${owner}/${repo}/${endpoint}`;
113113
return await fetchJson(url);
@@ -199,7 +199,7 @@ export async function checkForExtensionUpdate(
199199
}
200200
const { owner, repo } = parseGitHubRepoForReleases(source);
201201

202-
const releaseData = await fetchFromGithub(
202+
const releaseData = await fetchReleaseFromGithub(
203203
owner,
204204
repo,
205205
installMetadata.ref,
@@ -228,32 +228,44 @@ export async function downloadFromGitHubRelease(
228228
const { owner, repo } = parseGitHubRepoForReleases(source);
229229

230230
try {
231-
const releaseData = await fetchFromGithub(owner, repo, ref);
231+
const releaseData = await fetchReleaseFromGithub(owner, repo, ref);
232232
if (!releaseData) {
233233
throw new Error(
234234
`No release data found for ${owner}/${repo} at tag ${ref}`,
235235
);
236236
}
237237

238238
const asset = findReleaseAsset(releaseData.assets);
239-
if (!asset) {
240-
// If there are no release assets, then we just clone the repo using the
241-
// ref the release points to.
242-
await cloneFromGit(
243-
{
244-
...installMetadata,
245-
ref: releaseData.tag_name,
246-
},
247-
destination,
239+
let archiveUrl: string | undefined;
240+
let isTar = false;
241+
let isZip = false;
242+
if (asset) {
243+
archiveUrl = asset.browser_download_url;
244+
} else {
245+
if (releaseData.tarball_url) {
246+
archiveUrl = releaseData.tarball_url;
247+
isTar = true;
248+
} else if (releaseData.zipball_url) {
249+
archiveUrl = releaseData.zipball_url;
250+
isZip = true;
251+
}
252+
}
253+
if (!archiveUrl) {
254+
throw new Error(
255+
`No assets found for release with tag ${releaseData.tag_name}`,
248256
);
249-
return releaseData.tag_name;
250257
}
251-
252-
const downloadedAssetPath = path.join(
258+
let downloadedAssetPath = path.join(
253259
destination,
254-
path.basename(asset.browser_download_url),
260+
path.basename(new URL(archiveUrl).pathname),
255261
);
256-
await downloadFile(asset.browser_download_url, downloadedAssetPath);
262+
if (isTar && !downloadedAssetPath.endsWith('.tar.gz')) {
263+
downloadedAssetPath += '.tar.gz';
264+
} else if (isZip && !downloadedAssetPath.endsWith('.zip')) {
265+
downloadedAssetPath += '.zip';
266+
}
267+
268+
await downloadFile(archiveUrl, downloadedAssetPath);
257269

258270
extractFile(downloadedAssetPath, destination);
259271

@@ -284,6 +296,13 @@ export async function downloadFromGitHubRelease(
284296
}
285297
}
286298

299+
interface GithubReleaseData {
300+
assets: Asset[];
301+
tag_name: string;
302+
tarball_url?: string;
303+
zipball_url?: string;
304+
}
305+
287306
interface Asset {
288307
name: string;
289308
browser_download_url: string;
@@ -326,9 +345,7 @@ export function findReleaseAsset(assets: Asset[]): Asset | undefined {
326345
return undefined;
327346
}
328347

329-
async function fetchJson(
330-
url: string,
331-
): Promise<{ assets: Asset[]; tag_name: string }> {
348+
async function fetchJson<T>(url: string): Promise<T> {
332349
const headers: { 'User-Agent': string; Authorization?: string } = {
333350
'User-Agent': 'gemini-cli',
334351
};
@@ -348,7 +365,7 @@ async function fetchJson(
348365
res.on('data', (chunk) => chunks.push(chunk));
349366
res.on('end', () => {
350367
const data = Buffer.concat(chunks).toString();
351-
resolve(JSON.parse(data) as { assets: Asset[]; tag_name: string });
368+
resolve(JSON.parse(data) as T);
352369
});
353370
})
354371
.on('error', reject);

0 commit comments

Comments
 (0)