Skip to content
Snippets Groups Projects
Unverified Commit bc8e06e1 authored by Sergei Zharinov's avatar Sergei Zharinov Committed by GitHub
Browse files

refactor(rubygems): Decouple metadata fetching from versions fetching (#22808)

parent 932012fa
No related branches found
No related tags found
No related merge requests found
...@@ -6,7 +6,7 @@ import { getQueryString, joinUrlParts, parseUrl } from '../../../util/url'; ...@@ -6,7 +6,7 @@ import { getQueryString, joinUrlParts, parseUrl } from '../../../util/url';
import * as rubyVersioning from '../../versioning/ruby'; import * as rubyVersioning from '../../versioning/ruby';
import { Datasource } from '../datasource'; import { Datasource } from '../datasource';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
import { GemVersions, GemsInfo, MarshalledVersionInfo } from './schema'; import { GemMetadata, GemVersions, MarshalledVersionInfo } from './schema';
import { VersionsEndpointCache } from './versions-endpoint-cache'; import { VersionsEndpointCache } from './versions-endpoint-cache';
export class RubyGemsDatasource extends Datasource { export class RubyGemsDatasource extends Datasource {
...@@ -57,39 +57,42 @@ export class RubyGemsDatasource extends Datasource { ...@@ -57,39 +57,42 @@ export class RubyGemsDatasource extends Datasource {
cachedVersions.type === 'not-supported' && cachedVersions.type === 'not-supported' &&
registryHostname !== 'rubygems.org' registryHostname !== 'rubygems.org'
) { ) {
const hostname = registryHostname; if (
return hostname === 'rubygems.pkg.github.com' || registryHostname === 'rubygems.pkg.github.com' ||
hostname === 'gitlab.com' registryHostname === 'gitlab.com'
? await this.getDependencyFallback(registryUrl, packageName) ) {
: await this.getDependency(registryUrl, packageName); return await this.getReleasesViaFallbackAPI(registryUrl, packageName);
}
const gemMetadata = await this.fetchGemMetadata(
registryUrl,
packageName
);
if (!gemMetadata) {
return await this.getReleasesViaFallbackAPI(registryUrl, packageName);
}
return await this.getReleasesViaAPI(
registryUrl,
packageName,
gemMetadata
);
} }
return null;
} catch (error) { } catch (error) {
this.handleGenericErrors(error); this.handleGenericErrors(error);
} }
return null;
} }
async getDependencyFallback( async fetchGemMetadata(
registryUrl: string, registryUrl: string,
packageName: string packageName: string
): Promise<ReleaseResult | null> { ): Promise<GemMetadata | null> {
const path = joinUrlParts(registryUrl, `/api/v1/dependencies`);
const query = getQueryString({ gems: packageName });
const url = `${path}?${query}`;
const { body: buffer } = await this.http.getBuffer(url);
const data = Marshal.parse(buffer);
return MarshalledVersionInfo.parse(data);
}
async fetchGemsInfo(
registryUrl: string,
packageName: string
): Promise<GemsInfo | null> {
try { try {
const { body } = await this.http.getJson( const { body } = await this.http.getJson(
joinUrlParts(registryUrl, '/api/v1/gems', `${packageName}.json`), joinUrlParts(registryUrl, '/api/v1/gems', `${packageName}.json`),
GemsInfo GemMetadata
); );
return body; return body;
} catch (err) { } catch (err) {
...@@ -124,41 +127,48 @@ export class RubyGemsDatasource extends Datasource { ...@@ -124,41 +127,48 @@ export class RubyGemsDatasource extends Datasource {
} }
} }
async getDependency( async getReleasesViaAPI(
registryUrl: string, registryUrl: string,
packageName: string packageName: string,
gemMetadata: GemMetadata
): Promise<ReleaseResult | null> { ): Promise<ReleaseResult | null> {
const info = await this.fetchGemsInfo(registryUrl, packageName); const gemVersions = await this.fetchGemVersions(registryUrl, packageName);
if (!info) {
return await this.getDependencyFallback(registryUrl, packageName);
}
let releases: Release[] | null = null; let releases: Release[] | null = null;
const gemVersions = await this.fetchGemVersions(registryUrl, packageName);
if (gemVersions?.length) { if (gemVersions?.length) {
releases = gemVersions; releases = gemVersions;
} else if (info.version) { } else if (gemMetadata.latestVersion) {
releases = [{ version: info.version }]; releases = [{ version: gemMetadata.latestVersion }];
} } else {
if (!releases) {
return null; return null;
} }
const result: ReleaseResult = { releases }; const result: ReleaseResult = { releases };
if (info.changelogUrl) { if (gemMetadata.changelogUrl) {
result.changelogUrl = info.changelogUrl; result.changelogUrl = gemMetadata.changelogUrl;
} }
if (info.homepage) { if (gemMetadata.homepage) {
result.homepage = info.homepage; result.homepage = gemMetadata.homepage;
} }
if (info.sourceUrl) { if (gemMetadata.sourceUrl) {
result.sourceUrl = info.sourceUrl; result.sourceUrl = gemMetadata.sourceUrl;
} }
return result; return result;
} }
async getReleasesViaFallbackAPI(
registryUrl: string,
packageName: string
): Promise<ReleaseResult | null> {
const path = joinUrlParts(registryUrl, `/api/v1/dependencies`);
const query = getQueryString({ gems: packageName });
const url = `${path}?${query}`;
const { body: buffer } = await this.http.getBuffer(url);
const data = Marshal.parse(buffer);
return MarshalledVersionInfo.parse(data);
}
} }
...@@ -14,7 +14,7 @@ export const MarshalledVersionInfo = LooseArray( ...@@ -14,7 +14,7 @@ export const MarshalledVersionInfo = LooseArray(
.nullable() .nullable()
.catch(null); .catch(null);
export const GemsInfo = z export const GemMetadata = z
.object({ .object({
name: z.string().transform((x) => x.toLowerCase()), name: z.string().transform((x) => x.toLowerCase()),
version: z.string().nullish().catch(null), version: z.string().nullish().catch(null),
...@@ -31,13 +31,13 @@ export const GemsInfo = z ...@@ -31,13 +31,13 @@ export const GemsInfo = z
source_code_uri: sourceUrl, source_code_uri: sourceUrl,
}) => ({ }) => ({
packageName, packageName,
version, latestVersion: version,
changelogUrl, changelogUrl,
homepage, homepage,
sourceUrl, sourceUrl,
}) })
); );
export type GemsInfo = z.infer<typeof GemsInfo>; export type GemMetadata = z.infer<typeof GemMetadata>;
export const GemVersions = LooseArray( export const GemVersions = LooseArray(
z z
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment