From 9b4e5150248a6b0026acf9c73bb00a295cba4c48 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Fri, 17 Jan 2025 11:18:00 -0300 Subject: [PATCH] refactor(http): Separate `getJson` and `getJsonUnchecked` (#33651) --- lib/config/presets/github/index.ts | 2 +- lib/config/presets/gitlab/index.ts | 2 +- lib/config/presets/npm/index.ts | 2 +- .../datasource/bitbucket-tags/index.ts | 18 ++++-- lib/modules/datasource/conan/index.ts | 2 +- lib/modules/datasource/conda/index.ts | 2 +- lib/modules/datasource/crate/index.ts | 2 +- lib/modules/datasource/custom/formats/json.ts | 2 +- lib/modules/datasource/dart-version/index.ts | 2 +- lib/modules/datasource/dart/index.ts | 2 +- lib/modules/datasource/docker/common.ts | 4 +- lib/modules/datasource/docker/index.ts | 4 +- .../datasource/flutter-version/index.ts | 2 +- .../github-release-attachments/index.ts | 14 +++-- lib/modules/datasource/github-tags/index.ts | 2 +- .../datasource/gitlab-packages/index.ts | 4 +- .../datasource/gitlab-releases/index.ts | 2 +- lib/modules/datasource/gitlab-tags/index.ts | 8 ++- lib/modules/datasource/go/releases-goproxy.ts | 4 +- .../datasource/gradle-version/index.ts | 3 +- lib/modules/datasource/hermit/index.ts | 2 +- lib/modules/datasource/java-version/index.ts | 3 +- .../datasource/jenkins-plugins/index.ts | 2 +- lib/modules/datasource/node-version/index.ts | 2 +- lib/modules/datasource/npm/get.ts | 2 +- lib/modules/datasource/nuget/v3.ts | 8 ++- lib/modules/datasource/packagist/index.ts | 10 +-- lib/modules/datasource/pod/index.ts | 2 +- lib/modules/datasource/puppet-forge/index.ts | 2 +- lib/modules/datasource/pypi/index.ts | 4 +- lib/modules/datasource/repology/index.ts | 2 +- .../datasource/terraform-module/base.ts | 2 +- .../datasource/terraform-module/index.ts | 5 +- .../datasource/terraform-provider/index.ts | 21 ++++--- .../platform/bitbucket-server/index.ts | 20 +++--- .../platform/bitbucket-server/utils.ts | 2 +- lib/modules/platform/bitbucket/comments.ts | 2 +- lib/modules/platform/bitbucket/index.ts | 22 +++---- lib/modules/platform/bitbucket/pr-cache.ts | 2 +- lib/modules/platform/gerrit/client.ts | 29 ++++----- lib/modules/platform/gitea/gitea-helper.ts | 31 +++++----- lib/modules/platform/gitea/pr-cache.ts | 11 ++-- lib/modules/platform/github/index.ts | 43 ++++++++----- lib/modules/platform/github/pr.ts | 2 +- lib/modules/platform/github/user.ts | 22 ++++--- lib/modules/platform/gitlab/http.ts | 11 +++- lib/modules/platform/gitlab/index.ts | 37 ++++++----- lib/modules/platform/gitlab/merge-request.ts | 2 +- lib/util/http/bitbucket.spec.ts | 10 ++- .../repository-http-cache-provider.spec.ts | 22 +++---- lib/util/http/gerrit.spec.ts | 2 +- lib/util/http/gitea.spec.ts | 13 ++-- lib/util/http/github.spec.ts | 28 ++++++--- lib/util/http/gitlab.spec.ts | 14 +++-- lib/util/http/index.spec.ts | 2 +- lib/util/http/index.ts | 62 +++++++++++++------ lib/util/merge-confidence/index.ts | 4 +- .../update/pr/changelog/github/index.ts | 6 +- .../update/pr/changelog/gitlab/index.ts | 11 ++-- tools/docs/github-query-items.ts | 2 +- 60 files changed, 333 insertions(+), 229 deletions(-) diff --git a/lib/config/presets/github/index.ts b/lib/config/presets/github/index.ts index 06cca040ac..a906323310 100644 --- a/lib/config/presets/github/index.ts +++ b/lib/config/presets/github/index.ts @@ -24,7 +24,7 @@ export async function fetchJSONFile( logger.trace({ url }, `Preset URL`); let res: { body: { content: string } }; try { - res = await http.getJson(url); + res = await http.getJsonUnchecked(url); } catch (err) { // istanbul ignore if: not testable with nock if (err instanceof ExternalHostError) { diff --git a/lib/config/presets/gitlab/index.ts b/lib/config/presets/gitlab/index.ts index 300bf3e51f..2af74c99d0 100644 --- a/lib/config/presets/gitlab/index.ts +++ b/lib/config/presets/gitlab/index.ts @@ -14,7 +14,7 @@ async function getDefaultBranchName( urlEncodedPkgName: string, endpoint: string, ): Promise<string> { - const res = await gitlabApi.getJson<GitlabProject>( + const res = await gitlabApi.getJsonUnchecked<GitlabProject>( `${endpoint}projects/${urlEncodedPkgName}`, ); return res.body.default_branch ?? 'master'; // should never happen, but we keep this to ensure the current behavior diff --git a/lib/config/presets/npm/index.ts b/lib/config/presets/npm/index.ts index c01c5c70e0..e50201915c 100644 --- a/lib/config/presets/npm/index.ts +++ b/lib/config/presets/npm/index.ts @@ -31,7 +31,7 @@ export async function getPreset({ 'Using npm packages for Renovate presets is now deprecated. Please migrate to repository-based presets instead.', ); const packageUrl = resolvePackageUrl(registryUrl, pkg); - const body = (await http.getJson<NpmResponse>(packageUrl)).body; + const body = (await http.getJsonUnchecked<NpmResponse>(packageUrl)).body; // TODO: check null #22198 dep = body.versions![body['dist-tags']!.latest]; } catch { diff --git a/lib/modules/datasource/bitbucket-tags/index.ts b/lib/modules/datasource/bitbucket-tags/index.ts index f8b59d2319..1ca5ddf168 100644 --- a/lib/modules/datasource/bitbucket-tags/index.ts +++ b/lib/modules/datasource/bitbucket-tags/index.ts @@ -65,9 +65,12 @@ export class BitbucketTagsDatasource extends Datasource { }: GetReleasesConfig): Promise<ReleaseResult | null> { const url = `/2.0/repositories/${repo}/refs/tags`; const bitbucketTags = ( - await this.bitbucketHttp.getJson<PagedResult<BitbucketTag>>(url, { - paginate: true, - }) + await this.bitbucketHttp.getJsonUnchecked<PagedResult<BitbucketTag>>( + url, + { + paginate: true, + }, + ) ).body.values; const dependency: ReleaseResult = { @@ -96,8 +99,9 @@ export class BitbucketTagsDatasource extends Datasource { ): Promise<string | null> { const url = `/2.0/repositories/${repo}/refs/tags/${tag}`; - const bitbucketTag = (await this.bitbucketHttp.getJson<BitbucketTag>(url)) - .body; + const bitbucketTag = ( + await this.bitbucketHttp.getJsonUnchecked<BitbucketTag>(url) + ).body; return bitbucketTag.target?.hash ?? null; } @@ -136,7 +140,9 @@ export class BitbucketTagsDatasource extends Datasource { const url = `/2.0/repositories/${repo}/commits/${mainBranch}`; const bitbucketCommits = ( - await this.bitbucketHttp.getJson<PagedResult<BitbucketCommit>>(url) + await this.bitbucketHttp.getJsonUnchecked<PagedResult<BitbucketCommit>>( + url, + ) ).body; if (bitbucketCommits.values.length === 0) { diff --git a/lib/modules/datasource/conan/index.ts b/lib/modules/datasource/conan/index.ts index 0319d16719..079600bd4d 100644 --- a/lib/modules/datasource/conan/index.ts +++ b/lib/modules/datasource/conan/index.ts @@ -126,7 +126,7 @@ export class ConanDatasource extends Datasource { ); try { - const rep = await this.http.getJson(lookupUrl); + const rep = await this.http.getJsonUnchecked(lookupUrl); const conanJson = ConanJSON.parse(rep.body); if (conanJson) { logger.trace({ lookupUrl }, 'Got conan api result'); diff --git a/lib/modules/datasource/conda/index.ts b/lib/modules/datasource/conda/index.ts index 980eb8de9b..6985d4d4cd 100644 --- a/lib/modules/datasource/conda/index.ts +++ b/lib/modules/datasource/conda/index.ts @@ -52,7 +52,7 @@ export class CondaDatasource extends Datasource { let response: { body: CondaPackage }; try { - response = await this.http.getJson(url); + response = await this.http.getJsonUnchecked(url); result.homepage = response.body.html_url; result.sourceUrl = response.body.dev_url; diff --git a/lib/modules/datasource/crate/index.ts b/lib/modules/datasource/crate/index.ts index 29eb0b8498..7e0be2656c 100644 --- a/lib/modules/datasource/crate/index.ts +++ b/lib/modules/datasource/crate/index.ts @@ -156,7 +156,7 @@ export class CrateDatasource extends Datasource { try { type Response = { crate: CrateMetadata }; - const response = await this.http.getJson<Response>(crateUrl); + const response = await this.http.getJsonUnchecked<Response>(crateUrl); return response.body.crate; } catch (err) { logger.warn( diff --git a/lib/modules/datasource/custom/formats/json.ts b/lib/modules/datasource/custom/formats/json.ts index ead333419b..63b7fb70ad 100644 --- a/lib/modules/datasource/custom/formats/json.ts +++ b/lib/modules/datasource/custom/formats/json.ts @@ -4,7 +4,7 @@ import type { CustomDatasourceFetcher } from './types'; export class JSONFetcher implements CustomDatasourceFetcher { async fetch(http: Http, registryURL: string): Promise<unknown> { - const response = await http.getJson(registryURL); + const response = await http.getJsonUnchecked(registryURL); return response.body; } diff --git a/lib/modules/datasource/dart-version/index.ts b/lib/modules/datasource/dart-version/index.ts index 23f95ccab8..06b5440f8f 100644 --- a/lib/modules/datasource/dart-version/index.ts +++ b/lib/modules/datasource/dart-version/index.ts @@ -41,7 +41,7 @@ export class DartVersionDatasource extends Datasource { try { for (const channel of this.channels) { const resp = ( - await this.http.getJson<DartResponse>( + await this.http.getJsonUnchecked<DartResponse>( `${registryUrl}/storage/v1/b/dart-archive/o?delimiter=%2F&prefix=channels%2F${channel}%2Frelease%2F&alt=json`, ) ).body; diff --git a/lib/modules/datasource/dart/index.ts b/lib/modules/datasource/dart/index.ts index 88e549cfeb..80ea1cf8e3 100644 --- a/lib/modules/datasource/dart/index.ts +++ b/lib/modules/datasource/dart/index.ts @@ -37,7 +37,7 @@ export class DartDatasource extends Datasource { let raw: HttpResponse<DartResult> | null = null; try { - raw = await this.http.getJson<DartResult>(pkgUrl); + raw = await this.http.getJsonUnchecked<DartResult>(pkgUrl); } catch (err) { this.handleGenericErrors(err); } diff --git a/lib/modules/datasource/docker/common.ts b/lib/modules/datasource/docker/common.ts index 1ccc12c66a..b838b25d88 100644 --- a/lib/modules/datasource/docker/common.ts +++ b/lib/modules/datasource/docker/common.ts @@ -63,7 +63,7 @@ export async function getAuthHeaders( ? await http.get(apiCheckUrl, options) : // use json request, as this will be cached for tags, so it returns json // TODO: add cache test - await http.getJson(apiCheckUrl, options); + await http.getJsonUnchecked(apiCheckUrl, options); if (apiCheckResponse.statusCode === 200) { logger.debug(`No registry auth required for ${apiCheckUrl}`); @@ -193,7 +193,7 @@ export async function getAuthHeaders( ); opts.noAuth = true; const authResponse = ( - await http.getJson<{ token?: string; access_token?: string }>( + await http.getJsonUnchecked<{ token?: string; access_token?: string }>( authUrl.href, opts, ) diff --git a/lib/modules/datasource/docker/index.ts b/lib/modules/datasource/docker/index.ts index 3e4339d0fa..dec17989b8 100644 --- a/lib/modules/datasource/docker/index.ts +++ b/lib/modules/datasource/docker/index.ts @@ -629,7 +629,7 @@ export class DockerDatasource extends Datasource { // typescript issue :-/ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const res = (await this.http.getJson<QuayRestDockerTags>( + const res = (await this.http.getJsonUnchecked<QuayRestDockerTags>( url, )) as HttpResponse<QuayRestDockerTags>; const pageTags = res.body.tags.map((tag) => tag.name); @@ -671,7 +671,7 @@ export class DockerDatasource extends Datasource { do { let res: HttpResponse<{ tags: string[] }>; try { - res = await this.http.getJson<{ tags: string[] }>(url, { + res = await this.http.getJsonUnchecked<{ tags: string[] }>(url, { headers, noAuth: true, }); diff --git a/lib/modules/datasource/flutter-version/index.ts b/lib/modules/datasource/flutter-version/index.ts index 46dd2ce47e..5069f9779e 100644 --- a/lib/modules/datasource/flutter-version/index.ts +++ b/lib/modules/datasource/flutter-version/index.ts @@ -43,7 +43,7 @@ export class FlutterVersionDatasource extends Datasource { }; try { const resp = ( - await this.http.getJson<FlutterResponse>( + await this.http.getJsonUnchecked<FlutterResponse>( `${registryUrl}/flutter_infra_release/releases/releases_linux.json`, ) ).body; diff --git a/lib/modules/datasource/github-release-attachments/index.ts b/lib/modules/datasource/github-release-attachments/index.ts index 14caabb969..2b95ca53fe 100644 --- a/lib/modules/datasource/github-release-attachments/index.ts +++ b/lib/modules/datasource/github-release-attachments/index.ts @@ -210,9 +210,10 @@ export class GithubReleaseAttachmentsDatasource extends Datasource { } const apiBaseUrl = getApiBaseUrl(registryUrl); - const { body: currentRelease } = await this.http.getJson<GithubRestRelease>( - `${apiBaseUrl}repos/${repo}/releases/tags/${currentValue}`, - ); + const { body: currentRelease } = + await this.http.getJsonUnchecked<GithubRestRelease>( + `${apiBaseUrl}repos/${repo}/releases/tags/${currentValue}`, + ); const digestAsset = await this.findDigestAsset( currentRelease, currentDigest, @@ -221,9 +222,10 @@ export class GithubReleaseAttachmentsDatasource extends Datasource { if (!digestAsset || newValue === currentValue) { newDigest = currentDigest; } else { - const { body: newRelease } = await this.http.getJson<GithubRestRelease>( - `${apiBaseUrl}repos/${repo}/releases/tags/${newValue}`, - ); + const { body: newRelease } = + await this.http.getJsonUnchecked<GithubRestRelease>( + `${apiBaseUrl}repos/${repo}/releases/tags/${newValue}`, + ); newDigest = await this.mapDigestAssetToRelease(digestAsset, newRelease); } return newDigest; diff --git a/lib/modules/datasource/github-tags/index.ts b/lib/modules/datasource/github-tags/index.ts index 0fdca9b6b3..3887179303 100644 --- a/lib/modules/datasource/github-tags/index.ts +++ b/lib/modules/datasource/github-tags/index.ts @@ -43,7 +43,7 @@ export class GithubTagsDatasource extends Datasource { let digest: string | null = null; try { const url = `${apiBaseUrl}repos/${githubRepo}/commits?per_page=1`; - const res = await this.http.getJson<{ sha: string }[]>(url); + const res = await this.http.getJsonUnchecked<{ sha: string }[]>(url); digest = res.body[0].sha; } catch (err) { logger.debug( diff --git a/lib/modules/datasource/gitlab-packages/index.ts b/lib/modules/datasource/gitlab-packages/index.ts index 28d0483aae..651fb6d014 100644 --- a/lib/modules/datasource/gitlab-packages/index.ts +++ b/lib/modules/datasource/gitlab-packages/index.ts @@ -74,7 +74,9 @@ export class GitlabPackagesDatasource extends Datasource { let response: GitlabPackage[]; try { response = ( - await this.http.getJson<GitlabPackage[]>(apiUrl, { paginate: true }) + await this.http.getJsonUnchecked<GitlabPackage[]>(apiUrl, { + paginate: true, + }) ).body; result.releases = response diff --git a/lib/modules/datasource/gitlab-releases/index.ts b/lib/modules/datasource/gitlab-releases/index.ts index 54ba562796..f82a5eb68b 100644 --- a/lib/modules/datasource/gitlab-releases/index.ts +++ b/lib/modules/datasource/gitlab-releases/index.ts @@ -43,7 +43,7 @@ export class GitlabReleasesDatasource extends Datasource { try { const gitlabReleasesResponse = ( - await this.http.getJson<GitlabRelease[]>(apiUrl) + await this.http.getJsonUnchecked<GitlabRelease[]>(apiUrl) ).body; return { diff --git a/lib/modules/datasource/gitlab-tags/index.ts b/lib/modules/datasource/gitlab-tags/index.ts index 89ba14da0d..77690fcce5 100644 --- a/lib/modules/datasource/gitlab-tags/index.ts +++ b/lib/modules/datasource/gitlab-tags/index.ts @@ -48,7 +48,7 @@ export class GitlabTagsDatasource extends Datasource { ); const gitlabTags = ( - await this.http.getJson<GitlabTag[]>(url, { + await this.http.getJsonUnchecked<GitlabTag[]>(url, { paginate: true, }) ).body; @@ -94,7 +94,8 @@ export class GitlabTagsDatasource extends Datasource { `repository/commits/`, newValue, ); - const gitlabCommits = await this.http.getJson<GitlabCommit>(url); + const gitlabCommits = + await this.http.getJsonUnchecked<GitlabCommit>(url); digest = gitlabCommits.body.id; } else { const url = joinUrlParts( @@ -103,7 +104,8 @@ export class GitlabTagsDatasource extends Datasource { urlEncodedRepo, `repository/commits?per_page=1`, ); - const gitlabCommits = await this.http.getJson<GitlabCommit[]>(url); + const gitlabCommits = + await this.http.getJsonUnchecked<GitlabCommit[]>(url); digest = gitlabCommits.body[0].id; } } catch (err) { diff --git a/lib/modules/datasource/go/releases-goproxy.ts b/lib/modules/datasource/go/releases-goproxy.ts index 1a2a9d301c..4464a2e33b 100644 --- a/lib/modules/datasource/go/releases-goproxy.ts +++ b/lib/modules/datasource/go/releases-goproxy.ts @@ -164,7 +164,7 @@ export class GoProxyDatasource extends Datasource { '@v', `${version}.info`, ); - const res = await this.http.getJson<VersionInfo>(url); + const res = await this.http.getJsonUnchecked<VersionInfo>(url); const result: Release = { version: res.body.Version, @@ -187,7 +187,7 @@ export class GoProxyDatasource extends Datasource { this.encodeCase(packageName), '@latest', ); - const res = await this.http.getJson<VersionInfo>(url); + const res = await this.http.getJsonUnchecked<VersionInfo>(url); return res.body.Version; } catch (err) { logger.trace({ err }, 'Failed to get latest version'); diff --git a/lib/modules/datasource/gradle-version/index.ts b/lib/modules/datasource/gradle-version/index.ts index bb6368e198..4667b68919 100644 --- a/lib/modules/datasource/gradle-version/index.ts +++ b/lib/modules/datasource/gradle-version/index.ts @@ -46,7 +46,8 @@ export class GradleVersionDatasource extends Datasource { let releases: Release[]; try { - const response = await this.http.getJson<GradleRelease[]>(registryUrl); + const response = + await this.http.getJsonUnchecked<GradleRelease[]>(registryUrl); releases = response.body .filter((release) => !release.snapshot && !release.nightly) .map((release) => { diff --git a/lib/modules/datasource/hermit/index.ts b/lib/modules/datasource/hermit/index.ts index 5e6b53bd4b..8a920b3c3d 100644 --- a/lib/modules/datasource/hermit/index.ts +++ b/lib/modules/datasource/hermit/index.ts @@ -125,7 +125,7 @@ export class HermitDatasource extends Datasource { const apiBaseUrl = getApiBaseUrl(`https://${host}`); - const indexRelease = await this.http.getJson<GithubRestRelease>( + const indexRelease = await this.http.getJsonUnchecked<GithubRestRelease>( `${apiBaseUrl}repos/${owner}/${repo}/releases/tags/index`, ); diff --git a/lib/modules/datasource/java-version/index.ts b/lib/modules/datasource/java-version/index.ts index 1e1d68d4a2..4924b0c8ff 100644 --- a/lib/modules/datasource/java-version/index.ts +++ b/lib/modules/datasource/java-version/index.ts @@ -31,7 +31,8 @@ export class JavaVersionDatasource extends Datasource { ): Promise<Release[] | null> { const pgUrl = `${url}&page=${page}`; try { - const pgRes = await this.http.getJson<AdoptiumJavaResponse>(pgUrl); + const pgRes = + await this.http.getJsonUnchecked<AdoptiumJavaResponse>(pgUrl); return ( pgRes?.body?.versions?.map(({ semver }) => ({ version: semver, diff --git a/lib/modules/datasource/jenkins-plugins/index.ts b/lib/modules/datasource/jenkins-plugins/index.ts index db434ba666..1f846c1c24 100644 --- a/lib/modules/datasource/jenkins-plugins/index.ts +++ b/lib/modules/datasource/jenkins-plugins/index.ts @@ -117,7 +117,7 @@ export class JenkinsPluginsDatasource extends Datasource { try { logger.debug(`jenkins-plugins: Fetching Jenkins plugins from ${url}`); const startTime = Date.now(); - response = (await this.http.getJson<T>(url)).body; + response = (await this.http.getJsonUnchecked<T>(url)).body; const durationMs = Math.round(Date.now() - startTime); logger.debug( { durationMs }, diff --git a/lib/modules/datasource/node-version/index.ts b/lib/modules/datasource/node-version/index.ts index c37c707c32..aba6bd7da8 100644 --- a/lib/modules/datasource/node-version/index.ts +++ b/lib/modules/datasource/node-version/index.ts @@ -46,7 +46,7 @@ export class NodeVersionDatasource extends Datasource { }; try { const resp = ( - await this.http.getJson<NodeRelease[]>( + await this.http.getJsonUnchecked<NodeRelease[]>( joinUrlParts(registryUrl, 'index.json'), ) ).body; diff --git a/lib/modules/datasource/npm/get.ts b/lib/modules/datasource/npm/get.ts index cd8ea585ec..ec6cc4e557 100644 --- a/lib/modules/datasource/npm/get.ts +++ b/lib/modules/datasource/npm/get.ts @@ -144,7 +144,7 @@ export async function getDependency( }); } - const raw = await http.getJson<NpmResponse>(packageUrl, options); + const raw = await http.getJsonUnchecked<NpmResponse>(packageUrl, options); if (cachedResult?.cacheData && raw.statusCode === 304) { logger.trace(`Cached npm result for ${packageName} is revalidated`); HttpCacheStats.incRemoteHits(packageUrl); diff --git a/lib/modules/datasource/nuget/v3.ts b/lib/modules/datasource/nuget/v3.ts index 2e6e289bf0..b773b5865f 100644 --- a/lib/modules/datasource/nuget/v3.ts +++ b/lib/modules/datasource/nuget/v3.ts @@ -52,7 +52,8 @@ export class NugetV3Api { ); // istanbul ignore else: currently not testable if (!servicesIndexRaw) { - servicesIndexRaw = (await http.getJson<ServicesIndexRaw>(url)).body; + servicesIndexRaw = (await http.getJsonUnchecked<ServicesIndexRaw>(url)) + .body; await packageCache.set( NugetV3Api.cacheNamespace, responseCacheKey, @@ -132,7 +133,7 @@ export class NugetV3Api { let items = catalogPage.items; if (!items) { const url = catalogPage['@id']; - const catalogPageFull = await http.getJson<CatalogPage>(url); + const catalogPageFull = await http.getJsonUnchecked<CatalogPage>(url); items = catalogPageFull.body.items; } return items.map(({ catalogEntry }) => catalogEntry); @@ -146,7 +147,8 @@ export class NugetV3Api { ): Promise<ReleaseResult | null> { const baseUrl = feedUrl.replace(regEx(/\/*$/), ''); const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`; - const packageRegistration = await http.getJson<PackageRegistration>(url); + const packageRegistration = + await http.getJsonUnchecked<PackageRegistration>(url); const catalogPages = packageRegistration.body.items || []; const catalogPagesQueue = catalogPages.map( (page) => (): Promise<CatalogEntry[]> => this.getCatalogEntry(http, page), diff --git a/lib/modules/datasource/packagist/index.ts b/lib/modules/datasource/packagist/index.ts index 1284745a7e..da8573de0b 100644 --- a/lib/modules/datasource/packagist/index.ts +++ b/lib/modules/datasource/packagist/index.ts @@ -49,13 +49,13 @@ export class PackagistDatasource extends Datasource { return username && password ? { username, password } : {}; } - private async getJson<T, U extends z.ZodSchema<T>>( + private async getJson<Schema extends z.ZodType<any, any, any>>( url: string, - schema: U, - ): Promise<z.infer<typeof schema>> { + schema: Schema, + ): Promise<z.infer<Schema>> { const opts = PackagistDatasource.getHostOpts(url); - const { body } = await this.http.getJson(url, opts); - return schema.parse(body); + const { body } = await this.http.getJson(url, opts, schema); + return body; } @cache({ diff --git a/lib/modules/datasource/pod/index.ts b/lib/modules/datasource/pod/index.ts index 86aa044908..ca728d3955 100644 --- a/lib/modules/datasource/pod/index.ts +++ b/lib/modules/datasource/pod/index.ts @@ -125,7 +125,7 @@ export class PodDatasource extends Datasource { packageName: string, ): Promise<T | null> { try { - const resp = await this.githubHttp.getJson<T>(url); + const resp = await this.githubHttp.getJsonUnchecked<T>(url); if (resp?.body) { return resp.body; } diff --git a/lib/modules/datasource/puppet-forge/index.ts b/lib/modules/datasource/puppet-forge/index.ts index f656f4d5fa..9bed72a544 100644 --- a/lib/modules/datasource/puppet-forge/index.ts +++ b/lib/modules/datasource/puppet-forge/index.ts @@ -28,7 +28,7 @@ export class PuppetForgeDatasource extends Datasource { let module: PuppetModule; try { - const response = await this.http.getJson<PuppetModule>(url); + const response = await this.http.getJsonUnchecked<PuppetModule>(url); module = response.body; } catch (err) { this.handleGenericErrors(err); diff --git a/lib/modules/datasource/pypi/index.ts b/lib/modules/datasource/pypi/index.ts index 3e8812116e..16bcb1bcc9 100644 --- a/lib/modules/datasource/pypi/index.ts +++ b/lib/modules/datasource/pypi/index.ts @@ -110,7 +110,9 @@ export class PypiDatasource extends Datasource { const dependency: ReleaseResult = { releases: [] }; logger.trace({ lookupUrl }, 'Pypi api got lookup'); const headers = await this.getAuthHeaders(lookupUrl); - const rep = await this.http.getJson<PypiJSON>(lookupUrl, { headers }); + const rep = await this.http.getJsonUnchecked<PypiJSON>(lookupUrl, { + headers, + }); const dep = rep?.body; if (!dep) { logger.trace({ dependency: packageName }, 'pip package not found'); diff --git a/lib/modules/datasource/repology/index.ts b/lib/modules/datasource/repology/index.ts index 987a2c20ea..45295b7ae7 100644 --- a/lib/modules/datasource/repology/index.ts +++ b/lib/modules/datasource/repology/index.ts @@ -56,7 +56,7 @@ export class RepologyDatasource extends Datasource { private async queryPackages(url: string): Promise<RepologyPackage[]> { try { - const res = await this.http.getJson<RepologyPackage[]>(url); + const res = await this.http.getJsonUnchecked<RepologyPackage[]>(url); return res.body; } catch (err) { if (err.statusCode === 404) { diff --git a/lib/modules/datasource/terraform-module/base.ts b/lib/modules/datasource/terraform-module/base.ts index 24f6a62493..e2c8aba86f 100644 --- a/lib/modules/datasource/terraform-module/base.ts +++ b/lib/modules/datasource/terraform-module/base.ts @@ -22,7 +22,7 @@ export abstract class TerraformDatasource extends Datasource { ): Promise<ServiceDiscoveryResult> { const discoveryURL = TerraformDatasource.getDiscoveryUrl(registryUrl); const serviceDiscovery = ( - await this.http.getJson<ServiceDiscoveryResult>(discoveryURL) + await this.http.getJsonUnchecked<ServiceDiscoveryResult>(discoveryURL) ).body; return serviceDiscovery; } diff --git a/lib/modules/datasource/terraform-module/index.ts b/lib/modules/datasource/terraform-module/index.ts index 4e3b25e4bf..05ff6d5e97 100644 --- a/lib/modules/datasource/terraform-module/index.ts +++ b/lib/modules/datasource/terraform-module/index.ts @@ -103,7 +103,7 @@ export class TerraformModuleDatasource extends TerraformDatasource { serviceDiscovery, repository, ); - res = (await this.http.getJson<TerraformRelease>(pkgUrl)).body; + res = (await this.http.getJsonUnchecked<TerraformRelease>(pkgUrl)).body; const returnedName = res.namespace + '/' + res.name + '/' + res.provider; if (returnedName !== repository) { logger.warn({ pkgUrl }, 'Terraform registry result mismatch'); @@ -152,7 +152,8 @@ export class TerraformModuleDatasource extends TerraformDatasource { serviceDiscovery, `${repository}/versions`, ); - res = (await this.http.getJson<TerraformModuleVersions>(pkgUrl)).body; + res = (await this.http.getJsonUnchecked<TerraformModuleVersions>(pkgUrl)) + .body; if (res.modules.length < 1) { logger.warn({ pkgUrl }, 'Terraform registry result mismatch'); return null; diff --git a/lib/modules/datasource/terraform-provider/index.ts b/lib/modules/datasource/terraform-provider/index.ts index b960f8cf42..81f7de33cf 100644 --- a/lib/modules/datasource/terraform-provider/index.ts +++ b/lib/modules/datasource/terraform-provider/index.ts @@ -113,7 +113,9 @@ export class TerraformProviderDatasource extends TerraformDatasource { serviceDiscovery, repository, ); - const res = (await this.http.getJson<TerraformProvider>(backendURL)).body; + const res = ( + await this.http.getJsonUnchecked<TerraformProvider>(backendURL) + ).body; const dep: ReleaseResult = { releases: res.versions.map((version) => ({ version, @@ -149,8 +151,9 @@ export class TerraformProviderDatasource extends TerraformDatasource { serviceDiscovery, `${repository}/versions`, ); - const res = (await this.http.getJson<TerraformProviderVersions>(backendURL)) - .body; + const res = ( + await this.http.getJsonUnchecked<TerraformProviderVersions>(backendURL) + ).body; const dep: ReleaseResult = { releases: res.versions.map(({ version }) => ({ version, @@ -171,7 +174,9 @@ export class TerraformProviderDatasource extends TerraformDatasource { `index.json`, ); const res = ( - await this.http.getJson<TerraformProviderReleaseBackend>(backendURL) + await this.http.getJsonUnchecked<TerraformProviderReleaseBackend>( + backendURL, + ) ).body; const dep: ReleaseResult = { @@ -240,7 +245,7 @@ export class TerraformProviderDatasource extends TerraformDatasource { repository, ); const versionsResponse = ( - await this.http.getJson<TerraformRegistryVersions>( + await this.http.getJsonUnchecked<TerraformRegistryVersions>( `${backendURL}/versions`, ) ).body; @@ -263,7 +268,9 @@ export class TerraformProviderDatasource extends TerraformDatasource { const buildURL = `${backendURL}/${version}/download/${platform.os}/${platform.arch}`; try { const res = ( - await this.http.getJson<TerraformRegistryBuildResponse>(buildURL) + await this.http.getJsonUnchecked<TerraformRegistryBuildResponse>( + buildURL, + ) ).body; const newBuild: TerraformBuild = { name: repository, @@ -325,7 +332,7 @@ export class TerraformProviderDatasource extends TerraformDatasource { version: string, ): Promise<VersionDetailResponse> { return ( - await this.http.getJson<VersionDetailResponse>( + await this.http.getJsonUnchecked<VersionDetailResponse>( `${TerraformProviderDatasource.defaultRegistryUrls[1]}/${backendLookUpName}/${version}/index.json`, ) ).body; diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index 3c4274f2e9..7f1b2acceb 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -116,7 +116,7 @@ export async function initPlatform({ bitbucketServerVersion = process.env.RENOVATE_X_PLATFORM_VERSION; } else { const { version } = ( - await bitbucketServerHttp.getJson<{ version: string }>( + await bitbucketServerHttp.getJsonUnchecked<{ version: string }>( `./rest/api/1.0/application-properties`, ) ).body; @@ -199,7 +199,7 @@ export async function getRawFile( const fileUrl = `./rest/api/1.0/projects/${project}/repos/${slug}/browse/${fileName}?limit=20000` + (branchOrTag ? '&at=' + branchOrTag : ''); - const res = await bitbucketServerHttp.getJson<FileData>(fileUrl); + const res = await bitbucketServerHttp.getJsonUnchecked<FileData>(fileUrl); const { isLastPage, lines, size } = res.body; if (isLastPage) { return lines.map(({ text }) => text).join('\n'); @@ -245,13 +245,13 @@ export async function initRepo({ try { const info = ( - await bitbucketServerHttp.getJson<BbsRestRepo>( + await bitbucketServerHttp.getJsonUnchecked<BbsRestRepo>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}`, ) ).body; config.owner = info.project.key; logger.debug(`${repository} owner = ${config.owner}`); - const branchRes = await bitbucketServerHttp.getJson<BbsRestBranch>( + const branchRes = await bitbucketServerHttp.getJsonUnchecked<BbsRestBranch>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/branches/default`, ); @@ -303,7 +303,7 @@ export async function getBranchForceRebase( _branchName: string, ): Promise<boolean> { // https://docs.atlassian.com/bitbucket-server/rest/7.0.1/bitbucket-rest.html#idp342 - const res = await bitbucketServerHttp.getJson<{ + const res = await bitbucketServerHttp.getJsonUnchecked<{ mergeConfig: { defaultStrategy: { id: string } }; }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/settings/pull-requests`, @@ -327,7 +327,7 @@ export async function getPr( return null; } - const res = await bitbucketServerHttp.getJson<BbsRestPr>( + const res = await bitbucketServerHttp.getJsonUnchecked<BbsRestPr>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}`, { memCache: !refreshCache }, ); @@ -458,7 +458,7 @@ async function getStatus( const branchCommit = git.getBranchCommit(branchName); return ( - await bitbucketServerHttp.getJson<utils.BitbucketCommitStatus>( + await bitbucketServerHttp.getJsonUnchecked<utils.BitbucketCommitStatus>( // TODO: types (#22198) `./rest/build-status/1.0/commits/stats/${branchCommit!}`, { memCache }, @@ -777,7 +777,7 @@ async function getCommentVersion( ): Promise<number> { // GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/comments/{commentId} const { version } = ( - await bitbucketServerHttp.getJson<{ version: number }>( + await bitbucketServerHttp.getJsonUnchecked<{ version: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}/comments/${commentId}`, ) ).body; @@ -913,13 +913,13 @@ export async function createPr({ if (platformPrOptions?.bbUseDefaultReviewers) { logger.debug(`fetching default reviewers`); const { id } = ( - await bitbucketServerHttp.getJson<{ id: number }>( + await bitbucketServerHttp.getJsonUnchecked<{ id: number }>( `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}`, ) ).body; const defReviewers = ( - await bitbucketServerHttp.getJson<{ name: string }[]>( + await bitbucketServerHttp.getJsonUnchecked<{ name: string }[]>( `./rest/default-reviewers/1.0/projects/${config.projectKey}/repos/${ config.repositorySlug }/reviewers?sourceRefId=refs/heads/${escapeHash( diff --git a/lib/modules/platform/bitbucket-server/utils.ts b/lib/modules/platform/bitbucket-server/utils.ts index 92099dafab..8d51b2607d 100644 --- a/lib/modules/platform/bitbucket-server/utils.ts +++ b/lib/modules/platform/bitbucket-server/utils.ts @@ -68,7 +68,7 @@ function callApi<T>( return bitbucketServerHttp.deleteJson<T>(apiUrl, options); case 'get': default: - return bitbucketServerHttp.getJson<T>(apiUrl, options); + return bitbucketServerHttp.getJsonUnchecked<T>(apiUrl, options); } } diff --git a/lib/modules/platform/bitbucket/comments.ts b/lib/modules/platform/bitbucket/comments.ts index 2d91964a30..98cfbf5e2c 100644 --- a/lib/modules/platform/bitbucket/comments.ts +++ b/lib/modules/platform/bitbucket/comments.ts @@ -24,7 +24,7 @@ async function getComments( prNo: number, ): Promise<Comment[]> { const comments = ( - await bitbucketHttp.getJson<PagedResult<Comment>>( + await bitbucketHttp.getJsonUnchecked<PagedResult<Comment>>( `/2.0/repositories/${config.repository}/pullrequests/${prNo}/comments`, { paginate: true, diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index f58265dad7..0d562c7b5d 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -93,7 +93,7 @@ export async function initPlatform({ } try { const { uuid } = ( - await bitbucketHttp.getJson<Account>('/2.0/user', options) + await bitbucketHttp.getJsonUnchecked<Account>('/2.0/user', options) ).body; renovateUserUuid = uuid; } catch (err) { @@ -212,7 +212,7 @@ export async function initRepo({ if (bbUseDevelopmentBranch) { // Fetch Bitbucket development branch const developmentBranch = ( - await bitbucketHttp.getJson<RepoBranchingModel>( + await bitbucketHttp.getJsonUnchecked<RepoBranchingModel>( `/2.0/repositories/${repository}/branching-model`, ) ).body.development?.branch?.name; @@ -304,7 +304,7 @@ export async function findPr({ if (includeOtherAuthors) { // PR might have been created by anyone, so don't use the cached Renovate PR list const prs = ( - await bitbucketHttp.getJson<PagedResult<PrResponse>>( + await bitbucketHttp.getJsonUnchecked<PagedResult<PrResponse>>( `/2.0/repositories/${config.repository}/pullrequests?q=source.branch.name="${branchName}"&state=open`, ) ).body.values; @@ -363,7 +363,7 @@ export async function findPr({ // Gets details for a PR export async function getPr(prNo: number): Promise<Pr | null> { const pr = ( - await bitbucketHttp.getJson<PrResponse>( + await bitbucketHttp.getJsonUnchecked<PrResponse>( `/2.0/repositories/${config.repository}/pullrequests/${prNo}`, ) ).body; @@ -395,7 +395,7 @@ async function getBranchCommit( ): Promise<string | undefined> { try { const branch = ( - await bitbucketHttp.getJson<BranchResponse>( + await bitbucketHttp.getJsonUnchecked<BranchResponse>( `/2.0/repositories/${config.repository}/refs/branches/${escapeHash( branchName, )}`, @@ -424,7 +424,7 @@ async function getStatus( ): Promise<BitbucketStatus[]> { const sha = await getBranchCommit(branchName); return ( - await bitbucketHttp.getJson<PagedResult<BitbucketStatus>>( + await bitbucketHttp.getJsonUnchecked<PagedResult<BitbucketStatus>>( `/2.0/repositories/${config.repository}/commit/${sha!}/statuses`, { paginate: true, @@ -531,7 +531,7 @@ async function findOpenIssues(title: string): Promise<BbIssue[]> { const filter = encodeURIComponent(filters.join(' AND ')); return ( ( - await bitbucketHttp.getJson<{ values: BbIssue[] }>( + await bitbucketHttp.getJsonUnchecked<{ values: BbIssue[] }>( `/2.0/repositories/${config.repository}/issues?q=${filter}`, ) ).body.values || /* istanbul ignore next */ [] @@ -677,7 +677,7 @@ export async function getIssueList(): Promise<Issue[]> { } const filter = encodeURIComponent(filters.join(' AND ')); const url = `/2.0/repositories/${config.repository}/issues?q=${filter}`; - const res = await bitbucketHttp.getJson<{ values: Issue[] }>(url, { + const res = await bitbucketHttp.getJsonUnchecked<{ values: Issue[] }>(url, { cacheProvider: repoCacheProvider, }); return res.body.values || []; @@ -788,7 +788,7 @@ async function sanitizeReviewers( // Validate that each previous PR reviewer account is still active for (const reviewer of reviewers) { const reviewerUser = ( - await bitbucketHttp.getJson<Account>( + await bitbucketHttp.getJsonUnchecked<Account>( `/2.0/users/${reviewer.uuid}`, { memCache: true }, ) @@ -881,7 +881,7 @@ export async function createPr({ if (platformPrOptions?.bbUseDefaultReviewers) { const reviewersResponse = ( - await bitbucketHttp.getJson<PagedResult<EffectiveReviewer>>( + await bitbucketHttp.getJsonUnchecked<PagedResult<EffectiveReviewer>>( `/2.0/repositories/${config.repository}/effective-default-reviewers`, { paginate: true, @@ -1019,7 +1019,7 @@ export async function updatePr({ logger.debug(`updatePr(${prNo}, ${title}, body)`); // Updating a PR in Bitbucket will clear the reviewers if reviewers is not present const pr = ( - await bitbucketHttp.getJson<PrResponse>( + await bitbucketHttp.getJsonUnchecked<PrResponse>( `/2.0/repositories/${config.repository}/pullrequests/${prNo}`, ) ).body; diff --git a/lib/modules/platform/bitbucket/pr-cache.ts b/lib/modules/platform/bitbucket/pr-cache.ts index b8e9000e3c..84e8fc4a31 100644 --- a/lib/modules/platform/bitbucket/pr-cache.ts +++ b/lib/modules/platform/bitbucket/pr-cache.ts @@ -147,7 +147,7 @@ export class BitbucketPrCache { pagelen: 50, cacheProvider: repoCacheProvider, }; - const res = await http.getJson<PagedResult<PrResponse>>(url, opts); + const res = await http.getJsonUnchecked<PagedResult<PrResponse>>(url, opts); const items = res.body.values; logger.debug(`Fetched ${items.length} PRs to sync with cache`); diff --git a/lib/modules/platform/gerrit/client.ts b/lib/modules/platform/gerrit/client.ts index fbc392765b..e058f0b703 100644 --- a/lib/modules/platform/gerrit/client.ts +++ b/lib/modules/platform/gerrit/client.ts @@ -30,7 +30,7 @@ class GerritClient { private gerritHttp = new GerritHttp(); async getRepos(): Promise<string[]> { - const res = await this.gerritHttp.getJson<string[]>( + const res = await this.gerritHttp.getJsonUnchecked<string[]>( 'a/projects/?type=CODE&state=ACTIVE', {}, ); @@ -38,9 +38,10 @@ class GerritClient { } async getProjectInfo(repository: string): Promise<GerritProjectInfo> { - const projectInfo = await this.gerritHttp.getJson<GerritProjectInfo>( - `a/projects/${encodeURIComponent(repository)}`, - ); + const projectInfo = + await this.gerritHttp.getJsonUnchecked<GerritProjectInfo>( + `a/projects/${encodeURIComponent(repository)}`, + ); if (projectInfo.body.state !== 'ACTIVE') { throw new Error(REPOSITORY_ARCHIVED); } @@ -48,7 +49,7 @@ class GerritClient { } async getBranchInfo(repository: string): Promise<GerritBranchInfo> { - const branchInfo = await this.gerritHttp.getJson<GerritBranchInfo>( + const branchInfo = await this.gerritHttp.getJsonUnchecked<GerritBranchInfo>( `a/projects/${encodeURIComponent(repository)}/branches/HEAD`, ); return branchInfo.body; @@ -60,7 +61,7 @@ class GerritClient { refreshCache?: boolean, ): Promise<GerritChange[]> { const filters = GerritClient.buildSearchFilters(repository, findPRConfig); - const changes = await this.gerritHttp.getJson<GerritChange[]>( + const changes = await this.gerritHttp.getJsonUnchecked<GerritChange[]>( `a/changes/?q=` + filters.join('+') + this.requestDetails.map((det) => `&o=${det}`).join(''), @@ -73,7 +74,7 @@ class GerritClient { } async getChange(changeNumber: number): Promise<GerritChange> { - const changes = await this.gerritHttp.getJson<GerritChange>( + const changes = await this.gerritHttp.getJsonUnchecked<GerritChange>( `a/changes/${changeNumber}?` + this.requestDetails.map((det) => `o=${det}`).join('&'), ); @@ -81,9 +82,10 @@ class GerritClient { } async getMergeableInfo(change: GerritChange): Promise<GerritMergeableInfo> { - const mergeable = await this.gerritHttp.getJson<GerritMergeableInfo>( - `a/changes/${change._number}/revisions/current/mergeable`, - ); + const mergeable = + await this.gerritHttp.getJsonUnchecked<GerritMergeableInfo>( + `a/changes/${change._number}/revisions/current/mergeable`, + ); return mergeable.body; } @@ -99,10 +101,9 @@ class GerritClient { } async getMessages(changeNumber: number): Promise<GerritChangeMessageInfo[]> { - const messages = await this.gerritHttp.getJson<GerritChangeMessageInfo[]>( - `a/changes/${changeNumber}/messages`, - { memCache: false }, - ); + const messages = await this.gerritHttp.getJsonUnchecked< + GerritChangeMessageInfo[] + >(`a/changes/${changeNumber}/messages`, { memCache: false }); return messages.body; } diff --git a/lib/modules/platform/gitea/gitea-helper.ts b/lib/modules/platform/gitea/gitea-helper.ts index 84a8025010..53e5a54abf 100644 --- a/lib/modules/platform/gitea/gitea-helper.ts +++ b/lib/modules/platform/gitea/gitea-helper.ts @@ -46,13 +46,16 @@ export async function getCurrentUser( options?: GiteaHttpOptions, ): Promise<User> { const url = `${API_PATH}/user`; - const res = await giteaHttp.getJson<User>(url, options); + const res = await giteaHttp.getJsonUnchecked<User>(url, options); return res.body; } export async function getVersion(options?: GiteaHttpOptions): Promise<string> { const url = `${API_PATH}/version`; - const res = await giteaHttp.getJson<{ version: string }>(url, options); + const res = await giteaHttp.getJsonUnchecked<{ version: string }>( + url, + options, + ); return res.body.version; } @@ -62,7 +65,7 @@ export async function searchRepos( ): Promise<Repo[]> { const query = getQueryString(params); const url = `${API_PATH}/repos/search?${query}`; - const res = await giteaHttp.getJson<RepoSearchResults>(url, { + const res = await giteaHttp.getJsonUnchecked<RepoSearchResults>(url, { ...options, paginate: true, }); @@ -81,7 +84,7 @@ export async function orgListRepos( options?: GiteaHttpOptions, ): Promise<Repo[]> { const url = `${API_PATH}/orgs/${organization}/repos`; - const res = await giteaHttp.getJson<Repo[]>(url, { + const res = await giteaHttp.getJsonUnchecked<Repo[]>(url, { ...options, paginate: true, }); @@ -94,7 +97,7 @@ export async function getRepo( options?: GiteaHttpOptions, ): Promise<Repo> { const url = `${API_PATH}/repos/${repoPath}`; - const res = await giteaHttp.getJson<Repo>(url, options); + const res = await giteaHttp.getJsonUnchecked<Repo>(url, options); return res.body; } @@ -108,7 +111,7 @@ export async function getRepoContents( const url = `${API_PATH}/repos/${repoPath}/contents/${urlEscape( filePath, )}?${query}`; - const res = await giteaHttp.getJson<RepoContents>(url, options); + const res = await giteaHttp.getJsonUnchecked<RepoContents>(url, options); if (res.body.content) { res.body.contentString = Buffer.from(res.body.content, 'base64').toString(); @@ -176,7 +179,7 @@ export async function getPR( options?: GiteaHttpOptions, ): Promise<PR> { const url = `${API_PATH}/repos/${repoPath}/pulls/${idx}`; - const res = await giteaHttp.getJson<PR>(url, options); + const res = await giteaHttp.getJsonUnchecked<PR>(url, options); return res.body; } @@ -255,7 +258,7 @@ export async function searchIssues( ): Promise<Issue[]> { const query = getQueryString({ ...params, type: 'issues' }); const url = `${API_PATH}/repos/${repoPath}/issues?${query}`; - const res = await giteaHttp.getJson<Issue[]>(url, { + const res = await giteaHttp.getJsonUnchecked<Issue[]>(url, { ...options, paginate: true, }); @@ -269,7 +272,7 @@ export async function getIssue( options?: GiteaHttpOptions, ): Promise<Issue> { const url = `${API_PATH}/repos/${repoPath}/issues/${idx}`; - const res = await giteaHttp.getJson<Issue>(url, options); + const res = await giteaHttp.getJsonUnchecked<Issue>(url, options); return res.body; } @@ -278,7 +281,7 @@ export async function getRepoLabels( options?: GiteaHttpOptions, ): Promise<Label[]> { const url = `${API_PATH}/repos/${repoPath}/labels`; - const res = await giteaHttp.getJson<Label[]>(url, options); + const res = await giteaHttp.getJsonUnchecked<Label[]>(url, options); return res.body; } @@ -288,7 +291,7 @@ export async function getOrgLabels( options?: GiteaHttpOptions, ): Promise<Label[]> { const url = `${API_PATH}/orgs/${orgName}/labels`; - const res = await giteaHttp.getJson<Label[]>(url, options); + const res = await giteaHttp.getJsonUnchecked<Label[]>(url, options); return res.body; } @@ -350,7 +353,7 @@ export async function getComments( options?: GiteaHttpOptions, ): Promise<Comment[]> { const url = `${API_PATH}/repos/${repoPath}/issues/${issue}/comments`; - const res = await giteaHttp.getJson<Comment[]>(url, options); + const res = await giteaHttp.getJsonUnchecked<Comment[]>(url, options); return res.body; } @@ -409,7 +412,7 @@ export async function getCombinedCommitStatus( const url = `${API_PATH}/repos/${repoPath}/commits/${urlEscape( branchName, )}/statuses`; - const res = await giteaHttp.getJson<CommitStatus[]>(url, { + const res = await giteaHttp.getJsonUnchecked<CommitStatus[]>(url, { ...options, paginate: true, }); @@ -432,7 +435,7 @@ export async function getBranch( options?: GiteaHttpOptions, ): Promise<Branch> { const url = `${API_PATH}/repos/${repoPath}/branches/${urlEscape(branchName)}`; - const res = await giteaHttp.getJson<Branch>(url, options); + const res = await giteaHttp.getJsonUnchecked<Branch>(url, options); return res.body; } diff --git a/lib/modules/platform/gitea/pr-cache.ts b/lib/modules/platform/gitea/pr-cache.ts index 936689ef14..82d935de31 100644 --- a/lib/modules/platform/gitea/pr-cache.ts +++ b/lib/modules/platform/gitea/pr-cache.ts @@ -136,10 +136,13 @@ export class GiteaPrCache { while (url) { // TODO: use zod, typescript can't infer the type of the response #22198 - const res: HttpResponse<(PR | null)[]> = await http.getJson(url, { - memCache: false, - paginate: false, - }); + const res: HttpResponse<(PR | null)[]> = await http.getJsonUnchecked( + url, + { + memCache: false, + paginate: false, + }, + ); const needNextPage = this.reconcile(res.body); if (!needNextPage) { diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 8551653ce0..2ef5eb87da 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -251,7 +251,7 @@ export async function initPlatform({ async function fetchRepositories(): Promise<GhRestRepo[]> { try { if (isGHApp()) { - const res = await githubApi.getJson<{ + const res = await githubApi.getJsonUnchecked<{ repositories: GhRestRepo[]; }>(`installation/repositories?per_page=100`, { paginationField: 'repositories', @@ -259,7 +259,7 @@ async function fetchRepositories(): Promise<GhRestRepo[]> { }); return res.body.repositories; } else { - const res = await githubApi.getJson<GhRestRepo[]>( + const res = await githubApi.getJsonUnchecked<GhRestRepo[]>( `user/repos?per_page=100`, { paginate: 'all' }, ); @@ -313,7 +313,7 @@ async function getBranchProtection( if (config.parentRepo) { return {}; } - const res = await githubApi.getJson<BranchProtection>( + const res = await githubApi.getJsonUnchecked<BranchProtection>( `repos/${config.repository}/branches/${escapeHash(branchName)}/protection`, { cacheProvider: repoCacheProvider }, ); @@ -338,7 +338,10 @@ export async function getRawFile( if (branchOrTag) { url += `?ref=` + branchOrTag; } - const res = await githubApi.getJson<{ content: string }>(url, httpOptions); + const res = await githubApi.getJsonUnchecked<{ content: string }>( + url, + httpOptions, + ); const buf = res.body.content; const str = fromBase64(buf); return str; @@ -361,7 +364,7 @@ export async function listForks( // Get list of existing repos const url = `repos/${repository}/forks?per_page=100`; const repos = ( - await githubApi.getJson<GhRestRepo[]>(url, { + await githubApi.getJsonUnchecked<GhRestRepo[]>(url, { token, paginate: true, pageLimit: 100, @@ -792,7 +795,7 @@ function cachePr(pr?: GhPr | null): void { // Fetch fresh Pull Request and cache it when possible async function fetchPr(prNo: number): Promise<GhPr | null> { try { - const { body: ghRestPr } = await githubApi.getJson<GhRestPr>( + const { body: ghRestPr } = await githubApi.getJsonUnchecked<GhRestPr>( `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`, ); const result = coerceRestPr(ghRestPr); @@ -857,7 +860,7 @@ export async function findPr({ const repo = config.parentRepo ?? config.repository; const org = repo?.split('/')[0]; // PR might have been created by anyone, so don't use the cached Renovate PR list - const { body: prList } = await githubApi.getJson<GhRestPr[]>( + const { body: prList } = await githubApi.getJsonUnchecked<GhRestPr[]>( `repos/${repo}/pulls?head=${org}:${branchName}&state=open`, { cacheProvider: repoCacheProvider }, ); @@ -996,10 +999,11 @@ async function getStatus( const branch = escapeHash(branchName); const url = `repos/${config.repository}/commits/${branch}/status`; - const { body: status } = await githubApi.getJson<CombinedBranchStatus>(url, { - memCache: useCache, - cacheProvider: repoCacheProvider, - }); + const { body: status } = + await githubApi.getJsonUnchecked<CombinedBranchStatus>(url, { + memCache: useCache, + cacheProvider: repoCacheProvider, + }); return status; } @@ -1053,7 +1057,7 @@ export async function getBranchStatus( paginationField: 'check_runs', }; const checkRunsRaw = ( - await githubApi.getJson<{ + await githubApi.getJsonUnchecked<{ check_runs: { name: string; status: string; conclusion: string }[]; }>(checkRunsUrl, opts) ).body; @@ -1116,7 +1120,9 @@ async function getStatusCheck( const url = `repos/${config.repository}/commits/${branchCommit}/statuses`; return ( - await githubApi.getJson<GhBranchStatus[]>(url, { memCache: useCache }) + await githubApi.getJsonUnchecked<GhBranchStatus[]>(url, { + memCache: useCache, + }) ).body; } @@ -1547,10 +1553,13 @@ async function getComments(issueNo: number): Promise<Comment[]> { const repo = config.parentRepo ?? config.repository; const url = `repos/${repo}/issues/${issueNo}/comments?per_page=100`; try { - const { body: comments } = await githubApi.getJson<Comment[]>(url, { - paginate: true, - cacheProvider: repoCacheProvider, - }); + const { body: comments } = await githubApi.getJsonUnchecked<Comment[]>( + url, + { + paginate: true, + cacheProvider: repoCacheProvider, + }, + ); logger.debug(`Found ${comments.length} comments`); return comments; } catch (err) /* istanbul ignore next */ { diff --git a/lib/modules/platform/github/pr.ts b/lib/modules/platform/github/pr.ts index 66b37aa342..5e32084ca2 100644 --- a/lib/modules/platform/github/pr.ts +++ b/lib/modules/platform/github/pr.ts @@ -75,7 +75,7 @@ export async function getPrCache( const perPage = isInitial ? 100 : 20; const urlPath = `repos/${repo}/pulls?per_page=${perPage}&state=all&sort=updated&direction=desc&page=${pageIdx}`; - const res = await http.getJson<GhRestPr[]>(urlPath, opts); + const res = await http.getJsonUnchecked<GhRestPr[]>(urlPath, opts); apiQuotaAffected = true; requestsTotal += 1; diff --git a/lib/modules/platform/github/user.ts b/lib/modules/platform/github/user.ts index 5fabaedb94..c2fced06c0 100644 --- a/lib/modules/platform/github/user.ts +++ b/lib/modules/platform/github/user.ts @@ -32,12 +32,13 @@ export async function getUserDetails( ): Promise<UserDetails> { try { const userData = ( - await githubApi.getJson<{ login: string; name: string; id: number }>( - endpoint + 'user', - { - token, - }, - ) + await githubApi.getJsonUnchecked<{ + login: string; + name: string; + id: number; + }>(endpoint + 'user', { + token, + }) ).body; return { username: userData.login, @@ -56,9 +57,12 @@ export async function getUserEmail( ): Promise<string | null> { try { const emails = ( - await githubApi.getJson<{ email: string }[]>(endpoint + 'user/emails', { - token, - }) + await githubApi.getJsonUnchecked<{ email: string }[]>( + endpoint + 'user/emails', + { + token, + }, + ) ).body; return emails?.[0].email ?? null; } catch { diff --git a/lib/modules/platform/gitlab/http.ts b/lib/modules/platform/gitlab/http.ts index 51f6fc401f..deb011fc58 100644 --- a/lib/modules/platform/gitlab/http.ts +++ b/lib/modules/platform/gitlab/http.ts @@ -7,7 +7,9 @@ export const gitlabApi = new GitlabHttp(); export async function getUserID(username: string): Promise<number> { const userInfo = ( - await gitlabApi.getJson<{ id: number }[]>(`users?username=${username}`) + await gitlabApi.getJsonUnchecked<{ id: number }[]>( + `users?username=${username}`, + ) ).body; if (is.emptyArray(userInfo)) { @@ -22,7 +24,9 @@ export async function getUserID(username: string): Promise<number> { async function getMembers(group: string): Promise<GitLabUser[]> { const groupEncoded = encodeURIComponent(group); return ( - await gitlabApi.getJson<GitLabUser[]>(`groups/${groupEncoded}/members`) + await gitlabApi.getJsonUnchecked<GitLabUser[]>( + `groups/${groupEncoded}/members`, + ) ).body; } @@ -39,7 +43,8 @@ export async function getMemberUsernames(group: string): Promise<string[]> { export async function isUserBusy(user: string): Promise<boolean> { try { const url = `/users/${user}/status`; - const userStatus = (await gitlabApi.getJson<GitlabUserStatus>(url)).body; + const userStatus = (await gitlabApi.getJsonUnchecked<GitlabUserStatus>(url)) + .body; return userStatus.availability === 'busy'; } catch (err) { logger.warn({ err }, 'Failed to get user status'); diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 1010f448cd..64ed26afd3 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -117,7 +117,7 @@ export async function initPlatform({ try { if (!gitAuthor) { const user = ( - await gitlabApi.getJson<{ + await gitlabApi.getJsonUnchecked<{ email: string; name: string; id: number; @@ -133,7 +133,9 @@ export async function initPlatform({ gitlabVersion = process.env.RENOVATE_X_PLATFORM_VERSION; } else { const version = ( - await gitlabApi.getJson<{ version: string }>('version', { token }) + await gitlabApi.getJsonUnchecked<{ version: string }>('version', { + token, + }) ).body; gitlabVersion = version.version; } @@ -191,7 +193,7 @@ export async function getRepos(config?: AutodiscoverConfig): Promise<string[]> { await pMap( urls, (url) => - gitlabApi.getJson<RepoResponse[]>(url, { + gitlabApi.getJsonUnchecked<RepoResponse[]>(url, { paginate: true, }), { @@ -226,7 +228,7 @@ export async function getRawFile( const url = `projects/${repo}/repository/files/${escapedFileName}?ref=` + (branchOrTag ?? `HEAD`); - const res = await gitlabApi.getJson<{ content: string }>(url); + const res = await gitlabApi.getJsonUnchecked<{ content: string }>(url); const buf = res.body.content; const str = Buffer.from(buf, 'base64').toString(); return str; @@ -314,7 +316,7 @@ export async function initRepo({ let res: HttpResponse<RepoResponse>; try { - res = await gitlabApi.getJson<RepoResponse>( + res = await gitlabApi.getJsonUnchecked<RepoResponse>( `projects/${config.repository}`, ); if (res.body.archived) { @@ -433,7 +435,7 @@ async function getStatus( }/repository/commits/${branchSha!}/statuses`; return ( - await gitlabApi.getJson<GitlabBranchStatus[]>(url, { + await gitlabApi.getJsonUnchecked<GitlabBranchStatus[]>(url, { paginate: true, memCache: useCache, }) @@ -548,9 +550,12 @@ async function fetchPrList(): Promise<Pr[]> { const query = getQueryString(searchParams); const urlString = `projects/${config.repository}/merge_requests?${query}`; try { - const res = await gitlabApi.getJson<GitLabMergeRequest[]>(urlString, { - paginate: true, - }); + const res = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>( + urlString, + { + paginate: true, + }, + ); return res.body.map((pr) => prInfo(pr)); } catch (err) /* istanbul ignore next */ { logger.debug({ err }, 'Error fetching PR list'); @@ -571,7 +576,7 @@ export async function getPrList(): Promise<Pr[]> { async function ignoreApprovals(pr: number): Promise<void> { try { const url = `projects/${config.repository}/merge_requests/${pr}/approval_rules`; - const { body: rules } = await gitlabApi.getJson< + const { body: rules } = await gitlabApi.getJsonUnchecked< { name: string; rule_type: string; @@ -655,7 +660,7 @@ async function tryPrAutomerge( // Check for correct merge request status before setting `merge_when_pipeline_succeeds` to `true`. for (let attempt = 1; attempt <= retryTimes; attempt += 1) { - const { body } = await gitlabApi.getJson<{ + const { body } = await gitlabApi.getJsonUnchecked<{ merge_status: string; detailed_merge_status?: string; pipeline: { @@ -929,7 +934,7 @@ export async function findPr({ if (includeOtherAuthors) { // PR might have been created by anyone, so don't use the cached Renovate MR list - const response = await gitlabApi.getJson<GitLabMergeRequest[]>( + const response = await gitlabApi.getJsonUnchecked<GitLabMergeRequest[]>( `projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`, ); @@ -1054,7 +1059,7 @@ export async function getIssueList(): Promise<GitlabIssue[]> { searchParams.scope = 'created_by_me'; } const query = getQueryString(searchParams); - const res = await gitlabApi.getJson< + const res = await gitlabApi.getJsonUnchecked< { iid: number; title: string; labels: string[] }[] >(`projects/${config.repository}/issues?${query}`, { memCache: false, @@ -1080,7 +1085,7 @@ export async function getIssue( ): Promise<Issue | null> { try { const issueBody = ( - await gitlabApi.getJson<{ description: string }>( + await gitlabApi.getJsonUnchecked<{ description: string }>( `projects/${config.repository}/issues/${number}`, { memCache: useCache }, ) @@ -1127,7 +1132,7 @@ export async function ensureIssue({ } if (issue) { const existingDescription = ( - await gitlabApi.getJson<{ description: string }>( + await gitlabApi.getJsonUnchecked<{ description: string }>( `projects/${config.repository}/issues/${issue.iid}`, ) ).body.description; @@ -1302,7 +1307,7 @@ async function getComments(issueNo: number): Promise<GitlabComment[]> { logger.debug(`Getting comments for #${issueNo}`); const url = `projects/${config.repository}/merge_requests/${issueNo}/notes`; const comments = ( - await gitlabApi.getJson<GitlabComment[]>(url, { paginate: true }) + await gitlabApi.getJsonUnchecked<GitlabComment[]>(url, { paginate: true }) ).body; logger.debug(`Found ${comments.length} comments`); return comments; diff --git a/lib/modules/platform/gitlab/merge-request.ts b/lib/modules/platform/gitlab/merge-request.ts index 91eb6bf88d..0a657fa95c 100644 --- a/lib/modules/platform/gitlab/merge-request.ts +++ b/lib/modules/platform/gitlab/merge-request.ts @@ -9,7 +9,7 @@ export async function getMR( logger.debug(`getMR(${iid})`); const url = `projects/${repository}/merge_requests/${iid}?include_diverged_commits_count=1`; - return (await gitlabApi.getJson<GitLabMergeRequest>(url)).body; + return (await gitlabApi.getJsonUnchecked<GitLabMergeRequest>(url)).body; } export async function updateMR( diff --git a/lib/util/http/bitbucket.spec.ts b/lib/util/http/bitbucket.spec.ts index 52cc342b7d..fbf3a4ee42 100644 --- a/lib/util/http/bitbucket.spec.ts +++ b/lib/util/http/bitbucket.spec.ts @@ -78,7 +78,9 @@ describe('util/http/bitbucket', () => { values: valuesPageThree, page: '3', }); - const res = await api.getJson('/some-url?foo=bar', { paginate: true }); + const res = await api.getJsonUnchecked('/some-url?foo=bar', { + paginate: true, + }); expect(res.body).toEqual({ page: '1', pagelen: 210, @@ -112,7 +114,9 @@ describe('util/http/bitbucket', () => { values: valuesPageThree, page: '3', }); - const res = await api.getJson('some-url?pagelen=10', { paginate: true }); + const res = await api.getJsonUnchecked('some-url?pagelen=10', { + paginate: true, + }); expect(res.body).toEqual({ page: '1', pagelen: 21, @@ -146,7 +150,7 @@ describe('util/http/bitbucket', () => { values: valuesPageThree, page: '3', }); - const res = await api.getJson('some-url', { + const res = await api.getJsonUnchecked('some-url', { paginate: true, pagelen: 20, }); diff --git a/lib/util/http/cache/repository-http-cache-provider.spec.ts b/lib/util/http/cache/repository-http-cache-provider.spec.ts index a8acbba4b1..da8c1806d0 100644 --- a/lib/util/http/cache/repository-http-cache-provider.spec.ts +++ b/lib/util/http/cache/repository-http-cache-provider.spec.ts @@ -17,7 +17,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { const scope = httpMock.scope('https://example.com'); scope.get('/foo/bar').reply(200, { msg: 'Hello, world!' }, { etag: '123' }); - const res1 = await http.getJson('https://example.com/foo/bar'); + const res1 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res1).toMatchObject({ statusCode: 200, body: { msg: 'Hello, world!' }, @@ -25,7 +25,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { }); scope.get('/foo/bar').reply(304); - const res2 = await http.getJson('https://example.com/foo/bar'); + const res2 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res2).toMatchObject({ statusCode: 200, body: { msg: 'Hello, world!' }, @@ -43,7 +43,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { { msg: 'Hello, world!' }, { 'last-modified': 'Mon, 01 Jan 2000 00:00:00 GMT' }, ); - const res1 = await http.getJson('https://example.com/foo/bar'); + const res1 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res1).toMatchObject({ statusCode: 200, body: { msg: 'Hello, world!' }, @@ -51,7 +51,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { }); scope.get('/foo/bar').reply(304); - const res2 = await http.getJson('https://example.com/foo/bar'); + const res2 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res2).toMatchObject({ statusCode: 200, body: { msg: 'Hello, world!' }, @@ -71,7 +71,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { }; httpMock.scope('https://example.com').get('/foo/bar').reply(304); - const res = await http.getJson('https://example.com/foo/bar'); + const res = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res).toMatchObject({ statusCode: 200, @@ -86,7 +86,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { .get('/foo/bar') .reply(200, { msg: 'Hello, world!' }); - await http.getJson('https://example.com/foo/bar'); + await http.getJsonUnchecked('https://example.com/foo/bar'); expect(logger.logger.debug).toHaveBeenCalledWith( 'http cache: failed to persist cache for https://example.com/foo/bar', @@ -97,7 +97,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { const scope = httpMock.scope('https://example.com'); scope.get('/foo/bar').reply(200, { msg: 'Hello, world!' }, { etag: '123' }); - const res1 = await http.getJson('https://example.com/foo/bar'); + const res1 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res1).toMatchObject({ statusCode: 200, body: { msg: 'Hello, world!' }, @@ -107,7 +107,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { resetCache(); scope.get('/foo/bar').reply(304); - const res2 = await http.getJson('https://example.com/foo/bar'); + const res2 = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res2).toMatchObject({ statusCode: 304, authorization: false, @@ -118,7 +118,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { const scope = httpMock.scope('https://example.com'); scope.get('/foo/bar').reply(203); - const res = await http.getJson('https://example.com/foo/bar'); + const res = await http.getJsonUnchecked('https://example.com/foo/bar'); expect(res).toMatchObject({ statusCode: 203, @@ -130,7 +130,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { const scope = httpMock.scope('https://example.com'); scope.get('/foo/bar').reply(200, { msg: 'Hello, world!' }, { etag: '123' }); - const res1 = await http.getJson('https://example.com/foo/bar', { + const res1 = await http.getJsonUnchecked('https://example.com/foo/bar', { headers: { authorization: 'Bearer 123' }, }); expect(res1).toMatchObject({ @@ -140,7 +140,7 @@ describe('util/http/cache/repository-http-cache-provider', () => { }); scope.get('/foo/bar').reply(304); - const res2 = await http.getJson('https://example.com/foo/bar', { + const res2 = await http.getJsonUnchecked('https://example.com/foo/bar', { headers: { authorization: 'Bearer 123' }, }); expect(res2).toMatchObject({ diff --git a/lib/util/http/gerrit.spec.ts b/lib/util/http/gerrit.spec.ts index 7c99f72d5f..7d6563817c 100644 --- a/lib/util/http/gerrit.spec.ts +++ b/lib/util/http/gerrit.spec.ts @@ -33,7 +33,7 @@ describe('util/http/gerrit', () => { }); const res = await api - .getJson('some-url', { headers: { a: 'b' } }) + .getJsonUnchecked('some-url', { headers: { a: 'b' } }) .then((res) => res.body); return expect(res).toEqual(body); }); diff --git a/lib/util/http/gitea.spec.ts b/lib/util/http/gitea.spec.ts index 666d6f9481..6342d81027 100644 --- a/lib/util/http/gitea.spec.ts +++ b/lib/util/http/gitea.spec.ts @@ -18,7 +18,7 @@ describe('util/http/gitea', () => { .get('/pagination-example-1') .reply(200, { hello: 'world' }); - const res = await giteaHttp.getJson('pagination-example-1', { + const res = await giteaHttp.getJsonUnchecked('pagination-example-1', { paginate: true, }); expect(res.body).toEqual({ hello: 'world' }); @@ -34,9 +34,10 @@ describe('util/http/gitea', () => { .get('/pagination-example-1?page=3') .reply(200, ['mno', 'pqr']); - const res = await giteaHttp.getJson(`${baseUrl}/pagination-example-1`, { - paginate: true, - }); + const res = await giteaHttp.getJsonUnchecked( + `${baseUrl}/pagination-example-1`, + { paginate: true }, + ); expect(res.body).toHaveLength(6); expect(res.body).toEqual(['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr']); @@ -52,7 +53,7 @@ describe('util/http/gitea', () => { .get('/pagination-example-2?page=3') .reply(200, { data: ['mno', 'pqr'] }); - const res = await giteaHttp.getJson<{ data: string[] }>( + const res = await giteaHttp.getJsonUnchecked<{ data: string[] }>( 'pagination-example-2', { paginate: true, @@ -70,7 +71,7 @@ describe('util/http/gitea', () => { .get('/pagination-example-3?page=2') .reply(200, { data: [] }); - const res = await giteaHttp.getJson<{ data: string[] }>( + const res = await giteaHttp.getJsonUnchecked<{ data: string[] }>( 'pagination-example-3', { paginate: true, diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index 31292e7b3a..70dc177f8c 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -107,7 +107,7 @@ describe('util/http/github', () => { }) .get(`${url}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(url, { paginate: true }); + const res = await githubApi.getJsonUnchecked(url, { paginate: true }); expect(res.body).toEqual(['a', 'b', 'c', 'd', 'e']); }); @@ -133,7 +133,7 @@ describe('util/http/github', () => { ) .get(`${url}?page=3`) .reply(200, { the_field: ['d'], total: 4 }); - const res: any = await githubApi.getJson('some-url', { + const res = await githubApi.getJsonUnchecked<any>('some-url', { paginate: true, paginationField: 'the_field', }); @@ -169,7 +169,7 @@ describe('util/http/github', () => { }) .get(`${url}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(url, { + const res = await githubApi.getJsonUnchecked(url, { paginate: true, repository: 'some/repo', }); @@ -206,7 +206,7 @@ describe('util/http/github', () => { }) .get(`${url}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(url, { + const res = await githubApi.getJsonUnchecked(url, { paginate: true, repository: 'some/repo', baseUrl: 'https://github.domain.com', @@ -225,7 +225,9 @@ describe('util/http/github', () => { .reply(200, ['a'], { link: `<${url}?page=34>; rel="last"`, }); - const res = await githubApi.getJson('some-url', { paginate: true }); + const res = await githubApi.getJsonUnchecked('some-url', { + paginate: true, + }); expect(res).toBeDefined(); expect(res.body).toEqual(['a']); }); @@ -253,7 +255,9 @@ describe('util/http/github', () => { }) .get(`${apiUrl}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(apiUrl, { paginate: true }); + const res = await githubApi.getJsonUnchecked(apiUrl, { + paginate: true, + }); expect(res.body).toEqual(['a', 'b', 'c', 'd', 'e']); }); @@ -273,7 +277,9 @@ describe('util/http/github', () => { }) .get(`${apiUrl}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(apiUrl, { paginate: true }); + const res = await githubApi.getJsonUnchecked(apiUrl, { + paginate: true, + }); expect(res.body).toEqual(['a', 'b', 'c', 'd', 'e']); }); @@ -295,7 +301,9 @@ describe('util/http/github', () => { }) .get(`/${apiUrl}&page=3`) .reply(200, ['e']); - const res = await githubApi.getJson(apiUrl, { paginate: true }); + const res = await githubApi.getJsonUnchecked(apiUrl, { + paginate: true, + }); expect(res.body).toEqual(['a', 'b', 'c', 'd', 'e']); }); @@ -320,13 +328,13 @@ describe('util/http/github', () => { }, headers, ); - await githubApi.getJson(url); + await githubApi.getJsonUnchecked(url); } async function failWithError(error: string | Record<string, unknown>) { const url = '/some-url'; httpMock.scope(githubApiHost).get(url).replyWithError(error); - await githubApi.getJson(url); + await githubApi.getJsonUnchecked(url); } it('should throw Not found', async () => { diff --git a/lib/util/http/gitlab.spec.ts b/lib/util/http/gitlab.spec.ts index f3f3363eb6..6ab99079d3 100644 --- a/lib/util/http/gitlab.spec.ts +++ b/lib/util/http/gitlab.spec.ts @@ -44,7 +44,9 @@ describe('util/http/gitlab', () => { }) .get('/api/v4/some-url&page=3') .reply(200, ['d']); - const res = await gitlabApi.getJson('some-url', { paginate: true }); + const res = await gitlabApi.getJsonUnchecked('some-url', { + paginate: true, + }); expect(res.body).toHaveLength(4); }); @@ -64,7 +66,9 @@ describe('util/http/gitlab', () => { }) .get('/api/v4/some-url&page=3') .reply(200, ['d']); - const res = await gitlabApi.getJson('some-url', { paginate: true }); + const res = await gitlabApi.getJsonUnchecked('some-url', { + paginate: true, + }); expect(res.body).toHaveLength(4); }); @@ -87,7 +91,9 @@ describe('util/http/gitlab', () => { httpMock.scope(gitlabApiHost).get('/api/v4/some-url').reply(200, ['a'], { link: '<https://gitlab.com/api/v4/some-url&page=3>; rel="last"', }); - const res = await gitlabApi.getJson('some-url', { paginate: true }); + const res = await gitlabApi.getJsonUnchecked('some-url', { + paginate: true, + }); expect(res.body).toHaveLength(1); }); @@ -140,7 +146,7 @@ describe('util/http/gitlab', () => { it('ParseError', async () => { httpMock.scope(gitlabApiHost).get('/api/v4/some-url').reply(200, '{{'); - await expect(gitlabApi.getJson('some-url')).rejects.toThrow( + await expect(gitlabApi.getJsonUnchecked('some-url')).rejects.toThrow( EXTERNAL_HOST_ERROR, ); }); diff --git a/lib/util/http/index.spec.ts b/lib/util/http/index.spec.ts index 36af769a86..57eafc9007 100644 --- a/lib/util/http/index.spec.ts +++ b/lib/util/http/index.spec.ts @@ -80,7 +80,7 @@ describe('util/http/index', () => { .get('/') .reply(200, '{ "test": true }', { etag: 'abc123' }); - const res = await http.getJson('http://renovate.com'); + const res = await http.getJsonUnchecked('http://renovate.com'); expect(res).toEqual({ authorization: false, diff --git a/lib/util/http/index.ts b/lib/util/http/index.ts index c99bfbaad9..d6fb3e59fa 100644 --- a/lib/util/http/index.ts +++ b/lib/util/http/index.ts @@ -415,41 +415,65 @@ export class Http<Opts extends HttpOptions = HttpOptions> { return res.transform((response) => Result.ok(response.body)); } - getJson<ResT>(url: string, options?: Opts): Promise<HttpResponse<ResT>>; - getJson<ResT, Schema extends ZodType<ResT> = ZodType<ResT>>( + /** + * Request JSON and return the response without any validation. + * + * The usage of this method is discouraged, please use `getJson` instead. + * + * If you're new to Zod schema validation library: + * - consult the [documentation of Zod library](https://github.com/colinhacks/zod?tab=readme-ov-file#basic-usage) + * - search the Renovate codebase for 'zod' module usage + * - take a look at the `schema-utils.ts` file for Renovate-specific schemas and utilities + */ + getJsonUnchecked<ResT = unknown>( + url: string, + options?: Opts, + ): Promise<HttpResponse<ResT>> { + return this.requestJson<ResT>('get', { url, httpOptions: options }); + } + + /** + * Request JSON with a Zod schema for the response, + * throwing an error if the response is not valid. + * + * @param url + * @param schema Zod schema for the response + */ + getJson<Schema extends ZodType<any, any, any>>( url: string, schema: Schema, ): Promise<HttpResponse<Infer<Schema>>>; - getJson<ResT, Schema extends ZodType<ResT> = ZodType<ResT>>( + getJson<Schema extends ZodType<any, any, any>>( url: string, options: Opts, schema: Schema, ): Promise<HttpResponse<Infer<Schema>>>; - getJson<ResT = unknown, Schema extends ZodType<ResT> = ZodType<ResT>>( + getJson<Schema extends ZodType<any, any, any>>( arg1: string, arg2?: Opts | Schema, arg3?: Schema, - ): Promise<HttpResponse<ResT>> { - const args = this.resolveArgs<ResT>(arg1, arg2, arg3); - return this.requestJson<ResT>('get', args); + ): Promise<HttpResponse<Infer<Schema>>> { + const args = this.resolveArgs<Infer<Schema>>(arg1, arg2, arg3); + return this.requestJson<Infer<Schema>>('get', args); } - getJsonSafe< - ResT extends NonNullable<unknown>, - Schema extends ZodType<ResT> = ZodType<ResT>, - >(url: string, schema: Schema): AsyncResult<Infer<Schema>, SafeJsonError>; - getJsonSafe< - ResT extends NonNullable<unknown>, - Schema extends ZodType<ResT> = ZodType<ResT>, - >( + /** + * Request JSON with a Zod schema for the response, + * wrapping response data in a `Result` class. + * + * @param url + * @param schema Zod schema for the response + */ + getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>( + url: string, + schema: Schema, + ): AsyncResult<Infer<Schema>, SafeJsonError>; + getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>( url: string, options: Opts, schema: Schema, ): AsyncResult<Infer<Schema>, SafeJsonError>; - getJsonSafe< - ResT extends NonNullable<unknown>, - Schema extends ZodType<ResT> = ZodType<ResT>, - >( + getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>( arg1: string, arg2?: Opts | Schema, arg3?: Schema, diff --git a/lib/util/merge-confidence/index.ts b/lib/util/merge-confidence/index.ts index 93844cd7b3..8491263c61 100644 --- a/lib/util/merge-confidence/index.ts +++ b/lib/util/merge-confidence/index.ts @@ -168,7 +168,9 @@ async function queryApi( let confidence: MergeConfidence = 'neutral'; try { - const res = (await http.getJson<{ confidence: MergeConfidence }>(url)).body; + const res = ( + await http.getJsonUnchecked<{ confidence: MergeConfidence }>(url) + ).body; if (isMergeConfidence(res.confidence)) { confidence = res.confidence; } diff --git a/lib/workers/repository/update/pr/changelog/github/index.ts b/lib/workers/repository/update/pr/changelog/github/index.ts index 89e061532d..64d21bd9e3 100644 --- a/lib/workers/repository/update/pr/changelog/github/index.ts +++ b/lib/workers/repository/update/pr/changelog/github/index.ts @@ -28,11 +28,11 @@ export async function getReleaseNotesMd( logger.trace('github.getReleaseNotesMd()'); const apiPrefix = `${ensureTrailingSlash(apiBaseUrl)}repos/${repository}`; const { default_branch: defaultBranch = 'HEAD' } = ( - await http.getJson<{ default_branch: string }>(apiPrefix) + await http.getJsonUnchecked<{ default_branch: string }>(apiPrefix) ).body; // https://docs.github.com/en/rest/reference/git#get-a-tree - const res = await http.getJson<GithubGitTree>( + const res = await http.getJsonUnchecked<GithubGitTree>( `${apiPrefix}/git/trees/${defaultBranch}${ sourceDirectory ? '?recursive=1' : '' }`, @@ -73,7 +73,7 @@ export async function getReleaseNotesMd( } // https://docs.github.com/en/rest/reference/git#get-a-blob - const fileRes = await http.getJson<GithubGitBlob>( + const fileRes = await http.getJsonUnchecked<GithubGitBlob>( `${apiPrefix}/git/blobs/${sha}`, ); diff --git a/lib/workers/repository/update/pr/changelog/gitlab/index.ts b/lib/workers/repository/update/pr/changelog/gitlab/index.ts index 8957d154ea..4c17d4bac3 100644 --- a/lib/workers/repository/update/pr/changelog/gitlab/index.ts +++ b/lib/workers/repository/update/pr/changelog/gitlab/index.ts @@ -25,7 +25,7 @@ export async function getReleaseNotesMd( // https://docs.gitlab.com/13.2/ee/api/repositories.html#list-repository-tree const tree = ( - await http.getJson<GitlabTreeNode[]>( + await http.getJsonUnchecked<GitlabTreeNode[]>( `${apiPrefix}tree?per_page=100${ sourceDirectory ? `&path=${sourceDirectory}` : '' }`, @@ -69,9 +69,12 @@ export async function getReleaseList( const urlEncodedRepo = encodeURIComponent(repository); const apiUrl = `${apiBaseUrl}projects/${urlEncodedRepo}/releases`; - const res = await http.getJson<GitlabRelease[]>(`${apiUrl}?per_page=100`, { - paginate: true, - }); + const res = await http.getJsonUnchecked<GitlabRelease[]>( + `${apiUrl}?per_page=100`, + { + paginate: true, + }, + ); return res.body.map((release) => ({ url: `${project.baseUrl}${repository}/-/releases/${release.tag_name}`, notesSourceUrl: apiUrl, diff --git a/tools/docs/github-query-items.ts b/tools/docs/github-query-items.ts index 13527c800e..1683158541 100644 --- a/tools/docs/github-query-items.ts +++ b/tools/docs/github-query-items.ts @@ -63,7 +63,7 @@ export async function getOpenGitHubItems(): Promise<RenovateOpenItems> { const per_page = 100; try { const query = getQueryString({ q, per_page }); - const res = await githubApi.getJson<GithubApiQueryResponse>( + const res = await githubApi.getJsonUnchecked<GithubApiQueryResponse>( gitHubApiUrl + query, { paginationField: 'items', -- GitLab