renovate 44.78.0 → 44.79.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/global.d.ts +1 -1
- package/dist/config/global.js +2 -0
- package/dist/config/global.js.map +1 -1
- package/dist/config/options/index.js +35 -0
- package/dist/config/options/index.js.map +1 -1
- package/dist/config/presets/http/index.js +3 -1
- package/dist/config/presets/http/index.js.map +1 -1
- package/dist/config/presets/index.js +7 -1
- package/dist/config/presets/index.js.map +1 -1
- package/dist/config/presets/npm/index.js +4 -2
- package/dist/config/presets/npm/index.js.map +1 -1
- package/dist/config/types.d.ts +4 -1
- package/dist/config/types.js.map +1 -1
- package/dist/config/validation.js +18 -0
- package/dist/config/validation.js.map +1 -1
- package/dist/constants/error-messages.d.ts +2 -1
- package/dist/constants/error-messages.js +2 -1
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/global-config-option-defaults.generated.js +2 -0
- package/dist/global-config-option-defaults.generated.js.map +1 -1
- package/dist/modules/datasource/docker/common.js +3 -2
- package/dist/modules/datasource/docker/common.js.map +1 -1
- package/dist/modules/datasource/index.js +1 -1
- package/dist/modules/datasource/index.js.map +1 -1
- package/dist/modules/datasource/maven/util.js +3 -2
- package/dist/modules/datasource/maven/util.js.map +1 -1
- package/dist/modules/datasource/npm/get.js +1 -1
- package/dist/modules/datasource/npm/get.js.map +1 -1
- package/dist/modules/datasource/pod/index.js +2 -1
- package/dist/modules/datasource/pod/index.js.map +1 -1
- package/dist/modules/datasource/repology/index.js +3 -2
- package/dist/modules/datasource/repology/index.js.map +1 -1
- package/dist/types/host-rules.d.ts +35 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/util/host-rules.d.ts +8 -2
- package/dist/util/host-rules.js +54 -6
- package/dist/util/host-rules.js.map +1 -1
- package/dist/util/http/host-guard.js +279 -0
- package/dist/util/http/host-guard.js.map +1 -0
- package/dist/util/http/host-rules.js.map +1 -1
- package/dist/util/http/http.d.ts +8 -0
- package/dist/util/http/http.js +37 -21
- package/dist/util/http/http.js.map +1 -1
- package/dist/util/http/types.d.ts +6 -0
- package/dist/util/http/types.js.map +1 -1
- package/dist/util/http/util.js +10 -1
- package/dist/util/http/util.js.map +1 -1
- package/dist/workers/repository/init/inherited.js +28 -4
- package/dist/workers/repository/init/inherited.js.map +1 -1
- package/dist/workers/repository/init/merge.js +28 -12
- package/dist/workers/repository/init/merge.js.map +1 -1
- package/package.json +2 -2
- package/renovate-schema.json +17 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-guard.js","names":["hostRules.find"],"sources":["../../../lib/util/http/host-guard.ts"],"sourcesContent":["import dns from 'node:dns';\nimport dnsPromises from 'node:dns/promises';\nimport net from 'node:net';\nimport { isString } from '@sindresorhus/is';\nimport type {\n BeforeRedirectHook,\n BeforeRequestHook,\n NormalizedOptions,\n PlainResponse,\n} from 'got';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { HOST_BLOCKED } from '../../constants/error-messages.ts';\nimport { logger } from '../../logger/index.ts';\nimport { hasProxy } from '../../proxy.ts';\nimport type { InternalHostGrant } from '../../types/index.ts';\nimport * as hostRules from '../host-rules.ts';\nimport { coerceObject } from '../object.ts';\nimport { regEx } from '../regex.ts';\nimport { parseUrl } from '../url.ts';\n\n/** Why a host must not be requested. */\nexport type BlockedHostCategory =\n /** loopback, RFC1918, link-local, and other special-use addresses that are never routable on the public Internet */\n | 'internal'\n /** Cloud provider instance-metadata services (IMDS and equivalents), which can potentially hand out credentials to anything that can reach them, and should never be accessible from an HTTP request from Renovate, regardless of any self-hosted administrator allowlisting */\n | 'metadata';\n\n/**\n * Instance-metadata hostnames, blocked regardless of what they resolve to.\n *\n * Only names which serve nothing but metadata belong here: a name in this set can never be permitted, whatever the configuration says. Providers whose metadata service is only reachable by IP (AWS, Azure, ...) are covered by {@link metadataBlockList} instead.\n */\nconst metadataHostnames = new Set([\n 'metadata.google.internal',\n // Equinix Metal (formerly Packet)\n 'metadata.packet.net',\n]);\n\n// `BlockList.check()` classifies IPv4-mapped IPv6 addresses (in dotted-quad, hexadecimal, and uncompressed spellings) against IPv4 rules, so e.g. `::ffff:169.254.169.254` matches `169.254.169.254` without any normalization on our side.\nconst metadataBlockList = new net.BlockList();\n// AWS/GCP/Azure/... IMDS\nmetadataBlockList.addAddress('169.254.169.254', 'ipv4');\n// AWS IMDS IPv6 endpoint\nmetadataBlockList.addAddress('fd00:ec2::254', 'ipv6');\n// AWS ECS task credentials endpoint\nmetadataBlockList.addAddress('169.254.170.2', 'ipv4');\n// AWS EKS Pod Identity endpoint\nmetadataBlockList.addAddress('169.254.170.23', 'ipv4');\n// Alibaba Cloud/Tencent Cloud metadata\nmetadataBlockList.addAddress('100.100.100.200', 'ipv4');\n\nconst internalBlockList = new net.BlockList();\n// \"this network\" (routes to localhost on Linux)\ninternalBlockList.addSubnet('0.0.0.0', 8, 'ipv4');\n// RFC1918 private ranges\ninternalBlockList.addSubnet('10.0.0.0', 8, 'ipv4');\ninternalBlockList.addSubnet('172.16.0.0', 12, 'ipv4');\ninternalBlockList.addSubnet('192.168.0.0', 16, 'ipv4');\n// carrier-grade NAT\ninternalBlockList.addSubnet('100.64.0.0', 10, 'ipv4');\n// loopback\ninternalBlockList.addSubnet('127.0.0.0', 8, 'ipv4');\n// link-local, including the cloud metadata endpoints\ninternalBlockList.addSubnet('169.254.0.0', 16, 'ipv4');\n// multicast\ninternalBlockList.addSubnet('224.0.0.0', 4, 'ipv4');\n// IPv6 unspecified and loopback\ninternalBlockList.addAddress('::', 'ipv6');\ninternalBlockList.addAddress('::1', 'ipv6');\n// IPv6 unique-local\ninternalBlockList.addSubnet('fc00::', 7, 'ipv6');\n// IPv6 link-local\ninternalBlockList.addSubnet('fe80::', 10, 'ipv6');\n\n/**\n * Classifies an IP address, returning the category it is blocked under, or `null` for a public address.\n *\n * A string that is not a valid IP address is classified as `internal` - we should fail closed instead of possibly connecting to something we shouldn't be.\n */\nexport function classifyIpAddress(address: string): BlockedHostCategory | null {\n const version = net.isIP(address);\n if (version === 0) {\n return 'internal';\n }\n\n const family = version === 4 ? 'ipv4' : 'ipv6';\n\n if (metadataBlockList.check(address, family)) {\n return 'metadata';\n }\n\n if (internalBlockList.check(address, family)) {\n return 'internal';\n }\n\n return null;\n}\n\n/**\n * Classifies a hostname against the metadata-endpoint hostname list.\n *\n * Only metadata hostnames can be classified without DNS resolution - any other hostname needs its resolved addresses checked via {@link classifyIpAddress}.\n */\nexport function classifyHostname(hostname: string): BlockedHostCategory | null {\n // handle trailing-dot FQDN forms like `metadata.google.internal.`\n const normalized = hostname.toLowerCase().replace(regEx(/\\.$/), '');\n if (metadataHostnames.has(normalized)) {\n return 'metadata';\n }\n return null;\n}\n\n/** Strips the brackets `URL` keeps around IPv6 hosts, leaving other hosts as they are. */\nfunction unbracketHostname(hostname: string): string {\n if (hostname.startsWith('[') && hostname.endsWith(']')) {\n return hostname.slice(1, -1);\n }\n return hostname;\n}\n\n/**\n * Classifies a URL from its host alone: IP-literal hosts are classified by address, and metadata hostnames by name.\n *\n * Returns `null` when nothing can be decided at the URL level - i.e. the host is a regular hostname, whose resolved addresses must be checked via {@link classifyIpAddress} at DNS lookup time.\n */\nexport function classifyUrl(url: URL): BlockedHostCategory | null {\n const hostname = unbracketHostname(url.hostname);\n\n if (net.isIP(hostname) !== 0) {\n return classifyIpAddress(hostname);\n }\n\n return classifyHostname(hostname);\n}\n\n/**\n * What the URL-level check decided for a request, and so how the addresses its host resolves to must be treated.\n */\nexport type HostGuardDecision =\n /** internal addresses are permitted for this request, and only metadata addresses need blocking at resolution time */\n | 'granted'\n /** every address the host resolves to must be validated at DNS lookup time, with internal ones blocking the request */\n | 'check-dns'\n /** as `check-dns`, but an internal address only warns - the `internalHostAccess=warn` default lets the request through */\n | 'warn-dns';\n\ninterface BlockedAddress {\n address: string;\n category: BlockedHostCategory;\n}\n\n/**\n * Returns the resolved address which decides the outcome for a hostname, or `null` when every one of them is a public address.\n *\n * Each resolved record is a potential connection target, so each must pass. A metadata address decides the outcome over an internal one, as it is blocked in every mode.\n */\nfunction findBlockedAddress(addresses: string[]): BlockedAddress | null {\n let internal: BlockedAddress | null = null;\n for (const address of addresses) {\n const category = classifyIpAddress(address);\n if (category === 'metadata') {\n return { address, category };\n }\n if (category === 'internal') {\n internal ??= { address, category };\n }\n }\n return internal;\n}\n\n/**\n * Applies `decision` to the addresses a hostname resolved to, logging the outcome, and returning `true` when the request must not be made.\n */\nfunction isResolutionBlocked(\n hostname: string,\n addresses: string[],\n decision: HostGuardDecision,\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): boolean {\n const blocked = findBlockedAddress(addresses);\n if (!blocked) {\n return false;\n }\n\n if (blocked.category === 'internal') {\n if (decision === 'granted') {\n return false;\n }\n if (decision === 'warn-dns') {\n warnInternalHost(hostname, hostType, responseBecomesConfig);\n return false;\n }\n }\n\n logger.warn(\n { hostname, address: blocked.address },\n 'Blocked HTTP request: hostname resolves to a blocked address',\n );\n return true;\n}\n\n/**\n * Validates every address a hostname resolves to, on every connection, which also catches a host whose answer changes between checks (DNS rebinding).\n *\n * The guard is built per request, as the policy it enforces is read from the configuration when the request is made.\n */\nfunction makeGuardedLookup(\n decision: HostGuardDecision,\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): typeof dns.lookup {\n return function guardedLookup(\n hostname: string,\n options: dns.LookupOptions,\n callback: (\n err: NodeJS.ErrnoException | null,\n address: string | dns.LookupAddress[],\n family?: number,\n ) => void,\n ): void {\n dns.lookup(hostname, options, (err, address, family) => {\n if (err) {\n callback(err, address, family);\n return;\n }\n\n // with `options.all`, the result is an array of every record\n const addresses = isString(address)\n ? [address]\n : address.map((entry) => entry.address);\n if (\n isResolutionBlocked(\n hostname,\n addresses,\n decision,\n hostType,\n responseBecomesConfig,\n )\n ) {\n callback(new Error(HOST_BLOCKED), address, family);\n return;\n }\n\n callback(err, address, family);\n });\n // `dns.lookup` is an overloaded function, so the single signature implemented here is not assignable to it without a cast - got only ever calls the `(hostname, options, callback)` overload\n } as typeof dns.lookup;\n}\n\nfunction isPlatformEndpoint(url: URL): boolean {\n const endpoint = GlobalConfig.get('endpoint');\n if (!endpoint) {\n return false;\n }\n // the whole origin must match: another port or scheme on the platform's host is a different service, which the administrator has not vouched for\n return parseUrl(endpoint)?.origin === url.origin;\n}\n\n/**\n * Whether the administrator has permitted internal access for this request, leaving aside the `internalHostAccess` mode: a permitted request neither blocks nor warns, whatever the mode is.\n */\nfunction isInternalGranted(\n url: URL,\n grant: InternalHostGrant | undefined,\n responseBecomesConfig: boolean | undefined,\n): boolean {\n // without its platform, Renovate cannot run at all - the endpoint is the administrator's own choice of host\n if (isPlatformEndpoint(url)) {\n return true;\n }\n\n // a response which becomes configuration can redirect Renovate at anything, so the administrator must have named this host for this purpose, not merely named it\n if (responseBecomesConfig) {\n return grant?.scoped === true;\n }\n\n return grant?.explicit ?? grant?.implicit ?? false;\n}\n\n/**\n * Warns about a request which `internalHostAccess=block` would refuse, once per host, naming the grant which would permit it.\n */\nfunction warnInternalHost(\n hostname: string,\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): void {\n // a response which becomes config needs the deliberately-scoped grant, so pointing at a plain host rule would be misleading advice\n if (responseBecomesConfig) {\n logger.once.warn(\n { hostname, hostType },\n 'HTTP request to an internal host whose response becomes configuration, which `internalHostAccess=block` would refuse - permit it with a `hostRules` entry setting `allowInternal: true`, scoped with a `hostType` or a URL-prefix `matchHost`, or set `internalHostAccess=block` to enforce this now. The default will become `block` in a future major release.',\n );\n return;\n }\n\n logger.once.warn(\n { hostname, hostType },\n 'HTTP request to an internal host, which `internalHostAccess=block` would refuse - permit it with a `hostRules` entry naming the host, or one setting `allowInternal: true`, or set `internalHostAccess=block` to enforce this now. The default will become `block` in a future major release.',\n );\n}\n\n/**\n * Enforce the internal-host policy on a request URL, throwing `HOST_BLOCKED` when the request must not be made.\n *\n * Metadata endpoints are blocked no matter what the configuration says: Renovate's HTTP layer never has a legitimate reason to request them.\n */\nexport function checkUrl(\n url: URL,\n hostType: string | undefined,\n grant: InternalHostGrant | undefined,\n responseBecomesConfig?: boolean,\n): HostGuardDecision {\n const category = classifyUrl(url);\n if (category === 'metadata') {\n logger.warn(\n { url: url.href, hostType },\n 'Blocked HTTP request to a cloud instance-metadata endpoint',\n );\n throw new Error(HOST_BLOCKED);\n }\n\n const mode = GlobalConfig.get('internalHostAccess');\n if (\n mode === 'allow' ||\n isInternalGranted(url, grant, responseBecomesConfig)\n ) {\n if (category === 'internal') {\n logger.once.info(\n `Internal host ${url.hostname} permitted by configuration`,\n );\n }\n return 'granted';\n }\n\n // `warn` reports what `block` would refuse, without refusing it, so that administrators can add the grants they need before the default changes\n if (mode === 'warn') {\n if (category === 'internal') {\n warnInternalHost(url.hostname, hostType, responseBecomesConfig);\n }\n return 'warn-dns';\n }\n\n if (category === 'internal') {\n logger.warn(\n { url: url.href, hostType },\n 'Blocked HTTP request to an internal host - a self-hosted administrator can permit it via `hostRules`, or with `internalHostAccess=allow`',\n );\n throw new Error(HOST_BLOCKED);\n }\n return 'check-dns';\n}\n\n/**\n * Validates what a request's hostname resolves to, before the request is made, for deployments where `dnsLookup` cannot do it.\n *\n * A proxy agent connects to the proxy and hands it the target hostname, so the target is resolved by the proxy and Renovate's `dnsLookup` guard never runs. Resolving here instead is best-effort only: the proxy re-resolves the hostname itself, so a DNS-rebinding or split-horizon answer can still differ from what we saw. Pair it with egress controls on the proxy.\n */\nasync function preflightHostname(\n url: URL,\n decision: HostGuardDecision,\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): Promise<void> {\n const hostname = unbracketHostname(url.hostname);\n if (net.isIP(hostname) !== 0) {\n // an IP-literal host needs no resolution - `checkUrl` has already classified it\n return;\n }\n\n let addresses: dns.LookupAddress[];\n try {\n addresses = await dnsPromises.lookup(hostname, { all: true });\n } catch {\n // fail open: a locked-down proxy environment often has no resolver which can answer for public names at all, and failing closed would break every such deployment\n logger.once.debug(\n `Host guard could not resolve ${hostname} - relying on the proxy for this request`,\n );\n return;\n }\n\n if (\n isResolutionBlocked(\n hostname,\n addresses.map((entry) => entry.address),\n decision,\n hostType,\n responseBecomesConfig,\n )\n ) {\n throw new Error(HOST_BLOCKED);\n }\n}\n\nfunction makeBeforeRequest(\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): BeforeRequestHook {\n return async function hostGuardBeforeRequest(\n options: NormalizedOptions,\n ): Promise<void> {\n const url = options.url instanceof URL ? options.url : null;\n if (!url) {\n // fail closed: without a parsed target there is nothing to validate\n throw new Error(HOST_BLOCKED);\n }\n\n // got runs this hook again for every redirect target, so the decision is re-made for whatever host is about to be requested rather than carried over\n const grant = hostRules.find({\n hostType,\n url: url.toString(),\n }).internalHostGrant;\n await preflightHostname(\n url,\n checkUrl(url, hostType, grant, responseBecomesConfig),\n hostType,\n responseBecomesConfig,\n );\n };\n}\n\n/**\n * Removes the credentials belonging to the host a request is being redirected away from, so that a redirect cannot hand them to another origin.\n *\n * got strips the credentials it knows about itself - `authorization`, `cookie` and any URL userinfo - before this hook runs, and treats a scheme downgrade as a different origin, so an `https:` to `http:` redirect is covered. What it does not know about survives: the `Private-token` header GitLab personal access tokens are sent in (see `applyAuthorization`), and any credential an administrator configured through a `hostRules` `headers` entry.\n *\n * Those headers are dropped rather than replaced with the target host's own: `hostRules` headers are resolved once, when the request is built, so there is nothing to re-apply here. Sending none is the safe outcome.\n */\nfunction stripCrossOriginCredentials(\n options: NormalizedOptions,\n fromUrl: URL | null,\n toUrl: URL,\n hostType: string | undefined,\n): void {\n if (fromUrl?.origin === toUrl.origin) {\n // the credentials are still going to the host they were configured for\n return;\n }\n\n // an unparseable source URL is treated as cross-origin: it cannot be shown to be the same origin, so nothing is carried over\n if (fromUrl) {\n const configured = hostRules.find({\n hostType,\n url: fromUrl.toString(),\n }).headers;\n for (const name of Object.keys(coerceObject(configured))) {\n // got normalizes header names to lower case\n delete options.headers[name.toLowerCase()];\n }\n }\n\n // defence in depth: got has removed these already, but they must never reach another origin\n delete options.headers.authorization;\n delete options.headers.cookie;\n delete options.headers['private-token'];\n}\n\nfunction makeBeforeRedirect(\n hostType: string | undefined,\n responseBecomesConfig: boolean | undefined,\n): BeforeRedirectHook {\n return function hostGuardBeforeRedirect(\n options: NormalizedOptions,\n response: PlainResponse,\n ): void {\n const url = options.url instanceof URL ? options.url : null;\n if (!url) {\n // fail closed: without a parsed target there is nothing to validate\n throw new Error(HOST_BLOCKED);\n }\n\n const fromUrl = isString(response.url) ? parseUrl(response.url) : null;\n stripCrossOriginCredentials(options, fromUrl, url, hostType);\n\n // the original host's verdict must not carry over: the new host gets its own grant lookup and decision\n const grant = hostRules.find({\n hostType,\n url: url.toString(),\n }).internalHostGrant;\n // a redirect target of a config-fetching request is still config-fetching, so the flag carries over even though the verdict does not\n options.dnsLookup = makeGuardedLookup(\n checkUrl(url, hostType, grant, responseBecomesConfig),\n hostType,\n responseBecomesConfig,\n );\n };\n}\n\nexport interface HostGuard {\n dnsLookup: typeof dns.lookup;\n beforeRedirect: BeforeRedirectHook;\n /** Only set when a proxy is configured, which makes `dnsLookup` inert. */\n beforeRequest?: BeforeRequestHook;\n}\n\n/**\n * Enforce the internal-host policy for a request to `url`, throwing `HOST_BLOCKED` when the request must not be made at all.\n *\n * The returned got options carry the policy through the rest of the request's lifetime: `dnsLookup` validates what hostnames resolve to (on every connection, which also covers DNS rebinding), and `beforeRedirect` re-runs this check for every redirect target.\n *\n * When a proxy is configured, the proxy agent resolves the target hostname itself and `dnsLookup` is never called, so a `beforeRequest` hook resolves and validates the hostname up front instead - see {@link preflightHostname} for what that can and cannot catch.\n *\n * `responseBecomesConfig` marks a request whose response is interpreted as Renovate configuration, which an internal host may only serve under a deliberately-scoped `allowInternal` grant.\n *\n * Under the `internalHostAccess=warn` default, an internal host which no grant permits is logged rather than blocked, so that administrators can add the grants they need before the default becomes `block`.\n */\nexport function applyHostGuard(\n url: URL,\n hostType: string | undefined,\n grant: InternalHostGrant | undefined,\n responseBecomesConfig?: boolean,\n): HostGuard {\n const decision = checkUrl(url, hostType, grant, responseBecomesConfig);\n const guard: HostGuard = {\n dnsLookup: makeGuardedLookup(decision, hostType, responseBecomesConfig),\n beforeRedirect: makeBeforeRedirect(hostType, responseBecomesConfig),\n };\n\n if (hasProxy()) {\n guard.beforeRequest = makeBeforeRequest(hostType, responseBecomesConfig);\n }\n\n return guard;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-rules.js","names":["hostRules.find"],"sources":["../../../lib/util/http/host-rules.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../config/global.ts';\nimport {\n BITBUCKET_API_USING_HOST_TYPES,\n BITBUCKET_SERVER_API_USING_HOST_TYPES,\n FORGEJO_API_USING_HOST_TYPES,\n GITEA_API_USING_HOST_TYPES,\n GITHUB_API_USING_HOST_TYPES,\n GITLAB_API_USING_HOST_TYPES,\n} from '../../constants/index.ts';\nimport { logger } from '../../logger/index.ts';\nimport { hasProxy } from '../../proxy.ts';\nimport type { HostRule } from '../../types/index.ts';\nimport * as hostRules from '../host-rules.ts';\nimport { matchRegexOrGlobList } from '../string-match.ts';\nimport { parseUrl } from '../url.ts';\nimport type { InternalHttpOptions } from './http.ts';\nimport { keepAliveAgents } from './keep-alive.ts';\nimport type { GotOptions } from './types.ts';\n\nexport type HostRulesGotOptions = Pick<\n GotOptions & InternalHttpOptions,\n | 'hostType'\n | 'noAuth'\n | 'headers'\n | 'token'\n | 'username'\n | 'password'\n | 'context'\n | 'enabled'\n | 'abortOnError'\n | 'abortIgnoreStatusCodes'\n | 'timeout'\n | 'agent'\n | 'http2'\n | 'https'\n | 'readOnly'\n>;\n\nexport function findMatchingRule<GotOptions extends HostRulesGotOptions>(\n url: string,\n options: GotOptions,\n): HostRule {\n const { hostType, readOnly } = options;\n let res = hostRules.find({ hostType, url, readOnly });\n\n if (\n isNonEmptyString(res.token) ||\n isNonEmptyString(res.username) ||\n isNonEmptyString(res.password)\n ) {\n // do not fallback if we already have auth infos\n return res;\n }\n\n // Fallback to `github` hostType\n if (\n hostType &&\n GITHUB_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'github'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'github',\n url,\n }),\n ...res,\n };\n }\n\n const platform = GlobalConfig.get('platform');\n const platformEndpoint = GlobalConfig.get('endpoint');\n\n // in the case that an API URL is used for GitHub.com, fallback to `github` hostType, and use the `url`'s host to find a `matchHost: api.github.com` (or `matchHost: github.com`)\n if (url.startsWith('https://api.github.com/')) {\n res = {\n ...hostRules.find({\n hostType: 'github',\n url,\n }),\n ...res,\n };\n } else if (platform === 'github' && platformEndpoint) {\n // Fallback to `github` hostType when the request URL targets the same host\n // as the configured GitHub platform endpoint.\n //\n // This covers GitHub Enterprise Server without hardcoding URLs.\n const requestHost = parseUrl(url)?.hostname;\n const endpointHost = parseUrl(platformEndpoint)?.hostname;\n if (requestHost && endpointHost && requestHost === endpointHost) {\n res = {\n ...hostRules.find({ hostType: 'github', url }),\n ...res,\n };\n }\n }\n\n // Fallback to `gitlab` hostType\n if (\n hostType &&\n GITLAB_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'gitlab'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'gitlab',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `bitbucket` hostType\n if (\n hostType &&\n BITBUCKET_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'bitbucket'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'bitbucket',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `bitbucket-server` hostType\n if (\n hostType &&\n BITBUCKET_SERVER_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'bitbucket-server'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'bitbucket-server',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `forgejo` hostType\n if (\n hostType &&\n FORGEJO_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'forgejo'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'forgejo',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `gitea` hostType\n if (\n hostType &&\n GITEA_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'gitea'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'gitea',\n url,\n }),\n ...res,\n };\n }\n\n return res;\n}\n\n// Apply host rules to requests\nexport function applyHostRule<GotOptions extends HostRulesGotOptions>(\n url: string,\n options: GotOptions,\n hostRule: HostRule,\n): GotOptions {\n if (hostRule.enabled === false) {\n options.enabled = false;\n return options;\n }\n\n const { username, password, token, authType } = hostRule;\n const host = parseUrl(url)?.host;\n if (options.noAuth) {\n logger.trace({ url }, `Authorization disabled`);\n } else if (\n isNonEmptyString(options.headers?.authorization) ||\n isNonEmptyString(options.password) ||\n isNonEmptyString(options.token)\n ) {\n logger.once.debug(`hostRules: authentication already set for ${host}`);\n logger.trace({ url }, `Authorization already set`);\n } else if (password !== undefined) {\n logger.once.debug(`hostRules: applying Basic authentication for ${host}`);\n logger.trace({ url }, `Applying Basic authentication`);\n options.username = username;\n options.password = password;\n } else if (token) {\n logger.once.debug(`hostRules: applying Bearer authentication for ${host}`);\n logger.trace({ url }, `Applying Bearer authentication`);\n options.token = token;\n options.context = { ...options.context, authType };\n } else {\n logger.once.debug(`hostRules: no authentication for ${host}`);\n }\n // Apply optional params\n if (hostRule.abortOnError) {\n options.abortOnError = hostRule.abortOnError;\n }\n\n if (hostRule.abortIgnoreStatusCodes) {\n options.abortIgnoreStatusCodes = hostRule.abortIgnoreStatusCodes;\n }\n\n if (hostRule.timeout) {\n options.timeout = hostRule.timeout;\n }\n\n if (hostRule.headers) {\n const allowedHeaders = GlobalConfig.get('allowedHeaders');\n const filteredHeaders: Record<string, string> = {};\n\n for (const [header, value] of Object.entries(hostRule.headers)) {\n if (matchRegexOrGlobList(header, allowedHeaders)) {\n filteredHeaders[header] = value;\n } else {\n logger.once.error(\n { allowedHeaders, header },\n 'Disallowed hostRules headers',\n );\n }\n }\n\n options.headers = {\n ...options.headers,\n ...filteredHeaders,\n };\n }\n\n if (hostRule.keepAlive) {\n options.agent = keepAliveAgents;\n }\n\n if (!hasProxy() && hostRule.enableHttp2 === true) {\n options.http2 = true;\n }\n\n if (isNonEmptyString(hostRule.httpsCertificateAuthority)) {\n options.https = {\n ...options.https,\n certificateAuthority: hostRule.httpsCertificateAuthority,\n };\n }\n\n if (isNonEmptyString(hostRule.httpsPrivateKey)) {\n options.https = {\n ...options.https,\n key: hostRule.httpsPrivateKey,\n };\n }\n\n if (isNonEmptyString(hostRule.httpsCertificate)) {\n options.https = {\n ...options.https,\n certificate: hostRule.httpsCertificate,\n };\n }\n\n return options;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"host-rules.js","names":["hostRules.find"],"sources":["../../../lib/util/http/host-rules.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport { GlobalConfig } from '../../config/global.ts';\nimport {\n BITBUCKET_API_USING_HOST_TYPES,\n BITBUCKET_SERVER_API_USING_HOST_TYPES,\n FORGEJO_API_USING_HOST_TYPES,\n GITEA_API_USING_HOST_TYPES,\n GITHUB_API_USING_HOST_TYPES,\n GITLAB_API_USING_HOST_TYPES,\n} from '../../constants/index.ts';\nimport { logger } from '../../logger/index.ts';\nimport { hasProxy } from '../../proxy.ts';\nimport type { CombinedHostRule, HostRule } from '../../types/index.ts';\nimport * as hostRules from '../host-rules.ts';\nimport { matchRegexOrGlobList } from '../string-match.ts';\nimport { parseUrl } from '../url.ts';\nimport type { InternalHttpOptions } from './http.ts';\nimport { keepAliveAgents } from './keep-alive.ts';\nimport type { GotOptions } from './types.ts';\n\nexport type HostRulesGotOptions = Pick<\n GotOptions & InternalHttpOptions,\n | 'hostType'\n | 'noAuth'\n | 'headers'\n | 'token'\n | 'username'\n | 'password'\n | 'context'\n | 'enabled'\n | 'abortOnError'\n | 'abortIgnoreStatusCodes'\n | 'timeout'\n | 'agent'\n | 'http2'\n | 'https'\n | 'readOnly'\n>;\n\nexport function findMatchingRule<GotOptions extends HostRulesGotOptions>(\n url: string,\n options: GotOptions,\n): CombinedHostRule {\n const { hostType, readOnly } = options;\n let res = hostRules.find({ hostType, url, readOnly });\n\n if (\n isNonEmptyString(res.token) ||\n isNonEmptyString(res.username) ||\n isNonEmptyString(res.password)\n ) {\n // do not fallback if we already have auth infos\n return res;\n }\n\n // Fallback to `github` hostType\n if (\n hostType &&\n GITHUB_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'github'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'github',\n url,\n }),\n ...res,\n };\n }\n\n const platform = GlobalConfig.get('platform');\n const platformEndpoint = GlobalConfig.get('endpoint');\n\n // in the case that an API URL is used for GitHub.com, fallback to `github` hostType, and use the `url`'s host to find a `matchHost: api.github.com` (or `matchHost: github.com`)\n if (url.startsWith('https://api.github.com/')) {\n res = {\n ...hostRules.find({\n hostType: 'github',\n url,\n }),\n ...res,\n };\n } else if (platform === 'github' && platformEndpoint) {\n // Fallback to `github` hostType when the request URL targets the same host\n // as the configured GitHub platform endpoint.\n //\n // This covers GitHub Enterprise Server without hardcoding URLs.\n const requestHost = parseUrl(url)?.hostname;\n const endpointHost = parseUrl(platformEndpoint)?.hostname;\n if (requestHost && endpointHost && requestHost === endpointHost) {\n res = {\n ...hostRules.find({ hostType: 'github', url }),\n ...res,\n };\n }\n }\n\n // Fallback to `gitlab` hostType\n if (\n hostType &&\n GITLAB_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'gitlab'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'gitlab',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `bitbucket` hostType\n if (\n hostType &&\n BITBUCKET_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'bitbucket'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'bitbucket',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `bitbucket-server` hostType\n if (\n hostType &&\n BITBUCKET_SERVER_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'bitbucket-server'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'bitbucket-server',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `forgejo` hostType\n if (\n hostType &&\n FORGEJO_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'forgejo'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'forgejo',\n url,\n }),\n ...res,\n };\n }\n\n // Fallback to `gitea` hostType\n if (\n hostType &&\n GITEA_API_USING_HOST_TYPES.includes(hostType) &&\n hostType !== 'gitea'\n ) {\n res = {\n ...hostRules.find({\n hostType: 'gitea',\n url,\n }),\n ...res,\n };\n }\n\n return res;\n}\n\n// Apply host rules to requests\nexport function applyHostRule<GotOptions extends HostRulesGotOptions>(\n url: string,\n options: GotOptions,\n hostRule: HostRule,\n): GotOptions {\n if (hostRule.enabled === false) {\n options.enabled = false;\n return options;\n }\n\n const { username, password, token, authType } = hostRule;\n const host = parseUrl(url)?.host;\n if (options.noAuth) {\n logger.trace({ url }, `Authorization disabled`);\n } else if (\n isNonEmptyString(options.headers?.authorization) ||\n isNonEmptyString(options.password) ||\n isNonEmptyString(options.token)\n ) {\n logger.once.debug(`hostRules: authentication already set for ${host}`);\n logger.trace({ url }, `Authorization already set`);\n } else if (password !== undefined) {\n logger.once.debug(`hostRules: applying Basic authentication for ${host}`);\n logger.trace({ url }, `Applying Basic authentication`);\n options.username = username;\n options.password = password;\n } else if (token) {\n logger.once.debug(`hostRules: applying Bearer authentication for ${host}`);\n logger.trace({ url }, `Applying Bearer authentication`);\n options.token = token;\n options.context = { ...options.context, authType };\n } else {\n logger.once.debug(`hostRules: no authentication for ${host}`);\n }\n // Apply optional params\n if (hostRule.abortOnError) {\n options.abortOnError = hostRule.abortOnError;\n }\n\n if (hostRule.abortIgnoreStatusCodes) {\n options.abortIgnoreStatusCodes = hostRule.abortIgnoreStatusCodes;\n }\n\n if (hostRule.timeout) {\n options.timeout = hostRule.timeout;\n }\n\n if (hostRule.headers) {\n const allowedHeaders = GlobalConfig.get('allowedHeaders');\n const filteredHeaders: Record<string, string> = {};\n\n for (const [header, value] of Object.entries(hostRule.headers)) {\n if (matchRegexOrGlobList(header, allowedHeaders)) {\n filteredHeaders[header] = value;\n } else {\n logger.once.error(\n { allowedHeaders, header },\n 'Disallowed hostRules headers',\n );\n }\n }\n\n options.headers = {\n ...options.headers,\n ...filteredHeaders,\n };\n }\n\n if (hostRule.keepAlive) {\n options.agent = keepAliveAgents;\n }\n\n if (!hasProxy() && hostRule.enableHttp2 === true) {\n options.http2 = true;\n }\n\n if (isNonEmptyString(hostRule.httpsCertificateAuthority)) {\n options.https = {\n ...options.https,\n certificateAuthority: hostRule.httpsCertificateAuthority,\n };\n }\n\n if (isNonEmptyString(hostRule.httpsPrivateKey)) {\n options.https = {\n ...options.https,\n key: hostRule.httpsPrivateKey,\n };\n }\n\n if (isNonEmptyString(hostRule.httpsCertificate)) {\n options.https = {\n ...options.https,\n certificate: hostRule.httpsCertificate,\n };\n }\n\n return options;\n}\n"],"mappings":"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"}
|
package/dist/util/http/http.d.ts
CHANGED
|
@@ -18,6 +18,14 @@ declare abstract class HttpBase<JSONOpts extends HttpOptions = HttpOptions, Opts
|
|
|
18
18
|
protected get baseUrl(): string | undefined;
|
|
19
19
|
protected hostType: string;
|
|
20
20
|
constructor(hostType: string, options?: HttpOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Builds the final got options for a request to a given `url`
|
|
23
|
+
*
|
|
24
|
+
* This merges instance options, applies default headers, host rules and authorization, and rejects requests to disabled hosts.
|
|
25
|
+
*
|
|
26
|
+
* Both the `request()` and `stream()` paths must use this single entry point so that policy applied here covers every outbound request.
|
|
27
|
+
*/
|
|
28
|
+
private prepareOptions;
|
|
21
29
|
private request;
|
|
22
30
|
private _normalizeOptions;
|
|
23
31
|
/**
|
package/dist/util/http/http.js
CHANGED
|
@@ -3,6 +3,7 @@ import { get, set } from "../cache/memory/index.js";
|
|
|
3
3
|
import { coerceObject } from "../object.js";
|
|
4
4
|
import { getEnv } from "../env.js";
|
|
5
5
|
import { GlobalConfig } from "../../config/global.js";
|
|
6
|
+
import { coerceArray } from "../array.js";
|
|
6
7
|
import { logger } from "../../logger/index.js";
|
|
7
8
|
import { isHttpUrl, parseUrl, resolveBaseUrl } from "../url.js";
|
|
8
9
|
import { ObsoleteCacheHitLogger } from "../stats.js";
|
|
@@ -15,6 +16,7 @@ import { acquireLock } from "../mutex.js";
|
|
|
15
16
|
import { fetch, normalize, stream } from "./got.js";
|
|
16
17
|
import { Result } from "../result.js";
|
|
17
18
|
import { applyAuthorization } from "./auth.js";
|
|
19
|
+
import { applyHostGuard } from "./host-guard.js";
|
|
18
20
|
import { applyHostRule, findMatchingRule } from "./host-rules.js";
|
|
19
21
|
import { getQueue } from "./queue.js";
|
|
20
22
|
import { getRetryAfter, wrapWithRetry } from "./retry-after.js";
|
|
@@ -49,19 +51,21 @@ var HttpBase = class {
|
|
|
49
51
|
}
|
|
50
52
|
}, { isMergeableObject: isPlainObject });
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Builds the final got options for a request to a given `url`
|
|
56
|
+
*
|
|
57
|
+
* This merges instance options, applies default headers, host rules and authorization, and rejects requests to disabled hosts.
|
|
58
|
+
*
|
|
59
|
+
* Both the `request()` and `stream()` paths must use this single entry point so that policy applied here covers every outbound request.
|
|
60
|
+
*/
|
|
61
|
+
prepareOptions(resolvedUrl, httpOptions) {
|
|
54
62
|
const url = resolvedUrl.toString();
|
|
55
|
-
this.processOptions(resolvedUrl, httpOptions);
|
|
56
63
|
let options = merge({
|
|
57
64
|
...this.options,
|
|
58
65
|
hostType: this.hostType
|
|
59
66
|
}, httpOptions, { isMergeableObject: isPlainObject });
|
|
60
|
-
const method = options.method.toLowerCase();
|
|
61
|
-
const isReadMethod = ["head", "get"].includes(method);
|
|
62
|
-
logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);
|
|
63
67
|
applyDefaultHeaders(options);
|
|
64
|
-
if (isUndefined(options.readOnly) &&
|
|
68
|
+
if (isUndefined(options.readOnly) && ["head", "get"].includes(options.method.toLowerCase())) options.readOnly = true;
|
|
65
69
|
const hostRule = findMatchingRule(url, options);
|
|
66
70
|
options = applyHostRule(url, options, hostRule);
|
|
67
71
|
if (options.enabled === false) {
|
|
@@ -69,6 +73,26 @@ var HttpBase = class {
|
|
|
69
73
|
throw new Error(HOST_DISABLED);
|
|
70
74
|
}
|
|
71
75
|
options = applyAuthorization(options);
|
|
76
|
+
const guard = applyHostGuard(resolvedUrl, options.hostType, hostRule.internalHostGrant, options.responseBecomesConfig);
|
|
77
|
+
options.dnsLookup = guard.dnsLookup;
|
|
78
|
+
options.hooks = {
|
|
79
|
+
...options.hooks,
|
|
80
|
+
beforeRedirect: [...coerceArray(options.hooks?.beforeRedirect), guard.beforeRedirect]
|
|
81
|
+
};
|
|
82
|
+
if (guard.beforeRequest) options.hooks.beforeRequest = [...coerceArray(options.hooks.beforeRequest), guard.beforeRequest];
|
|
83
|
+
return {
|
|
84
|
+
options,
|
|
85
|
+
hostRule
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async request(requestUrl, httpOptions) {
|
|
89
|
+
const resolvedUrl = this.resolveUrl(requestUrl, httpOptions);
|
|
90
|
+
const url = resolvedUrl.toString();
|
|
91
|
+
this.processOptions(resolvedUrl, httpOptions);
|
|
92
|
+
const { options, hostRule } = this.prepareOptions(resolvedUrl, httpOptions);
|
|
93
|
+
const method = options.method.toLowerCase();
|
|
94
|
+
const isReadMethod = ["head", "get"].includes(method);
|
|
95
|
+
logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);
|
|
72
96
|
const timeout = options.timeout ?? 6e4;
|
|
73
97
|
options.timeout = timeout;
|
|
74
98
|
let cacheProvider;
|
|
@@ -138,7 +162,8 @@ var HttpBase = class {
|
|
|
138
162
|
return [
|
|
139
163
|
"baseUrl",
|
|
140
164
|
"cacheProvider",
|
|
141
|
-
"readOnly"
|
|
165
|
+
"readOnly",
|
|
166
|
+
"responseBecomesConfig"
|
|
142
167
|
];
|
|
143
168
|
}
|
|
144
169
|
processOptions(_url, _options) {}
|
|
@@ -315,21 +340,12 @@ var HttpBase = class {
|
|
|
315
340
|
return this.requestJson("delete", args);
|
|
316
341
|
}
|
|
317
342
|
stream(url, options) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
hostType: this.hostType,
|
|
343
|
+
const resolvedUrl = this.resolveUrl(url, options);
|
|
344
|
+
const { options: combinedOptions } = this.prepareOptions(resolvedUrl, {
|
|
321
345
|
...options,
|
|
322
346
|
method: "get"
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
applyDefaultHeaders(combinedOptions);
|
|
326
|
-
// v8 ignore else -- TODO: add test #40625
|
|
327
|
-
if (isUndefined(combinedOptions.readOnly) && ["head", "get"].includes(combinedOptions.method)) combinedOptions.readOnly = true;
|
|
328
|
-
const hostRule = findMatchingRule(url, combinedOptions);
|
|
329
|
-
combinedOptions = applyHostRule(resolvedUrl, combinedOptions, hostRule);
|
|
330
|
-
if (combinedOptions.enabled === false) throw new Error(HOST_DISABLED);
|
|
331
|
-
combinedOptions = applyAuthorization(combinedOptions);
|
|
332
|
-
return stream(resolvedUrl, this._normalizeOptions(combinedOptions));
|
|
347
|
+
});
|
|
348
|
+
return stream(resolvedUrl.toString(), this._normalizeOptions(combinedOptions));
|
|
333
349
|
}
|
|
334
350
|
async getToml(arg1, arg2, arg3) {
|
|
335
351
|
const { url, schema, httpOptions } = this.resolveArgs(arg1, arg2, arg3);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":["memCache.get"],"sources":["../../../lib/util/http/http.ts"],"sourcesContent":["import { isPlainObject, isUndefined } from '@sindresorhus/is';\nimport merge from 'deepmerge';\nimport type { Options, OptionsInit, RetryObject } from 'got';\nimport type { Merge, SetRequired } from 'type-fest';\nimport type { z } from 'zod/v4';\nimport { ZodType } from 'zod/v4';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { HOST_DISABLED } from '../../constants/error-messages.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { getEnv } from '../env.ts';\nimport { hash } from '../hash.ts';\nimport { acquireLock } from '../mutex.ts';\nimport { coerceObject } from '../object.ts';\nimport { type AsyncResult, Result } from '../result.ts';\nimport { Toml } from '../schema-utils/index.ts';\nimport { ObsoleteCacheHitLogger } from '../stats.ts';\nimport { compile } from '../template/index.ts';\nimport { isHttpUrl, parseUrl, resolveBaseUrl } from '../url.ts';\nimport { parseSingleYaml } from '../yaml.ts';\nimport { applyAuthorization } from './auth.ts';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport { fetch, normalize, stream } from './got.ts';\nimport { applyHostRule, findMatchingRule } from './host-rules.ts';\nimport { getQueue } from './queue.ts';\nimport { getRetryAfter, wrapWithRetry } from './retry-after.ts';\nimport { getThrottle } from './throttle.ts';\nimport type {\n GotOptions,\n GotStreamOptions,\n GotTask,\n HttpMethod,\n HttpOptions,\n HttpResponse,\n SafeJsonError,\n} from './types.ts';\nimport { copyResponse } from './util.ts';\n\nexport interface InternalJsonUnsafeOptions<\n Opts extends HttpOptions = HttpOptions,\n> {\n url: string | URL;\n httpOptions?: Opts;\n}\n\nexport interface InternalJsonOptions<\n Opts extends HttpOptions,\n ResT = unknown,\n Schema extends ZodType<ResT, any> = ZodType<ResT, any>,\n> extends InternalJsonUnsafeOptions<Opts> {\n schema?: Schema;\n}\n\nexport type InternalGotOptions = SetRequired<GotOptions, 'method' | 'context'>;\n\nexport interface InternalHttpOptions extends HttpOptions {\n json?: HttpOptions['body'];\n\n method?: HttpMethod;\n\n parseJson?: Options['parseJson'];\n}\n\nexport function applyDefaultHeaders(options: OptionsInit): void {\n const userAgentTemplate = GlobalConfig.get('userAgent');\n options.headers = {\n ...options.headers,\n 'user-agent': compile(userAgentTemplate, {}),\n };\n}\n\nexport abstract class HttpBase<\n JSONOpts extends HttpOptions = HttpOptions,\n Opts extends HttpOptions = HttpOptions,\n> {\n private readonly options: InternalGotOptions;\n\n protected get baseUrl(): string | undefined {\n return undefined;\n }\n\n protected hostType: string;\n\n constructor(hostType: string, options: HttpOptions = {}) {\n this.hostType = hostType;\n const retryLimit = getEnv().NODE_ENV === 'test' ? 0 : 2;\n this.options = merge<InternalGotOptions>(\n options,\n {\n method: 'get',\n context: { hostType },\n retry: {\n calculateDelay: (retryObject) =>\n this.calculateRetryDelay(retryObject),\n limit: retryLimit,\n maxRetryAfter: 0, // Don't rely on `got` retry-after handling, just let it fail and then we'll handle it\n enforceRetryRules: false,\n },\n },\n { isMergeableObject: isPlainObject },\n );\n }\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'text' },\n ): Promise<HttpResponse>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'buffer' },\n ): Promise<HttpResponse<Uint8Array>>;\n private async request<T = unknown>(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'json' },\n ): Promise<HttpResponse<T>>;\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<unknown>> {\n const resolvedUrl = this.resolveUrl(requestUrl, httpOptions);\n const url = resolvedUrl.toString();\n\n this.processOptions(resolvedUrl, httpOptions);\n\n let options = merge<InternalGotOptions, InternalHttpOptions>(\n {\n ...this.options,\n hostType: this.hostType,\n },\n httpOptions,\n { isMergeableObject: isPlainObject },\n );\n\n const method = options.method.toLowerCase();\n const isReadMethod = ['head', 'get'].includes(method);\n\n logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);\n\n applyDefaultHeaders(options);\n\n if (isUndefined(options.readOnly) && isReadMethod) {\n options.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, options);\n options = applyHostRule(url, options, hostRule);\n if (options.enabled === false) {\n logger.debug(`Host is disabled - rejecting request. HostUrl: ${url}`);\n throw new Error(HOST_DISABLED);\n }\n options = applyAuthorization(options);\n const timeout = options.timeout ?? 60000;\n options.timeout = timeout;\n\n let cacheProvider: HttpCacheProvider | undefined;\n if (isReadMethod && options.cacheProvider) {\n cacheProvider = options.cacheProvider;\n }\n\n const memCacheKey =\n !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE &&\n !cacheProvider &&\n options.memCache !== false &&\n isReadMethod\n ? hash(\n `got-${JSON.stringify({\n url,\n headers: options.headers,\n method,\n })}`,\n )\n : null;\n\n let resPromise: Promise<HttpResponse<unknown>> | null = null;\n\n // Cache GET requests unless memCache=false\n if (memCacheKey) {\n resPromise = memCache.get(memCacheKey);\n\n /* v8 ignore next: temporary code */\n if (resPromise && !cacheProvider) {\n ObsoleteCacheHitLogger.write(url);\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (!resPromise) {\n if (cacheProvider) {\n await cacheProvider.setCacheHeaders(method, url, options);\n }\n\n const startTime = Date.now();\n const httpTask: GotTask = async () => {\n let releaseLock: undefined | (() => void);\n if (isReadMethod) {\n releaseLock = await acquireLock(\n `${options.method} ${url}`,\n 'http-mutex',\n timeout * 2,\n );\n }\n try {\n const cachedResponse = await cacheProvider?.bypassServer<unknown>(\n options.method,\n url,\n );\n if (cachedResponse) {\n return cachedResponse;\n }\n\n const queueMs = Date.now() - startTime;\n return fetch(url, this._normalizeOptions(options), {\n queueMs,\n });\n } finally {\n releaseLock?.();\n }\n };\n\n const throttle = getThrottle(url);\n const throttledTask = throttle ? () => throttle.add(httpTask) : httpTask;\n\n const queue = getQueue(url);\n const queuedTask = queue ? () => queue.add(throttledTask) : throttledTask;\n\n const { maxRetryAfter = 60 } = hostRule;\n resPromise = wrapWithRetry(queuedTask, url, getRetryAfter, maxRetryAfter);\n\n if (memCacheKey) {\n memCache.set(memCacheKey, resPromise);\n }\n }\n\n try {\n const res = await resPromise;\n const deepCopyNeeded = !!memCacheKey && res.statusCode !== 304;\n const resCopy = copyResponse(res, deepCopyNeeded);\n resCopy.authorization = !!options?.headers?.authorization;\n\n this.handleResponse(resolvedUrl, resCopy);\n\n if (cacheProvider) {\n return await cacheProvider.wrapServerResponse(method, url, resCopy);\n }\n\n return resCopy;\n } catch (err) {\n const { abortOnError, abortIgnoreStatusCodes } = options;\n if (abortOnError && !abortIgnoreStatusCodes?.includes(err.statusCode)) {\n throw new ExternalHostError(err);\n }\n\n const staleResponse = await cacheProvider?.bypassServer<\n string | Uint8Array\n >(method, url, true);\n if (staleResponse) {\n logger.debug(\n { err },\n `Request error: returning stale cache instead for ${url}`,\n );\n return staleResponse;\n }\n\n this.handleError(requestUrl, httpOptions, err);\n }\n }\n\n private _normalizeOptions<T extends OptionsInit>(options: T): T {\n return normalize(options, this.extraOptions());\n }\n\n /**\n * Returns Renovate extra options which needs to be removed before passing to got.\n * @returns extra Renovate options.\n */\n protected extraOptions(): readonly string[] {\n return ['baseUrl', 'cacheProvider', 'readOnly'] as (keyof HttpOptions)[];\n }\n\n protected processOptions(_url: URL, _options: InternalHttpOptions): void {\n // noop\n }\n\n protected handleError(\n _url: string | URL,\n _httpOptions: HttpOptions,\n err: Error,\n ): never {\n throw err;\n }\n\n protected handleResponse(_url: URL, _res: HttpResponse<unknown>): void {\n // noop\n }\n\n resolveUrl(requestUrl: string | URL, options?: HttpOptions): URL {\n let url = requestUrl;\n\n if (url instanceof URL) {\n // already a aboslute URL\n return url;\n }\n\n const baseUrl = options?.baseUrl ?? this.baseUrl;\n if (baseUrl) {\n url = resolveBaseUrl(baseUrl, url);\n }\n\n const parsedUrl = parseUrl(url);\n if (!parsedUrl || !isHttpUrl(parsedUrl)) {\n logger.error(\n { url: requestUrl, baseUrl, resolvedUrl: url },\n 'Request Error: cannot parse url',\n );\n throw new Error('Invalid URL');\n }\n return parsedUrl;\n }\n\n protected calculateRetryDelay({ computedValue }: RetryObject): number {\n return computedValue;\n }\n\n get(\n url: string,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string | Uint8Array>> {\n return this.request(url, options);\n }\n\n head(url: string, options: HttpOptions = {}): Promise<HttpResponse<never>> {\n // to complex to validate\n return this.request(url, {\n ...options,\n responseType: 'text',\n method: 'head',\n }) as Promise<HttpResponse<never>>;\n }\n\n getText(url: string | URL, options: HttpOptions = {}): Promise<HttpResponse> {\n return this.request(url, { ...options, responseType: 'text' });\n }\n\n getBuffer(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<Uint8Array>> {\n return this.request(url, { ...options, responseType: 'buffer' });\n }\n\n protected requestJsonUnsafe<ResT>(\n method: HttpMethod,\n { url, httpOptions: requestOptions }: InternalJsonUnsafeOptions<JSONOpts>,\n ): Promise<HttpResponse<ResT>> {\n const { body: json, ...httpOptions } = { ...requestOptions };\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method,\n };\n // signal that we expect a json response\n opts.headers = {\n accept: 'application/json',\n ...opts.headers,\n };\n if (json) {\n opts.json = json;\n }\n return this.request<ResT>(url, { ...opts, responseType: 'json' });\n }\n\n private async requestJson<\n ResT,\n Schema extends ZodType<ResT, any> = ZodType<ResT, any>,\n >(\n method: HttpMethod,\n options: InternalJsonOptions<JSONOpts, ResT, Schema>,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.requestJsonUnsafe<ResT>(method, options);\n\n if (options.schema) {\n res.body = await options.schema.parseAsync(res.body);\n }\n\n return res;\n }\n\n private resolveArgs<ResT = unknown>(\n arg1: string,\n arg2: JSONOpts | ZodType<ResT> | undefined,\n arg3: ZodType<ResT> | undefined,\n ): InternalJsonOptions<JSONOpts, ResT> {\n const res: InternalJsonOptions<JSONOpts, ResT> = { url: arg1 };\n\n if (arg2 instanceof ZodType) {\n res.schema = arg2;\n } else if (arg2) {\n res.httpOptions = arg2;\n }\n\n if (arg3) {\n res.schema = arg3;\n }\n\n return res;\n }\n\n async getPlain(url: string, options?: Opts): Promise<HttpResponse> {\n const opt = coerceObject(options);\n return await this.getText(url, {\n headers: {\n Accept: 'text/plain',\n },\n ...opt,\n });\n }\n\n /**\n * @deprecated use `getYaml` instead\n */\n async getYamlUnchecked<ResT>(\n url: string,\n options?: Opts,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.getText(url, options);\n const body = parseSingleYaml<ResT>(res.body);\n return { ...res, body };\n }\n\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: Opts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: Opts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n };\n\n const res = await this.getText(url, opts);\n const body = await schema.parseAsync(parseSingleYaml(res.body));\n return { ...res, body };\n }\n\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(url: string, schema: Schema): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n url: string,\n options: Opts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n arg1: string,\n arg2: Opts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n let res: AsyncResult<HttpResponse<ResT>, SafeJsonError>;\n if (httpOptions) {\n res = Result.wrap(this.getYaml(url, httpOptions, schema));\n } else {\n res = Result.wrap(this.getYaml(url, schema));\n }\n\n return res.transform((response) => Result.ok(response.body));\n }\n\n /**\n * Request JSON and return the response without any validation.\n *\n * The usage of this method is discouraged, please use `getJson` instead.\n *\n * If you're new to Zod schema validation library:\n * - consult the [documentation of Zod library](https://github.com/colinhacks/zod?tab=readme-ov-file#basic-usage)\n * - search the Renovate codebase for 'zod' module usage\n * - take a look at the `schema-utils.ts` file for Renovate-specific schemas and utilities\n */\n getJsonUnchecked<ResT = unknown>(\n url: string,\n options?: JSONOpts,\n ): Promise<HttpResponse<ResT>> {\n return this.requestJson<ResT>('get', { url, httpOptions: options });\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * throwing an error if the response is not valid.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const args = this.resolveArgs<z.infer<Schema>>(arg1, arg2, arg3);\n return this.requestJson<z.infer<Schema>>('get', args);\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * wrapping response data in a `Result` class.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const args = this.resolveArgs<ResT>(arg1, arg2, arg3);\n return Result.wrap(this.requestJson<ResT>('get', args)).transform(\n (response) => Result.ok(response.body),\n );\n }\n\n /**\n * @deprecated use `head` instead\n */\n headJson(url: string, httpOptions?: JSONOpts): Promise<HttpResponse<never>> {\n return this.requestJson<never>('head', { url, httpOptions });\n }\n\n postJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('post', args);\n }\n\n putJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs<T>(arg1, arg2, arg3);\n return this.requestJson<T>('put', args);\n }\n\n patchJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('patch', args);\n }\n\n deleteJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('delete', args);\n }\n\n stream(url: string, options?: HttpOptions): NodeJS.ReadableStream {\n let combinedOptions: Merge<\n GotStreamOptions,\n SetRequired<InternalHttpOptions, 'method'>\n > = {\n ...this.options,\n hostType: this.hostType,\n ...options,\n method: 'get',\n };\n\n const resolvedUrl = this.resolveUrl(url, options).toString();\n\n applyDefaultHeaders(combinedOptions);\n\n // v8 ignore else -- TODO: add test #40625\n if (\n isUndefined(combinedOptions.readOnly) &&\n ['head', 'get'].includes(combinedOptions.method)\n ) {\n combinedOptions.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, combinedOptions);\n combinedOptions = applyHostRule(resolvedUrl, combinedOptions, hostRule);\n if (combinedOptions.enabled === false) {\n throw new Error(HOST_DISABLED);\n }\n combinedOptions = applyAuthorization(combinedOptions);\n\n return stream(resolvedUrl, this._normalizeOptions(combinedOptions));\n }\n\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const { url, schema, httpOptions } = this.resolveArgs<z.infer<Schema>>(\n arg1,\n arg2,\n arg3,\n );\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n headers: {\n 'Content-Type': 'application/toml',\n ...httpOptions?.headers,\n },\n };\n\n const res = await this.getText(url, opts);\n if (schema) {\n res.body = await Toml.pipe(schema).parseAsync(res.body);\n } else {\n res.body = (await Toml.parseAsync(res.body)) as z.infer<Schema>;\n }\n\n return res as HttpResponse<z.infer<Schema>>;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http.js","names":["memCache.get"],"sources":["../../../lib/util/http/http.ts"],"sourcesContent":["import { isPlainObject, isUndefined } from '@sindresorhus/is';\nimport merge from 'deepmerge';\nimport type { Options, OptionsInit, RetryObject } from 'got';\nimport type { SetRequired } from 'type-fest';\nimport type { z } from 'zod/v4';\nimport { ZodType } from 'zod/v4';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { HOST_DISABLED } from '../../constants/error-messages.ts';\nimport { logger } from '../../logger/index.ts';\nimport { ExternalHostError } from '../../types/errors/external-host-error.ts';\nimport type { CombinedHostRule } from '../../types/index.ts';\nimport { coerceArray } from '../array.ts';\nimport * as memCache from '../cache/memory/index.ts';\nimport { getEnv } from '../env.ts';\nimport { hash } from '../hash.ts';\nimport { acquireLock } from '../mutex.ts';\nimport { coerceObject } from '../object.ts';\nimport { type AsyncResult, Result } from '../result.ts';\nimport { Toml } from '../schema-utils/index.ts';\nimport { ObsoleteCacheHitLogger } from '../stats.ts';\nimport { compile } from '../template/index.ts';\nimport { isHttpUrl, parseUrl, resolveBaseUrl } from '../url.ts';\nimport { parseSingleYaml } from '../yaml.ts';\nimport { applyAuthorization } from './auth.ts';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport { fetch, normalize, stream } from './got.ts';\nimport { applyHostGuard } from './host-guard.ts';\nimport { applyHostRule, findMatchingRule } from './host-rules.ts';\nimport { getQueue } from './queue.ts';\nimport { getRetryAfter, wrapWithRetry } from './retry-after.ts';\nimport { getThrottle } from './throttle.ts';\nimport type {\n GotOptions,\n GotTask,\n HttpMethod,\n HttpOptions,\n HttpResponse,\n SafeJsonError,\n} from './types.ts';\nimport { copyResponse } from './util.ts';\n\nexport interface InternalJsonUnsafeOptions<\n Opts extends HttpOptions = HttpOptions,\n> {\n url: string | URL;\n httpOptions?: Opts;\n}\n\nexport interface InternalJsonOptions<\n Opts extends HttpOptions,\n ResT = unknown,\n Schema extends ZodType<ResT, any> = ZodType<ResT, any>,\n> extends InternalJsonUnsafeOptions<Opts> {\n schema?: Schema;\n}\n\nexport type InternalGotOptions = SetRequired<GotOptions, 'method' | 'context'>;\n\nexport interface InternalHttpOptions extends HttpOptions {\n json?: HttpOptions['body'];\n\n method?: HttpMethod;\n\n parseJson?: Options['parseJson'];\n}\n\nexport function applyDefaultHeaders(options: OptionsInit): void {\n const userAgentTemplate = GlobalConfig.get('userAgent');\n options.headers = {\n ...options.headers,\n 'user-agent': compile(userAgentTemplate, {}),\n };\n}\n\nexport abstract class HttpBase<\n JSONOpts extends HttpOptions = HttpOptions,\n Opts extends HttpOptions = HttpOptions,\n> {\n private readonly options: InternalGotOptions;\n\n protected get baseUrl(): string | undefined {\n return undefined;\n }\n\n protected hostType: string;\n\n constructor(hostType: string, options: HttpOptions = {}) {\n this.hostType = hostType;\n const retryLimit = getEnv().NODE_ENV === 'test' ? 0 : 2;\n this.options = merge<InternalGotOptions>(\n options,\n {\n method: 'get',\n context: { hostType },\n retry: {\n calculateDelay: (retryObject) =>\n this.calculateRetryDelay(retryObject),\n limit: retryLimit,\n maxRetryAfter: 0, // Don't rely on `got` retry-after handling, just let it fail and then we'll handle it\n enforceRetryRules: false,\n },\n },\n { isMergeableObject: isPlainObject },\n );\n }\n\n /**\n * Builds the final got options for a request to a given `url`\n *\n * This merges instance options, applies default headers, host rules and authorization, and rejects requests to disabled hosts.\n *\n * Both the `request()` and `stream()` paths must use this single entry point so that policy applied here covers every outbound request.\n */\n private prepareOptions(\n resolvedUrl: URL,\n httpOptions: InternalHttpOptions,\n ): {\n options: InternalGotOptions & InternalHttpOptions;\n hostRule: CombinedHostRule;\n } {\n const url = resolvedUrl.toString();\n\n let options = merge<InternalGotOptions, InternalHttpOptions>(\n {\n ...this.options,\n hostType: this.hostType,\n },\n httpOptions,\n { isMergeableObject: isPlainObject },\n );\n\n applyDefaultHeaders(options);\n\n if (\n isUndefined(options.readOnly) &&\n ['head', 'get'].includes(options.method.toLowerCase())\n ) {\n options.readOnly = true;\n }\n\n const hostRule = findMatchingRule(url, options);\n options = applyHostRule(url, options, hostRule);\n if (options.enabled === false) {\n logger.debug(`Host is disabled - rejecting request. HostUrl: ${url}`);\n throw new Error(HOST_DISABLED);\n }\n options = applyAuthorization(options);\n\n // enforced here so it runs before anything else - including cache lookups - can act on the URL, and for the stream path too\n const guard = applyHostGuard(\n resolvedUrl,\n options.hostType,\n hostRule.internalHostGrant,\n options.responseBecomesConfig,\n );\n options.dnsLookup = guard.dnsLookup;\n options.hooks = {\n ...options.hooks,\n beforeRedirect: [\n ...coerceArray(options.hooks?.beforeRedirect),\n guard.beforeRedirect,\n ],\n };\n if (guard.beforeRequest) {\n options.hooks.beforeRequest = [\n ...coerceArray(options.hooks.beforeRequest),\n guard.beforeRequest,\n ];\n }\n\n return { options, hostRule };\n }\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'text' },\n ): Promise<HttpResponse>;\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'buffer' },\n ): Promise<HttpResponse<Uint8Array>>;\n private async request<T = unknown>(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions & { responseType: 'json' },\n ): Promise<HttpResponse<T>>;\n\n private async request(\n requestUrl: string | URL,\n httpOptions: InternalHttpOptions,\n ): Promise<HttpResponse<unknown>> {\n const resolvedUrl = this.resolveUrl(requestUrl, httpOptions);\n const url = resolvedUrl.toString();\n\n this.processOptions(resolvedUrl, httpOptions);\n\n const { options, hostRule } = this.prepareOptions(resolvedUrl, httpOptions);\n\n const method = options.method.toLowerCase();\n const isReadMethod = ['head', 'get'].includes(method);\n\n logger.trace(`HTTP request: ${method.toUpperCase()} ${url}`);\n\n const timeout = options.timeout ?? 60000;\n options.timeout = timeout;\n\n let cacheProvider: HttpCacheProvider | undefined;\n if (isReadMethod && options.cacheProvider) {\n cacheProvider = options.cacheProvider;\n }\n\n const memCacheKey =\n !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE &&\n !cacheProvider &&\n options.memCache !== false &&\n isReadMethod\n ? hash(\n `got-${JSON.stringify({\n url,\n headers: options.headers,\n method,\n })}`,\n )\n : null;\n\n let resPromise: Promise<HttpResponse<unknown>> | null = null;\n\n // Cache GET requests unless memCache=false\n if (memCacheKey) {\n resPromise = memCache.get(memCacheKey);\n\n /* v8 ignore next: temporary code */\n if (resPromise && !cacheProvider) {\n ObsoleteCacheHitLogger.write(url);\n }\n }\n\n // v8 ignore else -- TODO: add test #40625\n if (!resPromise) {\n if (cacheProvider) {\n await cacheProvider.setCacheHeaders(method, url, options);\n }\n\n const startTime = Date.now();\n const httpTask: GotTask = async () => {\n let releaseLock: undefined | (() => void);\n if (isReadMethod) {\n releaseLock = await acquireLock(\n `${options.method} ${url}`,\n 'http-mutex',\n timeout * 2,\n );\n }\n try {\n const cachedResponse = await cacheProvider?.bypassServer<unknown>(\n options.method,\n url,\n );\n if (cachedResponse) {\n return cachedResponse;\n }\n\n const queueMs = Date.now() - startTime;\n return fetch(url, this._normalizeOptions(options), {\n queueMs,\n });\n } finally {\n releaseLock?.();\n }\n };\n\n const throttle = getThrottle(url);\n const throttledTask = throttle ? () => throttle.add(httpTask) : httpTask;\n\n const queue = getQueue(url);\n const queuedTask = queue ? () => queue.add(throttledTask) : throttledTask;\n\n const { maxRetryAfter = 60 } = hostRule;\n resPromise = wrapWithRetry(queuedTask, url, getRetryAfter, maxRetryAfter);\n\n if (memCacheKey) {\n memCache.set(memCacheKey, resPromise);\n }\n }\n\n try {\n const res = await resPromise;\n const deepCopyNeeded = !!memCacheKey && res.statusCode !== 304;\n const resCopy = copyResponse(res, deepCopyNeeded);\n resCopy.authorization = !!options?.headers?.authorization;\n\n this.handleResponse(resolvedUrl, resCopy);\n\n if (cacheProvider) {\n return await cacheProvider.wrapServerResponse(method, url, resCopy);\n }\n\n return resCopy;\n } catch (err) {\n const { abortOnError, abortIgnoreStatusCodes } = options;\n if (abortOnError && !abortIgnoreStatusCodes?.includes(err.statusCode)) {\n throw new ExternalHostError(err);\n }\n\n const staleResponse = await cacheProvider?.bypassServer<\n string | Uint8Array\n >(method, url, true);\n if (staleResponse) {\n logger.debug(\n { err },\n `Request error: returning stale cache instead for ${url}`,\n );\n return staleResponse;\n }\n\n this.handleError(requestUrl, httpOptions, err);\n }\n }\n\n private _normalizeOptions<T extends OptionsInit>(options: T): T {\n return normalize(options, this.extraOptions());\n }\n\n /**\n * Returns Renovate extra options which needs to be removed before passing to got.\n * @returns extra Renovate options.\n */\n protected extraOptions(): readonly string[] {\n return [\n 'baseUrl',\n 'cacheProvider',\n 'readOnly',\n 'responseBecomesConfig',\n ] as (keyof HttpOptions)[];\n }\n\n protected processOptions(_url: URL, _options: InternalHttpOptions): void {\n // noop\n }\n\n protected handleError(\n _url: string | URL,\n _httpOptions: HttpOptions,\n err: Error,\n ): never {\n throw err;\n }\n\n protected handleResponse(_url: URL, _res: HttpResponse<unknown>): void {\n // noop\n }\n\n resolveUrl(requestUrl: string | URL, options?: HttpOptions): URL {\n let url = requestUrl;\n\n if (url instanceof URL) {\n // already a aboslute URL\n return url;\n }\n\n const baseUrl = options?.baseUrl ?? this.baseUrl;\n if (baseUrl) {\n url = resolveBaseUrl(baseUrl, url);\n }\n\n const parsedUrl = parseUrl(url);\n if (!parsedUrl || !isHttpUrl(parsedUrl)) {\n logger.error(\n { url: requestUrl, baseUrl, resolvedUrl: url },\n 'Request Error: cannot parse url',\n );\n throw new Error('Invalid URL');\n }\n return parsedUrl;\n }\n\n protected calculateRetryDelay({ computedValue }: RetryObject): number {\n return computedValue;\n }\n\n get(\n url: string,\n options: HttpOptions = {},\n ): Promise<HttpResponse<string | Uint8Array>> {\n return this.request(url, options);\n }\n\n head(url: string, options: HttpOptions = {}): Promise<HttpResponse<never>> {\n // to complex to validate\n return this.request(url, {\n ...options,\n responseType: 'text',\n method: 'head',\n }) as Promise<HttpResponse<never>>;\n }\n\n getText(url: string | URL, options: HttpOptions = {}): Promise<HttpResponse> {\n return this.request(url, { ...options, responseType: 'text' });\n }\n\n getBuffer(\n url: string | URL,\n options: HttpOptions = {},\n ): Promise<HttpResponse<Uint8Array>> {\n return this.request(url, { ...options, responseType: 'buffer' });\n }\n\n protected requestJsonUnsafe<ResT>(\n method: HttpMethod,\n { url, httpOptions: requestOptions }: InternalJsonUnsafeOptions<JSONOpts>,\n ): Promise<HttpResponse<ResT>> {\n const { body: json, ...httpOptions } = { ...requestOptions };\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method,\n };\n // signal that we expect a json response\n opts.headers = {\n accept: 'application/json',\n ...opts.headers,\n };\n if (json) {\n opts.json = json;\n }\n return this.request<ResT>(url, { ...opts, responseType: 'json' });\n }\n\n private async requestJson<\n ResT,\n Schema extends ZodType<ResT, any> = ZodType<ResT, any>,\n >(\n method: HttpMethod,\n options: InternalJsonOptions<JSONOpts, ResT, Schema>,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.requestJsonUnsafe<ResT>(method, options);\n\n if (options.schema) {\n res.body = await options.schema.parseAsync(res.body);\n }\n\n return res;\n }\n\n private resolveArgs<ResT = unknown>(\n arg1: string,\n arg2: JSONOpts | ZodType<ResT> | undefined,\n arg3: ZodType<ResT> | undefined,\n ): InternalJsonOptions<JSONOpts, ResT> {\n const res: InternalJsonOptions<JSONOpts, ResT> = { url: arg1 };\n\n if (arg2 instanceof ZodType) {\n res.schema = arg2;\n } else if (arg2) {\n res.httpOptions = arg2;\n }\n\n if (arg3) {\n res.schema = arg3;\n }\n\n return res;\n }\n\n async getPlain(url: string, options?: Opts): Promise<HttpResponse> {\n const opt = coerceObject(options);\n return await this.getText(url, {\n headers: {\n Accept: 'text/plain',\n },\n ...opt,\n });\n }\n\n /**\n * @deprecated use `getYaml` instead\n */\n async getYamlUnchecked<ResT>(\n url: string,\n options?: Opts,\n ): Promise<HttpResponse<ResT>> {\n const res = await this.getText(url, options);\n const body = parseSingleYaml<ResT>(res.body);\n return { ...res, body };\n }\n\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: Opts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getYaml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: Opts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n };\n\n const res = await this.getText(url, opts);\n const body = await schema.parseAsync(parseSingleYaml(res.body));\n return { ...res, body };\n }\n\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(url: string, schema: Schema): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n url: string,\n options: Opts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getYamlSafe<\n ResT extends NonNullable<unknown>,\n Schema extends ZodType<ResT> = ZodType<ResT>,\n >(\n arg1: string,\n arg2: Opts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const url = arg1;\n let schema: Schema;\n let httpOptions: Opts | undefined;\n if (arg3) {\n schema = arg3;\n httpOptions = arg2 as Opts;\n } else {\n schema = arg2 as Schema;\n }\n\n let res: AsyncResult<HttpResponse<ResT>, SafeJsonError>;\n if (httpOptions) {\n res = Result.wrap(this.getYaml(url, httpOptions, schema));\n } else {\n res = Result.wrap(this.getYaml(url, schema));\n }\n\n return res.transform((response) => Result.ok(response.body));\n }\n\n /**\n * Request JSON and return the response without any validation.\n *\n * The usage of this method is discouraged, please use `getJson` instead.\n *\n * If you're new to Zod schema validation library:\n * - consult the [documentation of Zod library](https://github.com/colinhacks/zod?tab=readme-ov-file#basic-usage)\n * - search the Renovate codebase for 'zod' module usage\n * - take a look at the `schema-utils.ts` file for Renovate-specific schemas and utilities\n */\n getJsonUnchecked<ResT = unknown>(\n url: string,\n options?: JSONOpts,\n ): Promise<HttpResponse<ResT>> {\n return this.requestJson<ResT>('get', { url, httpOptions: options });\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * throwing an error if the response is not valid.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n getJson<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const args = this.resolveArgs<z.infer<Schema>>(arg1, arg2, arg3);\n return this.requestJson<z.infer<Schema>>('get', args);\n }\n\n /**\n * Request JSON with a Zod schema for the response,\n * wrapping response data in a `Result` class.\n *\n * @param url\n * @param schema Zod schema for the response\n */\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): AsyncResult<z.infer<Schema>, SafeJsonError>;\n getJsonSafe<ResT extends NonNullable<unknown>, Schema extends ZodType<ResT>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): AsyncResult<ResT, SafeJsonError> {\n const args = this.resolveArgs<ResT>(arg1, arg2, arg3);\n return Result.wrap(this.requestJson<ResT>('get', args)).transform(\n (response) => Result.ok(response.body),\n );\n }\n\n /**\n * @deprecated use `head` instead\n */\n headJson(url: string, httpOptions?: JSONOpts): Promise<HttpResponse<never>> {\n return this.requestJson<never>('head', { url, httpOptions });\n }\n\n postJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n postJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('post', args);\n }\n\n putJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n putJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs<T>(arg1, arg2, arg3);\n return this.requestJson<T>('put', args);\n }\n\n patchJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n patchJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('patch', args);\n }\n\n deleteJson<T>(url: string, options?: JSONOpts): Promise<HttpResponse<T>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T, Schema extends ZodType<T> = ZodType<T>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n deleteJson<T = unknown, Schema extends ZodType<T> = ZodType<T>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<T>> {\n const args = this.resolveArgs(arg1, arg2, arg3);\n return this.requestJson<T>('delete', args);\n }\n\n stream(url: string, options?: HttpOptions): NodeJS.ReadableStream {\n const resolvedUrl = this.resolveUrl(url, options);\n\n const { options: combinedOptions } = this.prepareOptions(resolvedUrl, {\n ...options,\n method: 'get',\n });\n\n return stream(\n resolvedUrl.toString(),\n this._normalizeOptions(combinedOptions),\n );\n }\n\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n schema?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n url: string,\n options: JSONOpts,\n schema: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>>;\n async getToml<Schema extends ZodType<any, any, any>>(\n arg1: string,\n arg2?: JSONOpts | Schema,\n arg3?: Schema,\n ): Promise<HttpResponse<z.infer<Schema>>> {\n const { url, schema, httpOptions } = this.resolveArgs<z.infer<Schema>>(\n arg1,\n arg2,\n arg3,\n );\n\n const opts: InternalHttpOptions = {\n ...httpOptions,\n method: 'get',\n headers: {\n 'Content-Type': 'application/toml',\n ...httpOptions?.headers,\n },\n };\n\n const res = await this.getText(url, opts);\n if (schema) {\n res.body = await Toml.pipe(schema).parseAsync(res.body);\n } else {\n res.body = (await Toml.parseAsync(res.body)) as z.infer<Schema>;\n }\n\n return res as HttpResponse<z.infer<Schema>>;\n }\n}\n"],"mappings":"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"}
|
|
@@ -65,6 +65,12 @@ interface HttpOptions {
|
|
|
65
65
|
memCache?: boolean;
|
|
66
66
|
cacheProvider?: HttpCacheProvider;
|
|
67
67
|
readOnly?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The response body becomes Renovate configuration, so an internal host must be permitted by a deliberately-scoped `allowInternal` grant rather than an implicit one - see `applyHostGuard`.
|
|
70
|
+
*
|
|
71
|
+
* Set it on any request whose response is interpreted as config, no matter which `hostType` the request is made with.
|
|
72
|
+
*/
|
|
73
|
+
responseBecomesConfig?: boolean;
|
|
68
74
|
}
|
|
69
75
|
interface HttpHeaders extends IncomingHttpHeaders {
|
|
70
76
|
link?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../../lib/util/http/types.ts"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport type {\n OptionsInit,\n OptionsOfBufferResponseBody,\n OptionsOfJSONResponseBody,\n OptionsOfTextResponseBody,\n RequestError,\n} from 'got';\nimport type { ZodError } from 'zod/v4';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport type { EmptyResultError } from './errors.ts';\n\nexport type GotContextOptions = {\n authType?: string;\n} & Record<string, unknown>;\n\n// TODO: Move options to context\nexport type GotOptions = GotBufferOptions | GotTextOptions | GotJSONOptions;\nexport type GotBufferOptions = OptionsOfBufferResponseBody & GotExtraOptions;\nexport type GotTextOptions = OptionsOfTextResponseBody & GotExtraOptions;\nexport type GotJSONOptions = OptionsOfJSONResponseBody & GotExtraOptions;\n\nexport type GotStreamOptions = OptionsInit & GotExtraOptions;\n\n/**\n * Renovate extra options.\n */\nexport interface GotExtraOptions {\n abortOnError?: boolean;\n abortIgnoreStatusCodes?: number[];\n\n token?: string;\n hostType?: string;\n enabled?: boolean;\n memCache?: boolean;\n noAuth?: boolean;\n context?: GotContextOptions;\n\n /**\n * Got request timeout, overrides got interface.\n * Do not delete in `normalizeGotOptions`.\n */\n timeout?: number;\n}\n\n/**\n * Renovate extra options that are not part of `got` options.\n */\nexport const GotExtraOptionKeys: (keyof GotExtraOptions)[] = [\n 'abortOnError',\n 'abortIgnoreStatusCodes',\n 'enabled',\n 'hostType',\n 'memCache',\n 'noAuth',\n 'token',\n];\n\nexport type OutgoingHttpHeaders = Record<string, string | string[] | undefined>;\n\nexport type GraphqlVariables = Record<string, unknown>;\n\nexport interface GraphqlOptions {\n variables?: GraphqlVariables;\n paginate?: boolean;\n count?: number;\n limit?: number;\n cursor?: string | null;\n acceptHeader?: string;\n token?: string;\n readOnly?: boolean;\n}\n\n/**\n * Renovate http options that are partly not part of `got` options.\n * Remember to delete these in `normalizeGotOptions` before passing to `got`.\n */\nexport interface HttpOptions {\n body?: any;\n username?: string;\n password?: string;\n baseUrl?: string;\n headers?: OutgoingHttpHeaders;\n\n /**\n * Do not use authentication\n */\n noAuth?: boolean;\n\n throwHttpErrors?: boolean;\n\n token?: string;\n memCache?: boolean;\n cacheProvider?: HttpCacheProvider;\n readOnly?: boolean;\n}\n\nexport interface HttpHeaders extends IncomingHttpHeaders {\n link?: string | undefined;\n}\n\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head';\n\nexport interface HttpResponse<T = string> {\n statusCode: number;\n body: T;\n headers: HttpHeaders;\n authorization?: boolean;\n cached?: boolean;\n}\n\nexport type Task<T> = () => Promise<T>;\nexport type GotTask<T = unknown> = Task<HttpResponse<T>>;\n\nexport interface ThrottleLimitRule {\n matchHost: string;\n throttleMs: number;\n}\n\nexport interface ConcurrencyLimitRule {\n matchHost: string;\n concurrency: number;\n}\n\nexport type SafeJsonError = RequestError | ZodError | EmptyResultError;\n"],"mappings":";;;;AAgDA,MAAa,qBAAgD;CAC3D;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../lib/util/http/types.ts"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport type {\n OptionsInit,\n OptionsOfBufferResponseBody,\n OptionsOfJSONResponseBody,\n OptionsOfTextResponseBody,\n RequestError,\n} from 'got';\nimport type { ZodError } from 'zod/v4';\nimport type { HttpCacheProvider } from './cache/types.ts';\nimport type { EmptyResultError } from './errors.ts';\n\nexport type GotContextOptions = {\n authType?: string;\n} & Record<string, unknown>;\n\n// TODO: Move options to context\nexport type GotOptions = GotBufferOptions | GotTextOptions | GotJSONOptions;\nexport type GotBufferOptions = OptionsOfBufferResponseBody & GotExtraOptions;\nexport type GotTextOptions = OptionsOfTextResponseBody & GotExtraOptions;\nexport type GotJSONOptions = OptionsOfJSONResponseBody & GotExtraOptions;\n\nexport type GotStreamOptions = OptionsInit & GotExtraOptions;\n\n/**\n * Renovate extra options.\n */\nexport interface GotExtraOptions {\n abortOnError?: boolean;\n abortIgnoreStatusCodes?: number[];\n\n token?: string;\n hostType?: string;\n enabled?: boolean;\n memCache?: boolean;\n noAuth?: boolean;\n context?: GotContextOptions;\n\n /**\n * Got request timeout, overrides got interface.\n * Do not delete in `normalizeGotOptions`.\n */\n timeout?: number;\n}\n\n/**\n * Renovate extra options that are not part of `got` options.\n */\nexport const GotExtraOptionKeys: (keyof GotExtraOptions)[] = [\n 'abortOnError',\n 'abortIgnoreStatusCodes',\n 'enabled',\n 'hostType',\n 'memCache',\n 'noAuth',\n 'token',\n];\n\nexport type OutgoingHttpHeaders = Record<string, string | string[] | undefined>;\n\nexport type GraphqlVariables = Record<string, unknown>;\n\nexport interface GraphqlOptions {\n variables?: GraphqlVariables;\n paginate?: boolean;\n count?: number;\n limit?: number;\n cursor?: string | null;\n acceptHeader?: string;\n token?: string;\n readOnly?: boolean;\n}\n\n/**\n * Renovate http options that are partly not part of `got` options.\n * Remember to delete these in `normalizeGotOptions` before passing to `got`.\n */\nexport interface HttpOptions {\n body?: any;\n username?: string;\n password?: string;\n baseUrl?: string;\n headers?: OutgoingHttpHeaders;\n\n /**\n * Do not use authentication\n */\n noAuth?: boolean;\n\n throwHttpErrors?: boolean;\n\n token?: string;\n memCache?: boolean;\n cacheProvider?: HttpCacheProvider;\n readOnly?: boolean;\n\n /**\n * The response body becomes Renovate configuration, so an internal host must be permitted by a deliberately-scoped `allowInternal` grant rather than an implicit one - see `applyHostGuard`.\n *\n * Set it on any request whose response is interpreted as config, no matter which `hostType` the request is made with.\n */\n responseBecomesConfig?: boolean;\n}\n\nexport interface HttpHeaders extends IncomingHttpHeaders {\n link?: string | undefined;\n}\n\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head';\n\nexport interface HttpResponse<T = string> {\n statusCode: number;\n body: T;\n headers: HttpHeaders;\n authorization?: boolean;\n cached?: boolean;\n}\n\nexport type Task<T> = () => Promise<T>;\nexport type GotTask<T = unknown> = Task<HttpResponse<T>>;\n\nexport interface ThrottleLimitRule {\n matchHost: string;\n throttleMs: number;\n}\n\nexport interface ConcurrencyLimitRule {\n matchHost: string;\n concurrency: number;\n}\n\nexport type SafeJsonError = RequestError | ZodError | EmptyResultError;\n"],"mappings":";;;;AAgDA,MAAa,qBAAgD;CAC3D;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
package/dist/util/http/util.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../../constants/error-messages.js";
|
|
1
2
|
import { clone } from "../clone.js";
|
|
2
3
|
//#region lib/util/http/util.ts
|
|
3
4
|
function copyResponse({ statusCode, headers, body, cached }, deep) {
|
|
@@ -13,7 +14,15 @@ function copyResponse({ statusCode, headers, body, cached }, deep) {
|
|
|
13
14
|
if (cached) res.cached = true;
|
|
14
15
|
return res;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* The log message for a request the HTTP layer refused, distinguishing a host blocked by the internal-host policy from one an administrator disabled.
|
|
19
|
+
*
|
|
20
|
+
* Both are reported the same way by their callers - traced and swallowed - so only the wording tells them apart in the logs.
|
|
21
|
+
*/
|
|
22
|
+
function refusedHostMessage(err) {
|
|
23
|
+
return err.message === "host-blocked" ? "Host blocked" : "Host disabled";
|
|
24
|
+
}
|
|
16
25
|
//#endregion
|
|
17
|
-
export { copyResponse };
|
|
26
|
+
export { copyResponse, refusedHostMessage };
|
|
18
27
|
|
|
19
28
|
//# sourceMappingURL=util.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","names":[],"sources":["../../../lib/util/http/util.ts"],"sourcesContent":["import { clone } from '../clone.ts';\nimport type { HttpResponse } from './types.ts';\n\n// Copying will help to avoid circular structure\n// and mutation of the cached response.\nexport function copyResponse<T>(\n { statusCode, headers, body, cached }: HttpResponse<T>,\n deep: boolean,\n): HttpResponse<T> {\n const res: HttpResponse<T> = { statusCode, headers, body };\n\n if (deep) {\n res.headers = clone(headers);\n res.body =\n body instanceof Uint8Array ? (body.subarray() as T) : clone<T>(body);\n }\n\n if (cached) {\n res.cached = true;\n }\n\n return res;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.js","names":[],"sources":["../../../lib/util/http/util.ts"],"sourcesContent":["import { HOST_BLOCKED } from '../../constants/error-messages.ts';\nimport { clone } from '../clone.ts';\nimport type { HttpResponse } from './types.ts';\n\n// Copying will help to avoid circular structure\n// and mutation of the cached response.\nexport function copyResponse<T>(\n { statusCode, headers, body, cached }: HttpResponse<T>,\n deep: boolean,\n): HttpResponse<T> {\n const res: HttpResponse<T> = { statusCode, headers, body };\n\n if (deep) {\n res.headers = clone(headers);\n res.body =\n body instanceof Uint8Array ? (body.subarray() as T) : clone<T>(body);\n }\n\n if (cached) {\n res.cached = true;\n }\n\n return res;\n}\n\n/**\n * The log message for a request the HTTP layer refused, distinguishing a host blocked by the internal-host policy from one an administrator disabled.\n *\n * Both are reported the same way by their callers - traced and swallowed - so only the wording tells them apart in the logs.\n */\nexport function refusedHostMessage(err: Error): string {\n return err.message === HOST_BLOCKED ? 'Host blocked' : 'Host disabled';\n}\n"],"mappings":";;;AAMA,SAAgB,aACd,EAAE,YAAY,SAAS,MAAM,UAC7B,MACiB;CACjB,MAAM,MAAuB;EAAE;EAAY;EAAS;CAAK;CAEzD,IAAI,MAAM;EACR,IAAI,UAAU,MAAM,OAAO;EAC3B,IAAI,OACF,gBAAgB,aAAc,KAAK,SAAS,IAAU,MAAS,IAAI;CACvE;CAEA,IAAI,QACF,IAAI,SAAS;CAGf,OAAO;AACT;;;;;;AAOA,SAAgB,mBAAmB,KAAoB;CACrD,OAAO,IAAI,YAAA,iBAA2B,iBAAiB;AACzD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CONFIG_INHERIT_NOT_FOUND, CONFIG_INHERIT_PARSE_ERROR, CONFIG_VALIDATION } from "../../../constants/error-messages.js";
|
|
2
2
|
import { coerceObject } from "../../../util/object.js";
|
|
3
3
|
import { setUserConfigFileNames } from "../../../config/app-strings.js";
|
|
4
|
+
import { GlobalConfig } from "../../../config/global.js";
|
|
4
5
|
import { logger } from "../../../logger/index.js";
|
|
5
6
|
import { mergeChildConfig } from "../../../config/utils.js";
|
|
6
7
|
import { InheritConfig } from "../../../config/inherit.js";
|
|
@@ -16,6 +17,28 @@ import { applyHostRules } from "./merge.js";
|
|
|
16
17
|
import { isNonEmptyArray, isNullOrUndefined, isString } from "@sindresorhus/is";
|
|
17
18
|
import { dequal } from "dequal";
|
|
18
19
|
//#region lib/workers/repository/init/inherited.ts
|
|
20
|
+
const inheritedConfigValidationError = "The inherited config contains some invalid settings";
|
|
21
|
+
/**
|
|
22
|
+
* Report an inherited config validation failure against the inherited config, rather than the repository being processed.
|
|
23
|
+
*
|
|
24
|
+
* The inherited config repository is managed by the organization's administrators, so a fault there is not one the repository's owners have introduced - and they may not even be able to read the file to see it.
|
|
25
|
+
*/
|
|
26
|
+
function throwInheritedConfigValidationError(validationSource, errors) {
|
|
27
|
+
const error = new Error(CONFIG_VALIDATION);
|
|
28
|
+
error.validationSource = validationSource;
|
|
29
|
+
error.validationError = inheritedConfigValidationError;
|
|
30
|
+
error.validationMessage = errors.map((err) => err.message).join(", ");
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* How the inherited config's `hostRules` are registered.
|
|
35
|
+
*
|
|
36
|
+
* The inherited config repository is controlled by the organization's administrators rather than by the self-hosted administrator, so its rules are untrusted unless the administrator has opted into trusting them.
|
|
37
|
+
*/
|
|
38
|
+
function inheritedHostRuleOptions() {
|
|
39
|
+
if (!GlobalConfig.get("inheritConfigTrusted")) return;
|
|
40
|
+
return { inherited: true };
|
|
41
|
+
}
|
|
19
42
|
async function mergeInheritedConfig(config) {
|
|
20
43
|
if (!config.repository || !config.inheritConfig) return config;
|
|
21
44
|
if (!isString(config.inheritConfigRepoName) || !isString(config.inheritConfigFileName)) {
|
|
@@ -55,12 +78,13 @@ async function mergeInheritedConfig(config) {
|
|
|
55
78
|
logger.debug({ parseResult }, "Error parsing inherited config.");
|
|
56
79
|
throw new Error(CONFIG_INHERIT_PARSE_ERROR);
|
|
57
80
|
}
|
|
81
|
+
const inheritedConfigSource = `Inherited config (\`${config.inheritConfigFileName}\` in \`${inheritConfigRepoName}\`)`;
|
|
58
82
|
const inheritedConfig = parseResult.parsedContents;
|
|
59
83
|
logger.debug({ config: inheritedConfig }, `Inherited config`);
|
|
60
84
|
const res = await validateConfig("inherit", inheritedConfig);
|
|
61
85
|
if (res.errors.length) {
|
|
62
86
|
logger.warn({ errors: res.errors }, "Found errors in inherited configuration.");
|
|
63
|
-
|
|
87
|
+
throwInheritedConfigValidationError(inheritedConfigSource, res.errors);
|
|
64
88
|
}
|
|
65
89
|
if (res.warnings.length) logger.warn({ warnings: res.warnings }, "Found warnings in inherited configuration.");
|
|
66
90
|
if (isNonEmptyArray(inheritedConfig.configFileNames)) {
|
|
@@ -80,7 +104,7 @@ async function mergeInheritedConfig(config) {
|
|
|
80
104
|
secrets: coerceObject(config.secrets),
|
|
81
105
|
variables: coerceObject(config.variables)
|
|
82
106
|
});
|
|
83
|
-
applyHostRules(filteredConfig);
|
|
107
|
+
applyHostRules(filteredConfig, inheritedHostRuleOptions());
|
|
84
108
|
filteredConfig = InheritConfig.set(filteredConfig);
|
|
85
109
|
return mergeChildConfig(config, filteredConfig);
|
|
86
110
|
}
|
|
@@ -90,7 +114,7 @@ async function mergeInheritedConfig(config) {
|
|
|
90
114
|
const validationRes = await validateConfig("inherit", resolvedConfig);
|
|
91
115
|
if (validationRes.errors.length) {
|
|
92
116
|
logger.warn({ errors: validationRes.errors }, "Found errors in presets inside the inherited configuration.");
|
|
93
|
-
|
|
117
|
+
throwInheritedConfigValidationError(inheritedConfigSource, validationRes.errors);
|
|
94
118
|
}
|
|
95
119
|
if (validationRes.warnings.length) logger.warn({ warnings: validationRes.warnings }, "Found warnings in presets inside the inherited configuration.");
|
|
96
120
|
decryptedConfig = await decryptConfig(resolvedConfig, config.repository);
|
|
@@ -104,7 +128,7 @@ async function mergeInheritedConfig(config) {
|
|
|
104
128
|
secrets: coerceObject(config.secrets),
|
|
105
129
|
variables: coerceObject(config.variables)
|
|
106
130
|
});
|
|
107
|
-
applyHostRules(filteredConfig);
|
|
131
|
+
applyHostRules(filteredConfig, inheritedHostRuleOptions());
|
|
108
132
|
filteredConfig = InheritConfig.set(filteredConfig);
|
|
109
133
|
return mergeChildConfig(config, filteredConfig);
|
|
110
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inherited.js","names":["template.compile"],"sources":["../../../../lib/workers/repository/init/inherited.ts"],"sourcesContent":["import { isNonEmptyArray, isNullOrUndefined, isString } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { setUserConfigFileNames } from '../../../config/app-strings.ts';\nimport { decryptConfig } from '../../../config/decrypt.ts';\nimport { mergeChildConfig, removeGlobalConfig } from '../../../config/index.ts';\nimport { InheritConfig } from '../../../config/inherit.ts';\nimport { parseFileConfig } from '../../../config/parse.ts';\nimport { resolveConfigPresets } from '../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../config/secrets.ts';\nimport type { RenovateConfig } from '../../../config/types.ts';\nimport { validateConfig } from '../../../config/validation.ts';\nimport {\n CONFIG_INHERIT_NOT_FOUND,\n CONFIG_INHERIT_PARSE_ERROR,\n CONFIG_VALIDATION,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { platform } from '../../../modules/platform/index.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport * as template from '../../../util/template/index.ts';\nimport { applyHostRules } from './merge.ts';\n\nexport async function mergeInheritedConfig(\n config: RenovateConfig,\n): Promise<RenovateConfig> {\n // typescript doesn't know that repo is defined\n if (!config.repository || !config.inheritConfig) {\n return config;\n }\n if (\n !isString(config.inheritConfigRepoName) ||\n !isString(config.inheritConfigFileName)\n ) {\n // Config validation should prevent this error\n logger.error(\n {\n inheritConfigRepoName: config.inheritConfigRepoName,\n inheritConfigFileName: config.inheritConfigFileName,\n },\n 'Invalid inherited config.',\n );\n return config;\n }\n const templateConfig = {\n topLevelOrg: config.topLevelOrg,\n parentOrg: config.parentOrg,\n repository: config.repository,\n };\n const inheritConfigRepoName = template.compile(\n config.inheritConfigRepoName,\n templateConfig,\n false,\n );\n logger.trace(\n { templateConfig, inheritConfigRepoName },\n 'Compiled inheritConfigRepoName result.',\n );\n logger.debug(\n `Checking for inherited config file ${config.inheritConfigFileName} in repo ${inheritConfigRepoName}.`,\n );\n let configFileRaw: string | null = null;\n try {\n configFileRaw = await platform.getRawFile(\n config.inheritConfigFileName,\n inheritConfigRepoName,\n );\n } catch (err) {\n if (config.inheritConfigStrict) {\n logger.debug({ err }, 'Error getting inherited config.');\n throw new Error(CONFIG_INHERIT_NOT_FOUND);\n }\n logger.trace({ err }, `Error getting inherited config.`);\n }\n if (!configFileRaw) {\n logger.debug(`No inherited config found in ${inheritConfigRepoName}.`);\n return config;\n }\n const parseResult = parseFileConfig(\n config.inheritConfigFileName,\n configFileRaw,\n );\n if (!parseResult.success) {\n logger.debug({ parseResult }, 'Error parsing inherited config.');\n throw new Error(CONFIG_INHERIT_PARSE_ERROR);\n }\n const inheritedConfig = parseResult.parsedContents as RenovateConfig;\n logger.debug({ config: inheritedConfig }, `Inherited config`);\n const res = await validateConfig('inherit', inheritedConfig);\n if (res.errors.length) {\n logger.warn(\n { errors: res.errors },\n 'Found errors in inherited configuration.',\n );\n throw new Error(CONFIG_VALIDATION);\n }\n if (res.warnings.length) {\n logger.warn(\n { warnings: res.warnings },\n 'Found warnings in inherited configuration.',\n );\n }\n\n // set user config file name here\n if (isNonEmptyArray(inheritedConfig.configFileNames)) {\n logger.debug(\n { configFileNames: inheritedConfig.configFileNames },\n 'Updated the config filenames list',\n );\n setUserConfigFileNames(inheritedConfig.configFileNames);\n delete config.configFileNames;\n }\n\n let decryptedConfig = await decryptConfig(inheritedConfig, config.repository);\n\n let filteredConfig = removeGlobalConfig(decryptedConfig, true);\n if (!dequal(decryptedConfig, filteredConfig)) {\n logger.debug(\n { inheritedConfig: decryptedConfig, filteredConfig },\n 'Removed global config from inherited config.',\n );\n }\n\n if (isNullOrUndefined(filteredConfig.extends)) {\n filteredConfig = applySecretsAndVariablesToConfig({\n config: filteredConfig,\n secrets: coerceObject(config.secrets),\n variables: coerceObject(config.variables),\n });\n applyHostRules(filteredConfig);\n filteredConfig = InheritConfig.set(filteredConfig);\n return mergeChildConfig(config, filteredConfig);\n }\n\n logger.debug('Resolving presets found in inherited config');\n const { config: resolvedConfig } = await resolveConfigPresets(\n filteredConfig,\n config,\n config.ignorePresets,\n );\n logger.trace({ config: resolvedConfig }, 'Resolved inherited config');\n\n const validationRes = await validateConfig('inherit', resolvedConfig);\n if (validationRes.errors.length) {\n logger.warn(\n { errors: validationRes.errors },\n 'Found errors in presets inside the inherited configuration.',\n );\n throw new Error(CONFIG_VALIDATION);\n }\n if (validationRes.warnings.length) {\n logger.warn(\n { warnings: validationRes.warnings },\n 'Found warnings in presets inside the inherited configuration.',\n );\n }\n\n // decrypt again, as resolved presets could contain encrypted values\n decryptedConfig = await decryptConfig(resolvedConfig, config.repository);\n\n // remove global config options once again, as resolved presets could have added some\n filteredConfig = removeGlobalConfig(decryptedConfig, true);\n if (!dequal(decryptedConfig, filteredConfig)) {\n logger.debug(\n { inheritedConfig: decryptedConfig, filteredConfig },\n 'Removed global config from inherited config presets.',\n );\n }\n\n filteredConfig = applySecretsAndVariablesToConfig({\n config: filteredConfig,\n secrets: coerceObject(config.secrets),\n variables: coerceObject(config.variables),\n });\n applyHostRules(filteredConfig);\n filteredConfig = InheritConfig.set(filteredConfig);\n return mergeChildConfig(config, filteredConfig);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inherited.js","names":["template.compile"],"sources":["../../../../lib/workers/repository/init/inherited.ts"],"sourcesContent":["import { isNonEmptyArray, isNullOrUndefined, isString } from '@sindresorhus/is';\nimport { dequal } from 'dequal';\nimport { setUserConfigFileNames } from '../../../config/app-strings.ts';\nimport { decryptConfig } from '../../../config/decrypt.ts';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { mergeChildConfig, removeGlobalConfig } from '../../../config/index.ts';\nimport { InheritConfig } from '../../../config/inherit.ts';\nimport { parseFileConfig } from '../../../config/parse.ts';\nimport { resolveConfigPresets } from '../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../config/secrets.ts';\nimport type {\n RenovateConfig,\n ValidationMessage,\n} from '../../../config/types.ts';\nimport { validateConfig } from '../../../config/validation.ts';\nimport {\n CONFIG_INHERIT_NOT_FOUND,\n CONFIG_INHERIT_PARSE_ERROR,\n CONFIG_VALIDATION,\n} from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { platform } from '../../../modules/platform/index.ts';\nimport type { AddHostRuleOptions } from '../../../util/host-rules.ts';\nimport { coerceObject } from '../../../util/object.ts';\nimport * as template from '../../../util/template/index.ts';\nimport { applyHostRules } from './merge.ts';\n\nconst inheritedConfigValidationError =\n 'The inherited config contains some invalid settings';\n\n/**\n * Report an inherited config validation failure against the inherited config, rather than the repository being processed.\n *\n * The inherited config repository is managed by the organization's administrators, so a fault there is not one the repository's owners have introduced - and they may not even be able to read the file to see it.\n */\nfunction throwInheritedConfigValidationError(\n validationSource: string,\n errors: ValidationMessage[],\n): never {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = validationSource;\n error.validationError = inheritedConfigValidationError;\n error.validationMessage = errors.map((err) => err.message).join(', ');\n throw error;\n}\n\n/**\n * How the inherited config's `hostRules` are registered.\n *\n * The inherited config repository is controlled by the organization's administrators rather than by the self-hosted administrator, so its rules are untrusted unless the administrator has opted into trusting them.\n */\nfunction inheritedHostRuleOptions(): AddHostRuleOptions | undefined {\n if (!GlobalConfig.get('inheritConfigTrusted')) {\n return undefined;\n }\n return { inherited: true };\n}\n\nexport async function mergeInheritedConfig(\n config: RenovateConfig,\n): Promise<RenovateConfig> {\n // typescript doesn't know that repo is defined\n if (!config.repository || !config.inheritConfig) {\n return config;\n }\n if (\n !isString(config.inheritConfigRepoName) ||\n !isString(config.inheritConfigFileName)\n ) {\n // Config validation should prevent this error\n logger.error(\n {\n inheritConfigRepoName: config.inheritConfigRepoName,\n inheritConfigFileName: config.inheritConfigFileName,\n },\n 'Invalid inherited config.',\n );\n return config;\n }\n const templateConfig = {\n topLevelOrg: config.topLevelOrg,\n parentOrg: config.parentOrg,\n repository: config.repository,\n };\n const inheritConfigRepoName = template.compile(\n config.inheritConfigRepoName,\n templateConfig,\n false,\n );\n logger.trace(\n { templateConfig, inheritConfigRepoName },\n 'Compiled inheritConfigRepoName result.',\n );\n logger.debug(\n `Checking for inherited config file ${config.inheritConfigFileName} in repo ${inheritConfigRepoName}.`,\n );\n let configFileRaw: string | null = null;\n try {\n configFileRaw = await platform.getRawFile(\n config.inheritConfigFileName,\n inheritConfigRepoName,\n );\n } catch (err) {\n if (config.inheritConfigStrict) {\n logger.debug({ err }, 'Error getting inherited config.');\n throw new Error(CONFIG_INHERIT_NOT_FOUND);\n }\n logger.trace({ err }, `Error getting inherited config.`);\n }\n if (!configFileRaw) {\n logger.debug(`No inherited config found in ${inheritConfigRepoName}.`);\n return config;\n }\n const parseResult = parseFileConfig(\n config.inheritConfigFileName,\n configFileRaw,\n );\n if (!parseResult.success) {\n logger.debug({ parseResult }, 'Error parsing inherited config.');\n throw new Error(CONFIG_INHERIT_PARSE_ERROR);\n }\n const inheritedConfigSource = `Inherited config (\\`${config.inheritConfigFileName}\\` in \\`${inheritConfigRepoName}\\`)`;\n const inheritedConfig = parseResult.parsedContents as RenovateConfig;\n logger.debug({ config: inheritedConfig }, `Inherited config`);\n const res = await validateConfig('inherit', inheritedConfig);\n if (res.errors.length) {\n logger.warn(\n { errors: res.errors },\n 'Found errors in inherited configuration.',\n );\n throwInheritedConfigValidationError(inheritedConfigSource, res.errors);\n }\n if (res.warnings.length) {\n logger.warn(\n { warnings: res.warnings },\n 'Found warnings in inherited configuration.',\n );\n }\n\n // set user config file name here\n if (isNonEmptyArray(inheritedConfig.configFileNames)) {\n logger.debug(\n { configFileNames: inheritedConfig.configFileNames },\n 'Updated the config filenames list',\n );\n setUserConfigFileNames(inheritedConfig.configFileNames);\n delete config.configFileNames;\n }\n\n let decryptedConfig = await decryptConfig(inheritedConfig, config.repository);\n\n let filteredConfig = removeGlobalConfig(decryptedConfig, true);\n if (!dequal(decryptedConfig, filteredConfig)) {\n logger.debug(\n { inheritedConfig: decryptedConfig, filteredConfig },\n 'Removed global config from inherited config.',\n );\n }\n\n if (isNullOrUndefined(filteredConfig.extends)) {\n filteredConfig = applySecretsAndVariablesToConfig({\n config: filteredConfig,\n secrets: coerceObject(config.secrets),\n variables: coerceObject(config.variables),\n });\n applyHostRules(filteredConfig, inheritedHostRuleOptions());\n filteredConfig = InheritConfig.set(filteredConfig);\n return mergeChildConfig(config, filteredConfig);\n }\n\n logger.debug('Resolving presets found in inherited config');\n const { config: resolvedConfig } = await resolveConfigPresets(\n filteredConfig,\n config,\n config.ignorePresets,\n );\n logger.trace({ config: resolvedConfig }, 'Resolved inherited config');\n\n const validationRes = await validateConfig('inherit', resolvedConfig);\n if (validationRes.errors.length) {\n logger.warn(\n { errors: validationRes.errors },\n 'Found errors in presets inside the inherited configuration.',\n );\n throwInheritedConfigValidationError(\n inheritedConfigSource,\n validationRes.errors,\n );\n }\n if (validationRes.warnings.length) {\n logger.warn(\n { warnings: validationRes.warnings },\n 'Found warnings in presets inside the inherited configuration.',\n );\n }\n\n // decrypt again, as resolved presets could contain encrypted values\n decryptedConfig = await decryptConfig(resolvedConfig, config.repository);\n\n // remove global config options once again, as resolved presets could have added some\n filteredConfig = removeGlobalConfig(decryptedConfig, true);\n if (!dequal(decryptedConfig, filteredConfig)) {\n logger.debug(\n { inheritedConfig: decryptedConfig, filteredConfig },\n 'Removed global config from inherited config presets.',\n );\n }\n\n filteredConfig = applySecretsAndVariablesToConfig({\n config: filteredConfig,\n secrets: coerceObject(config.secrets),\n variables: coerceObject(config.variables),\n });\n applyHostRules(filteredConfig, inheritedHostRuleOptions());\n filteredConfig = InheritConfig.set(filteredConfig);\n return mergeChildConfig(config, filteredConfig);\n}\n"],"mappings":"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"}
|