From 3ded2789e3b07e2a2ceebf23b7d39c286e266bd9 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:21:35 +0300 Subject: [PATCH] refactor(dotnet-version): Refactor schemas (#21426) --- .../datasource/dotnet-version/index.ts | 89 +++++------------ .../datasource/dotnet-version/schema.ts | 95 ++++++++++--------- 2 files changed, 73 insertions(+), 111 deletions(-) diff --git a/lib/modules/datasource/dotnet-version/index.ts b/lib/modules/datasource/dotnet-version/index.ts index db8fce0494..a544e51754 100644 --- a/lib/modules/datasource/dotnet-version/index.ts +++ b/lib/modules/datasource/dotnet-version/index.ts @@ -1,14 +1,11 @@ -import is from '@sindresorhus/is'; import { cache } from '../../../util/cache/package/decorator'; -import type { HttpResponse } from '../../../util/http/types'; +import * as p from '../../../util/promises'; import { Datasource } from '../datasource'; import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; import { - DotnetRelease, - DotnetReleases, - DotnetReleasesIndex, - DotnetReleasesIndexSchema, - DotnetReleasesSchema, + DotnetRuntimeReleases, + DotnetSdkReleases, + ReleasesIndex, } from './schema'; export class DotnetVersionDatasource extends Datasource { @@ -38,42 +35,29 @@ export class DotnetVersionDatasource extends Datasource { return null; } - let result: ReleaseResult | null = null; - - let raw: HttpResponse<DotnetReleasesIndex> | null = null; try { - raw = await this.http.getJson( - this.defaultRegistryUrls[0], - DotnetReleasesIndexSchema + const registryUrl = this.defaultRegistryUrls[0]; + const { body: urls } = await this.http.getJson( + registryUrl, + ReleasesIndex ); - } catch (err) { - this.handleGenericErrors(err); - } - const body = raw?.body; - if (body) { - const releases: Release[] = []; - const { 'releases-index': releasesIndex } = body; - - for (const { 'releases.json': releasesUrl } of releasesIndex) { - const channelReleases = await this.getChannelReleases( - releasesUrl, - packageName - ); - if (channelReleases) { - releases.push(...channelReleases); - } - } + const channelReleases = await p.map( + urls, + (url) => this.getChannelReleases(url, packageName), + { concurrency: 1, stopOnError: true } + ); + const releases = channelReleases.flat(); const sourceUrl = packageName === 'dotnet-sdk' ? 'https://github.com/dotnet/sdk' : 'https://github.com/dotnet/runtime'; - result = { releases, sourceUrl }; + return { releases, sourceUrl }; + } catch (err) { + this.handleGenericErrors(err); } - - return result; } @cache({ @@ -85,43 +69,14 @@ export class DotnetVersionDatasource extends Datasource { async getChannelReleases( releaseUrl: string, packageName: string - ): Promise<Release[] | null> { - let result: Release[] = []; - - let raw: HttpResponse<DotnetReleases> | null = null; + ): Promise<Release[]> { + const schema = + packageName === 'dotnet-sdk' ? DotnetSdkReleases : DotnetRuntimeReleases; try { - raw = await this.http.getJson(releaseUrl, DotnetReleasesSchema); + const { body } = await this.http.getJson(releaseUrl, schema); + return body; } catch (err) { this.handleGenericErrors(err); } - - const body = raw?.body; - if (body) { - const type = DotnetVersionDatasource.getType(packageName); - const { releases: releases } = body; - result = releases - .filter( - ( - release - ): release is { - [P in keyof DotnetRelease]: NonNullable<DotnetRelease[P]>; - } => { - return !is.nullOrUndefined(release[type]); - } - ) - .map((release) => { - return { - version: release[type].version, - releaseTimestamp: release['release-date'], - changelogUrl: release['release-notes'], - }; - }); - } - - return result; - } - - private static getType(packageName: string): 'sdk' | 'runtime' { - return packageName === 'dotnet-sdk' ? 'sdk' : 'runtime'; } } diff --git a/lib/modules/datasource/dotnet-version/schema.ts b/lib/modules/datasource/dotnet-version/schema.ts index 4f16fdb193..0985f96634 100644 --- a/lib/modules/datasource/dotnet-version/schema.ts +++ b/lib/modules/datasource/dotnet-version/schema.ts @@ -1,52 +1,59 @@ import { z } from 'zod'; +import { looseArray } from '../../../util/schema-utils'; +import type { Release } from '../types'; -const Product = z.union([z.literal('.NET Core'), z.literal('.NET')]); -const SupportPhase = z.union([ - z.literal('current'), - z.literal('eol'), - z.literal('lts'), - z.literal('maintenance'), - z.literal('preview'), - z.literal('rc'), -]); -const ReleaseIndex = z.object({ - 'channel-version': z.string(), - 'latest-release': z.string(), - 'latest-release-date': z.string(), - security: z.boolean(), - 'latest-runtime': z.string(), - 'latest-sdk': z.string(), - product: Product, - 'support-phase': SupportPhase, - 'eol-date': z.string().nullable(), - 'releases.json': z.string(), -}); -export const DotnetReleasesIndexSchema = z.object({ - 'releases-index': z.array(ReleaseIndex), -}); +export const ReleasesIndex = z + .object({ + 'releases-index': looseArray( + z + .object({ + 'releases.json': z.string(), + }) + .transform(({ 'releases.json': releasesUrl }) => releasesUrl) + ), + }) + .transform(({ 'releases-index': releasesIndex }) => releasesIndex); -const ReleaseDetails = z.object({ - version: z.string(), - 'version-display': z.string(), -}); -const ReleaseSchema = z.object({ +const ReleaseBase = z.object({ 'release-date': z.string(), - 'release-version': z.string(), - security: z.boolean(), 'release-notes': z.string(), - runtime: z.nullable(ReleaseDetails), - sdk: z.nullable(ReleaseDetails), }); -export const DotnetReleasesSchema = z.object({ - 'channel-version': z.string(), - 'latest-release': z.string(), - 'latest-release-date': z.string(), - 'latest-runtime': z.string(), - 'latest-sdk': z.string(), - 'support-phase': SupportPhase, - releases: z.array(ReleaseSchema), +const ReleaseDetails = z.object({ + version: z.string(), }); -export type DotnetReleasesIndex = z.infer<typeof DotnetReleasesIndexSchema>; -export type DotnetReleases = z.infer<typeof DotnetReleasesSchema>; -export type DotnetRelease = z.infer<typeof ReleaseSchema>; +export const DotnetSdkReleases = z + .object({ + releases: looseArray( + ReleaseBase.extend({ + sdk: ReleaseDetails, + }) + ), + }) + .transform(({ releases }): Release[] => + releases.map( + ({ + sdk: { version }, + 'release-date': releaseTimestamp, + 'release-notes': changelogUrl, + }) => ({ version, releaseTimestamp, changelogUrl }) + ) + ); + +export const DotnetRuntimeReleases = z + .object({ + releases: looseArray( + ReleaseBase.extend({ + runtime: ReleaseDetails, + }) + ), + }) + .transform(({ releases }): Release[] => + releases.map( + ({ + runtime: { version }, + 'release-date': releaseTimestamp, + 'release-notes': changelogUrl, + }) => ({ version, releaseTimestamp, changelogUrl }) + ) + ); -- GitLab