renovate 43.231.4 → 43.232.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.
@@ -108,7 +108,7 @@ async function decryptConfig(config, repository, existingPath = "$") {
108
108
  if (env.MEND_HOSTED === "true") error.validationMessage = `Mend-hosted Renovate Apps no longer support the use of encrypted secrets in Renovate file config (e.g. renovate.json).
109
109
  Please migrate all secrets to the Developer Portal using the web UI available at https://developer.mend.io/
110
110
 
111
- Refer to migration documents here: https://docs.renovatebot.com/mend-hosted/migrating-secrets/`;
111
+ Refer to migration documents here: ${GlobalConfig.get("productLinks").documentation}mend-hosted/migrating-secrets/`;
112
112
  throw error;
113
113
  } else logger.error("Found encrypted data but no privateKey");
114
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decrypt.js","names":[],"sources":["../../lib/config/decrypt.ts"],"sourcesContent":["import {\n isArray,\n isNonEmptyString,\n isObject,\n isString,\n} from '@sindresorhus/is';\nimport { CONFIG_VALIDATION } from '../constants/error-messages.ts';\nimport { logger } from '../logger/index.ts';\nimport { getEnv } from '../util/env.ts';\nimport { regEx } from '../util/regex.ts';\nimport { addSecretForSanitizing } from '../util/sanitize.ts';\nimport { ensureTrailingSlash, parseUrl, trimSlashes } from '../util/url.ts';\nimport { tryDecryptBcPgp } from './decrypt/bcpgp.ts';\nimport { tryDecryptOpenPgp } from './decrypt/openpgp.ts';\nimport { GlobalConfig } from './global.ts';\nimport { DecryptedObject } from './schema.ts';\nimport type { AllConfig, RenovateConfig } from './types.ts';\n\nlet privateKey: string | undefined;\nlet privateKeyOld: string | undefined;\n\nexport function setPrivateKeys(\n pKey: string | undefined,\n pKeyOld: string | undefined,\n): void {\n privateKey = pKey;\n privateKeyOld = pKeyOld;\n}\n\nexport async function tryDecrypt(\n key: string,\n encryptedStr: string,\n repository: string,\n): Promise<string | null> {\n let decryptedStr: string | null = null;\n const decryptedObjStr =\n getEnv().RENOVATE_X_USE_OPENPGP === 'true'\n ? await tryDecryptOpenPgp(key, encryptedStr)\n : await tryDecryptBcPgp(key, encryptedStr);\n if (decryptedObjStr) {\n decryptedStr = validateDecryptedValue(decryptedObjStr, repository);\n }\n return decryptedStr;\n}\n\nexport function validateDecryptedValue(\n decryptedObjStr: string,\n repository: string,\n): string | null {\n try {\n const decryptedObj = DecryptedObject.safeParse(decryptedObjStr);\n if (!decryptedObj.success) {\n const error = new Error('config-validation');\n error.validationError = `Could not parse decrypted config.`;\n throw error;\n }\n\n const { o: org, r: repo, v: value } = decryptedObj.data;\n\n if (!isNonEmptyString(value)) {\n const error = new Error('config-validation');\n error.validationError = `Encrypted value in config is missing a value.`;\n throw error;\n }\n\n if (!isNonEmptyString(org)) {\n const error = new Error('config-validation');\n error.validationError = `Encrypted value in config is missing a scope.`;\n throw error;\n }\n\n const repositories = [repository.toUpperCase()];\n\n const azureCollection = getAzureCollection();\n if (isNonEmptyString(azureCollection)) {\n // used for full 'org/project/repo' matching\n repositories.push(`${azureCollection}/${repository}`.toUpperCase());\n // used for org prefix matching without repo\n repositories.push(`${azureCollection}/*/`.toUpperCase());\n }\n\n const orgPrefixes = org\n .split(',')\n .map((o) => o.trim())\n .map((o) => o.toUpperCase())\n .map((o) => ensureTrailingSlash(o));\n\n if (isNonEmptyString(repo)) {\n const scopedRepos = orgPrefixes.map((orgPrefix) =>\n `${orgPrefix}${repo}`.toUpperCase(),\n );\n for (const rp of repositories) {\n if (scopedRepos.some((r) => r === rp)) {\n return value;\n }\n }\n\n logger.debug(\n { scopedRepos },\n 'Secret is scoped to a different repository',\n );\n const error = new Error('config-validation');\n const scopeString = scopedRepos.join(',');\n error.validationError = `Encrypted secret is scoped to a different repository: \"${scopeString}\".`;\n throw error;\n }\n\n // no scoped repos, only org\n const azcol =\n azureCollection === undefined\n ? undefined\n : ensureTrailingSlash(azureCollection).toUpperCase();\n for (const rp of repositories) {\n if (\n orgPrefixes.some(\n (orgPrefix) => rp.startsWith(orgPrefix) && orgPrefix !== azcol,\n )\n ) {\n return value;\n }\n }\n logger.debug({ orgPrefixes }, 'Secret is scoped to a different org');\n const error = new Error('config-validation');\n const scopeString = orgPrefixes.join(',');\n error.validationError = `Encrypted secret is scoped to a different org: \"${scopeString}\".`;\n throw error;\n } catch (err) {\n logger.warn({ err }, 'Could not parse decrypted string');\n }\n return null;\n}\n\nexport async function decryptConfig<T extends RenovateConfig = AllConfig>(\n config: T,\n repository: string,\n existingPath = '$',\n): Promise<T> {\n logger.trace({ config }, 'decryptConfig()');\n const decryptedConfig = { ...config };\n for (const [key, val] of Object.entries(config)) {\n if (key === 'encrypted' && isObject(val)) {\n const path = `${existingPath}.${key}`;\n logger.debug({ config: val }, `Found encrypted config in ${path}`);\n\n const encryptedWarning = GlobalConfig.get('encryptedWarning');\n if (isString(encryptedWarning)) {\n logger.once.warn(encryptedWarning);\n }\n\n if (privateKey) {\n for (const [eKey, eVal] of Object.entries(val)) {\n logger.debug(`Trying to decrypt ${eKey} in ${path}`);\n let decryptedStr = await tryDecrypt(privateKey, eVal, repository);\n if (privateKeyOld && !isNonEmptyString(decryptedStr)) {\n logger.debug(`Trying to decrypt with old private key`);\n decryptedStr = await tryDecrypt(privateKeyOld, eVal, repository);\n }\n if (!isNonEmptyString(decryptedStr)) {\n const error = new Error('config-validation');\n error.validationError = `Failed to decrypt field ${eKey}. Please re-encrypt and try again.`;\n throw error;\n }\n logger.debug(`Decrypted ${eKey} in ${path}`);\n // v8 ignore if -- TODO: add test #40625\n if (eKey === 'npmToken') {\n const token = decryptedStr.replace(regEx(/\\n$/), '');\n decryptedConfig[eKey] = token;\n addSecretForSanitizing(token);\n } else {\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[eKey] = decryptedStr;\n addSecretForSanitizing(decryptedStr);\n }\n }\n } else {\n const env = getEnv();\n if (env.RENOVATE_X_ENCRYPTED_STRICT === 'true') {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = 'config';\n error.validationError = 'Encrypted config unsupported';\n error.validationMessage = `This config contains an encrypted object at location \\`$.${key}\\` but no privateKey is configured. To support encrypted config, the Renovate administrator must configure a \\`privateKey\\` in Global Configuration.`;\n if (env.MEND_HOSTED === 'true') {\n // oxlint-disable-next-line renovate/no-hardcoded-docs-url -- no config access during decryption\n error.validationMessage = `Mend-hosted Renovate Apps no longer support the use of encrypted secrets in Renovate file config (e.g. renovate.json).\nPlease migrate all secrets to the Developer Portal using the web UI available at https://developer.mend.io/\n\nRefer to migration documents here: https://docs.renovatebot.com/mend-hosted/migrating-secrets/`;\n }\n throw error;\n } else {\n logger.error('Found encrypted data but no privateKey');\n }\n }\n delete decryptedConfig.encrypted;\n } else if (isArray(val)) {\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[key] = [];\n for (const [index, item] of val.entries()) {\n if (isObject(item) && !isArray(item)) {\n const path = `${existingPath}.${key}[${index}]`;\n // @ts-expect-error -- type can't be narrowed\n (decryptedConfig[key] as RenovateConfig[]).push(\n await decryptConfig(item as RenovateConfig, repository, path),\n );\n } else {\n // @ts-expect-error -- type can't be narrowed\n (decryptedConfig[key] as unknown[]).push(item);\n }\n }\n } else if (isObject(val) && key !== 'content') {\n const path = `${existingPath}.${key}`;\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[key] = await decryptConfig(\n val as RenovateConfig,\n repository,\n path,\n );\n }\n }\n delete decryptedConfig.encrypted;\n logger.trace({ config: decryptedConfig }, 'decryptedConfig');\n return decryptedConfig;\n}\n\nexport function getAzureCollection(): string | undefined {\n const platform = GlobalConfig.get('platform');\n if (platform !== 'azure') {\n return undefined;\n }\n\n const endpoint = GlobalConfig.get('endpoint');\n const endpointUrl = parseUrl(endpoint);\n if (endpointUrl === null) {\n // should not happen\n logger.warn({ endpoint }, 'Unable to parse endpoint for token decryption');\n return undefined;\n }\n\n const azureCollection = trimSlashes(endpointUrl.pathname);\n if (!isNonEmptyString(azureCollection)) {\n logger.debug({ endpoint }, 'Unable to find azure collection name from URL');\n return undefined;\n }\n\n if (azureCollection.startsWith('tfs/')) {\n // Azure DevOps Server\n return azureCollection.substring(4);\n }\n return azureCollection;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"decrypt.js","names":[],"sources":["../../lib/config/decrypt.ts"],"sourcesContent":["import {\n isArray,\n isNonEmptyString,\n isObject,\n isString,\n} from '@sindresorhus/is';\nimport { CONFIG_VALIDATION } from '../constants/error-messages.ts';\nimport { logger } from '../logger/index.ts';\nimport { getEnv } from '../util/env.ts';\nimport { regEx } from '../util/regex.ts';\nimport { addSecretForSanitizing } from '../util/sanitize.ts';\nimport { ensureTrailingSlash, parseUrl, trimSlashes } from '../util/url.ts';\nimport { tryDecryptBcPgp } from './decrypt/bcpgp.ts';\nimport { tryDecryptOpenPgp } from './decrypt/openpgp.ts';\nimport { GlobalConfig } from './global.ts';\nimport { DecryptedObject } from './schema.ts';\nimport type { AllConfig, RenovateConfig } from './types.ts';\n\nlet privateKey: string | undefined;\nlet privateKeyOld: string | undefined;\n\nexport function setPrivateKeys(\n pKey: string | undefined,\n pKeyOld: string | undefined,\n): void {\n privateKey = pKey;\n privateKeyOld = pKeyOld;\n}\n\nexport async function tryDecrypt(\n key: string,\n encryptedStr: string,\n repository: string,\n): Promise<string | null> {\n let decryptedStr: string | null = null;\n const decryptedObjStr =\n getEnv().RENOVATE_X_USE_OPENPGP === 'true'\n ? await tryDecryptOpenPgp(key, encryptedStr)\n : await tryDecryptBcPgp(key, encryptedStr);\n if (decryptedObjStr) {\n decryptedStr = validateDecryptedValue(decryptedObjStr, repository);\n }\n return decryptedStr;\n}\n\nexport function validateDecryptedValue(\n decryptedObjStr: string,\n repository: string,\n): string | null {\n try {\n const decryptedObj = DecryptedObject.safeParse(decryptedObjStr);\n if (!decryptedObj.success) {\n const error = new Error('config-validation');\n error.validationError = `Could not parse decrypted config.`;\n throw error;\n }\n\n const { o: org, r: repo, v: value } = decryptedObj.data;\n\n if (!isNonEmptyString(value)) {\n const error = new Error('config-validation');\n error.validationError = `Encrypted value in config is missing a value.`;\n throw error;\n }\n\n if (!isNonEmptyString(org)) {\n const error = new Error('config-validation');\n error.validationError = `Encrypted value in config is missing a scope.`;\n throw error;\n }\n\n const repositories = [repository.toUpperCase()];\n\n const azureCollection = getAzureCollection();\n if (isNonEmptyString(azureCollection)) {\n // used for full 'org/project/repo' matching\n repositories.push(`${azureCollection}/${repository}`.toUpperCase());\n // used for org prefix matching without repo\n repositories.push(`${azureCollection}/*/`.toUpperCase());\n }\n\n const orgPrefixes = org\n .split(',')\n .map((o) => o.trim())\n .map((o) => o.toUpperCase())\n .map((o) => ensureTrailingSlash(o));\n\n if (isNonEmptyString(repo)) {\n const scopedRepos = orgPrefixes.map((orgPrefix) =>\n `${orgPrefix}${repo}`.toUpperCase(),\n );\n for (const rp of repositories) {\n if (scopedRepos.some((r) => r === rp)) {\n return value;\n }\n }\n\n logger.debug(\n { scopedRepos },\n 'Secret is scoped to a different repository',\n );\n const error = new Error('config-validation');\n const scopeString = scopedRepos.join(',');\n error.validationError = `Encrypted secret is scoped to a different repository: \"${scopeString}\".`;\n throw error;\n }\n\n // no scoped repos, only org\n const azcol =\n azureCollection === undefined\n ? undefined\n : ensureTrailingSlash(azureCollection).toUpperCase();\n for (const rp of repositories) {\n if (\n orgPrefixes.some(\n (orgPrefix) => rp.startsWith(orgPrefix) && orgPrefix !== azcol,\n )\n ) {\n return value;\n }\n }\n logger.debug({ orgPrefixes }, 'Secret is scoped to a different org');\n const error = new Error('config-validation');\n const scopeString = orgPrefixes.join(',');\n error.validationError = `Encrypted secret is scoped to a different org: \"${scopeString}\".`;\n throw error;\n } catch (err) {\n logger.warn({ err }, 'Could not parse decrypted string');\n }\n return null;\n}\n\nexport async function decryptConfig<T extends RenovateConfig = AllConfig>(\n config: T,\n repository: string,\n existingPath = '$',\n): Promise<T> {\n logger.trace({ config }, 'decryptConfig()');\n const decryptedConfig = { ...config };\n for (const [key, val] of Object.entries(config)) {\n if (key === 'encrypted' && isObject(val)) {\n const path = `${existingPath}.${key}`;\n logger.debug({ config: val }, `Found encrypted config in ${path}`);\n\n const encryptedWarning = GlobalConfig.get('encryptedWarning');\n if (isString(encryptedWarning)) {\n logger.once.warn(encryptedWarning);\n }\n\n if (privateKey) {\n for (const [eKey, eVal] of Object.entries(val)) {\n logger.debug(`Trying to decrypt ${eKey} in ${path}`);\n let decryptedStr = await tryDecrypt(privateKey, eVal, repository);\n if (privateKeyOld && !isNonEmptyString(decryptedStr)) {\n logger.debug(`Trying to decrypt with old private key`);\n decryptedStr = await tryDecrypt(privateKeyOld, eVal, repository);\n }\n if (!isNonEmptyString(decryptedStr)) {\n const error = new Error('config-validation');\n error.validationError = `Failed to decrypt field ${eKey}. Please re-encrypt and try again.`;\n throw error;\n }\n logger.debug(`Decrypted ${eKey} in ${path}`);\n // v8 ignore if -- TODO: add test #40625\n if (eKey === 'npmToken') {\n const token = decryptedStr.replace(regEx(/\\n$/), '');\n decryptedConfig[eKey] = token;\n addSecretForSanitizing(token);\n } else {\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[eKey] = decryptedStr;\n addSecretForSanitizing(decryptedStr);\n }\n }\n } else {\n const env = getEnv();\n if (env.RENOVATE_X_ENCRYPTED_STRICT === 'true') {\n const error = new Error(CONFIG_VALIDATION);\n error.validationSource = 'config';\n error.validationError = 'Encrypted config unsupported';\n error.validationMessage = `This config contains an encrypted object at location \\`$.${key}\\` but no privateKey is configured. To support encrypted config, the Renovate administrator must configure a \\`privateKey\\` in Global Configuration.`;\n if (env.MEND_HOSTED === 'true') {\n error.validationMessage = `Mend-hosted Renovate Apps no longer support the use of encrypted secrets in Renovate file config (e.g. renovate.json).\nPlease migrate all secrets to the Developer Portal using the web UI available at https://developer.mend.io/\n\nRefer to migration documents here: ${GlobalConfig.get('productLinks').documentation}mend-hosted/migrating-secrets/`;\n }\n throw error;\n } else {\n logger.error('Found encrypted data but no privateKey');\n }\n }\n delete decryptedConfig.encrypted;\n } else if (isArray(val)) {\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[key] = [];\n for (const [index, item] of val.entries()) {\n if (isObject(item) && !isArray(item)) {\n const path = `${existingPath}.${key}[${index}]`;\n // @ts-expect-error -- type can't be narrowed\n (decryptedConfig[key] as RenovateConfig[]).push(\n await decryptConfig(item as RenovateConfig, repository, path),\n );\n } else {\n // @ts-expect-error -- type can't be narrowed\n (decryptedConfig[key] as unknown[]).push(item);\n }\n }\n } else if (isObject(val) && key !== 'content') {\n const path = `${existingPath}.${key}`;\n // @ts-expect-error -- type can't be narrowed\n decryptedConfig[key] = await decryptConfig(\n val as RenovateConfig,\n repository,\n path,\n );\n }\n }\n delete decryptedConfig.encrypted;\n logger.trace({ config: decryptedConfig }, 'decryptedConfig');\n return decryptedConfig;\n}\n\nexport function getAzureCollection(): string | undefined {\n const platform = GlobalConfig.get('platform');\n if (platform !== 'azure') {\n return undefined;\n }\n\n const endpoint = GlobalConfig.get('endpoint');\n const endpointUrl = parseUrl(endpoint);\n if (endpointUrl === null) {\n // should not happen\n logger.warn({ endpoint }, 'Unable to parse endpoint for token decryption');\n return undefined;\n }\n\n const azureCollection = trimSlashes(endpointUrl.pathname);\n if (!isNonEmptyString(azureCollection)) {\n logger.debug({ endpoint }, 'Unable to find azure collection name from URL');\n return undefined;\n }\n\n if (azureCollection.startsWith('tfs/')) {\n // Azure DevOps Server\n return azureCollection.substring(4);\n }\n return azureCollection;\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,IAAI;AACJ,IAAI;AAEJ,SAAgB,eACd,MACA,SACM;CACN,aAAa;CACb,gBAAgB;AAClB;AAEA,eAAsB,WACpB,KACA,cACA,YACwB;CACxB,IAAI,eAA8B;CAClC,MAAM,kBACJ,OAAO,CAAC,CAAC,2BAA2B,SAChC,MAAM,kBAAkB,KAAK,YAAY,IACzC,MAAM,gBAAgB,KAAK,YAAY;CAC7C,IAAI,iBACF,eAAe,uBAAuB,iBAAiB,UAAU;CAEnE,OAAO;AACT;AAEA,SAAgB,uBACd,iBACA,YACe;CACf,IAAI;EACF,MAAM,eAAe,gBAAgB,UAAU,eAAe;EAC9D,IAAI,CAAC,aAAa,SAAS;GACzB,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;GAC3C,MAAM,kBAAkB;GACxB,MAAM;EACR;EAEA,MAAM,EAAE,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,aAAa;EAEnD,IAAI,CAAC,iBAAiB,KAAK,GAAG;GAC5B,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;GAC3C,MAAM,kBAAkB;GACxB,MAAM;EACR;EAEA,IAAI,CAAC,iBAAiB,GAAG,GAAG;GAC1B,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;GAC3C,MAAM,kBAAkB;GACxB,MAAM;EACR;EAEA,MAAM,eAAe,CAAC,WAAW,YAAY,CAAC;EAE9C,MAAM,kBAAkB,mBAAmB;EAC3C,IAAI,iBAAiB,eAAe,GAAG;GAErC,aAAa,KAAK,GAAG,gBAAgB,GAAG,aAAa,YAAY,CAAC;GAElE,aAAa,KAAK,GAAG,gBAAgB,KAAK,YAAY,CAAC;EACzD;EAEA,MAAM,cAAc,IACjB,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC,CAC3B,KAAK,MAAM,oBAAoB,CAAC,CAAC;EAEpC,IAAI,iBAAiB,IAAI,GAAG;GAC1B,MAAM,cAAc,YAAY,KAAK,cACnC,GAAG,YAAY,OAAO,YAAY,CACpC;GACA,KAAK,MAAM,MAAM,cACf,IAAI,YAAY,MAAM,MAAM,MAAM,EAAE,GAClC,OAAO;GAIX,OAAO,MACL,EAAE,YAAY,GACd,4CACF;GACA,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;GAE3C,MAAM,kBAAkB,0DADJ,YAAY,KAAK,GACuD,EAAE;GAC9F,MAAM;EACR;EAGA,MAAM,QACJ,oBAAoB,KAAA,IAChB,KAAA,IACA,oBAAoB,eAAe,CAAC,CAAC,YAAY;EACvD,KAAK,MAAM,MAAM,cACf,IACE,YAAY,MACT,cAAc,GAAG,WAAW,SAAS,KAAK,cAAc,KAC3D,GAEA,OAAO;EAGX,OAAO,MAAM,EAAE,YAAY,GAAG,qCAAqC;EACnE,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;EAE3C,MAAM,kBAAkB,mDADJ,YAAY,KAAK,GACgD,EAAE;EACvF,MAAM;CACR,SAAS,KAAK;EACZ,OAAO,KAAK,EAAE,IAAI,GAAG,kCAAkC;CACzD;CACA,OAAO;AACT;AAEA,eAAsB,cACpB,QACA,YACA,eAAe,KACH;CACZ,OAAO,MAAM,EAAE,OAAO,GAAG,iBAAiB;CAC1C,MAAM,kBAAkB,EAAE,GAAG,OAAO;CACpC,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,MAAM,GAC5C,IAAI,QAAQ,eAAe,SAAS,GAAG,GAAG;EACxC,MAAM,OAAO,GAAG,aAAa,GAAG;EAChC,OAAO,MAAM,EAAE,QAAQ,IAAI,GAAG,6BAA6B,MAAM;EAEjE,MAAM,mBAAmB,aAAa,IAAI,kBAAkB;EAC5D,IAAI,SAAS,gBAAgB,GAC3B,OAAO,KAAK,KAAK,gBAAgB;EAGnC,IAAI,YACF,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,GAAG,GAAG;GAC9C,OAAO,MAAM,qBAAqB,KAAK,MAAM,MAAM;GACnD,IAAI,eAAe,MAAM,WAAW,YAAY,MAAM,UAAU;GAChE,IAAI,iBAAiB,CAAC,iBAAiB,YAAY,GAAG;IACpD,OAAO,MAAM,wCAAwC;IACrD,eAAe,MAAM,WAAW,eAAe,MAAM,UAAU;GACjE;GACA,IAAI,CAAC,iBAAiB,YAAY,GAAG;IACnC,MAAM,wBAAQ,IAAI,MAAM,mBAAmB;IAC3C,MAAM,kBAAkB,2BAA2B,KAAK;IACxD,MAAM;GACR;GACA,OAAO,MAAM,aAAa,KAAK,MAAM,MAAM;;GAE3C,IAAI,SAAS,YAAY;IACvB,MAAM,QAAQ,aAAa,QAAQ,MAAM,KAAK,GAAG,EAAE;IACnD,gBAAgB,QAAQ;IACxB,uBAAuB,KAAK;GAC9B,OAAO;IAEL,gBAAgB,QAAQ;IACxB,uBAAuB,YAAY;GACrC;EACF;OACK;GACL,MAAM,MAAM,OAAO;GACnB,IAAI,IAAI,gCAAgC,QAAQ;IAC9C,MAAM,QAAQ,IAAI,MAAM,iBAAiB;IACzC,MAAM,mBAAmB;IACzB,MAAM,kBAAkB;IACxB,MAAM,oBAAoB,4DAA4D,IAAI;IAC1F,IAAI,IAAI,gBAAgB,QACtB,MAAM,oBAAoB;;;qCAGD,aAAa,IAAI,cAAc,CAAC,CAAC,cAAc;IAE1E,MAAM;GACR,OACE,OAAO,MAAM,wCAAwC;EAEzD;EACA,OAAO,gBAAgB;CACzB,OAAO,IAAI,QAAQ,GAAG,GAAG;EAEvB,gBAAgB,OAAO,CAAC;EACxB,KAAK,MAAM,CAAC,OAAO,SAAS,IAAI,QAAQ,GACtC,IAAI,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG;GACpC,MAAM,OAAO,GAAG,aAAa,GAAG,IAAI,GAAG,MAAM;GAE7C,gBAAiB,IAAI,CAAsB,KACzC,MAAM,cAAc,MAAwB,YAAY,IAAI,CAC9D;EACF,OAEE,gBAAiB,IAAI,CAAe,KAAK,IAAI;CAGnD,OAAO,IAAI,SAAS,GAAG,KAAK,QAAQ,WAGlC,gBAAgB,OAAO,MAAM,cAC3B,KACA,YACA,GALc,aAAa,GAAG,KAMhC;CAGJ,OAAO,gBAAgB;CACvB,OAAO,MAAM,EAAE,QAAQ,gBAAgB,GAAG,iBAAiB;CAC3D,OAAO;AACT;AAEA,SAAgB,qBAAyC;CAEvD,IADiB,aAAa,IAAI,UACvB,MAAM,SACf;CAGF,MAAM,WAAW,aAAa,IAAI,UAAU;CAC5C,MAAM,cAAc,SAAS,QAAQ;CACrC,IAAI,gBAAgB,MAAM;EAExB,OAAO,KAAK,EAAE,SAAS,GAAG,+CAA+C;EACzE;CACF;CAEA,MAAM,kBAAkB,YAAY,YAAY,QAAQ;CACxD,IAAI,CAAC,iBAAiB,eAAe,GAAG;EACtC,OAAO,MAAM,EAAE,SAAS,GAAG,+CAA+C;EAC1E;CACF;CAEA,IAAI,gBAAgB,WAAW,MAAM,GAEnC,OAAO,gBAAgB,UAAU,CAAC;CAEpC,OAAO;AACT"}
@@ -49,6 +49,7 @@ var GlobalConfig = class GlobalConfig {
49
49
  "platform",
50
50
  "prCacheSyncMaxPages",
51
51
  "presetCachePersistence",
52
+ "productLinks",
52
53
  "repositoryCacheForceLocal",
53
54
  "requireConfig",
54
55
  "s3Endpoint",
@@ -1 +1 @@
1
- {"version":3,"file":"global.js","names":[],"sources":["../../lib/config/global.ts"],"sourcesContent":["import { globalConfigOptionDefaults } from '../global-config-option-defaults.generated.ts';\nimport type { RenovateConfig, RepoGlobalConfig } from './types.ts';\n\nexport class GlobalConfig {\n // TODO: once global config work is complete, add a test to make sure this list includes all options with globalOnly=true (#9603)\n static OPTIONS: readonly (keyof RepoGlobalConfig)[] = [\n 'allowCustomCrateRegistries',\n 'allowPlugins',\n 'allowScripts',\n 'allowShellExecutorForPostUpgradeCommands',\n 'allowedCommands',\n 'allowedEnv',\n 'allowedHeaders',\n 'allowedUnsafeExecutions',\n 'autodiscoverRepoOrder',\n 'autodiscoverRepoSort',\n 'bbUseDevelopmentBranch',\n 'binarySource',\n 'cacheDir',\n 'cacheHardTtlMinutes',\n 'cachePrivatePackages',\n 'cacheTtlOverride',\n 'configFileNames',\n 'containerbaseDir',\n 'customEnvVariables',\n 'dockerChildPrefix',\n 'dockerCliOptions',\n 'dockerMaxPages',\n 'dockerSidecarImage',\n 'dockerUser',\n 'dryRun',\n 'encryptedWarning',\n 'endpoint',\n 'executionTimeout',\n 'exposeAllEnv',\n 'gitTimeout',\n 'githubTokenWarn',\n 'httpCacheTtlDays',\n 'ignorePrAuthor',\n 'includeMirrors',\n 'localDir',\n 'migratePresets',\n 'onboarding',\n 'onboardingAutoCloseAge',\n 'onboardingBranch',\n 'onboardingCommitMessage',\n 'onboardingConfig',\n 'onboardingConfigFileName',\n 'onboardingNoDeps',\n 'onboardingPrTitle',\n 'platform',\n 'prCacheSyncMaxPages',\n 'presetCachePersistence',\n 'repositoryCacheForceLocal',\n 'requireConfig',\n 's3Endpoint',\n 's3PathStyle',\n 'toolSettings',\n 'userAgent',\n ];\n\n private static config: RepoGlobalConfig = {};\n\n static get(): RepoGlobalConfig;\n static get<Key extends keyof RepoGlobalConfig>(\n key: Key,\n ): Required<RepoGlobalConfig>[Key];\n static get<Key extends keyof RepoGlobalConfig>(\n key: Key,\n ): Required<RepoGlobalConfig>[Key];\n static get<Key extends keyof RepoGlobalConfig>(\n key?: Key,\n ): RepoGlobalConfig | Required<RepoGlobalConfig>[Key] {\n const defaultValue = key\n ? (globalConfigOptionDefaults[key] as Required<RepoGlobalConfig>[Key])\n : undefined;\n\n return key\n ? ((GlobalConfig.config[key] ??\n defaultValue) as Required<RepoGlobalConfig>[Key])\n : GlobalConfig.config;\n }\n\n static set(config: RenovateConfig & RepoGlobalConfig): RenovateConfig {\n GlobalConfig.reset();\n\n const result = { ...config };\n for (const option of GlobalConfig.OPTIONS) {\n GlobalConfig.config[option] = config[option] as never;\n delete result[option];\n }\n\n return result;\n }\n\n static reset(): void {\n GlobalConfig.config = {};\n }\n}\n"],"mappings":";;AAGA,IAAa,eAAb,MAAa,aAAa;CAExB,OAAO,UAA+C;EACpD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,OAAe,SAA2B,CAAC;CAS3C,OAAO,IACL,KACoD;EACpD,MAAM,eAAe,MAChB,2BAA2B,OAC5B,KAAA;EAEJ,OAAO,MACD,aAAa,OAAO,QACpB,eACF,aAAa;CACnB;CAEA,OAAO,IAAI,QAA2D;EACpE,aAAa,MAAM;EAEnB,MAAM,SAAS,EAAE,GAAG,OAAO;EAC3B,KAAK,MAAM,UAAU,aAAa,SAAS;GACzC,aAAa,OAAO,UAAU,OAAO;GACrC,OAAO,OAAO;EAChB;EAEA,OAAO;CACT;CAEA,OAAO,QAAc;EACnB,aAAa,SAAS,CAAC;CACzB;AACF"}
1
+ {"version":3,"file":"global.js","names":[],"sources":["../../lib/config/global.ts"],"sourcesContent":["import { globalConfigOptionDefaults } from '../global-config-option-defaults.generated.ts';\nimport type { RenovateConfig, RepoGlobalConfig } from './types.ts';\n\nexport class GlobalConfig {\n // TODO: once global config work is complete, add a test to make sure this list includes all options with globalOnly=true (#9603)\n static OPTIONS: readonly (keyof RepoGlobalConfig)[] = [\n 'allowCustomCrateRegistries',\n 'allowPlugins',\n 'allowScripts',\n 'allowShellExecutorForPostUpgradeCommands',\n 'allowedCommands',\n 'allowedEnv',\n 'allowedHeaders',\n 'allowedUnsafeExecutions',\n 'autodiscoverRepoOrder',\n 'autodiscoverRepoSort',\n 'bbUseDevelopmentBranch',\n 'binarySource',\n 'cacheDir',\n 'cacheHardTtlMinutes',\n 'cachePrivatePackages',\n 'cacheTtlOverride',\n 'configFileNames',\n 'containerbaseDir',\n 'customEnvVariables',\n 'dockerChildPrefix',\n 'dockerCliOptions',\n 'dockerMaxPages',\n 'dockerSidecarImage',\n 'dockerUser',\n 'dryRun',\n 'encryptedWarning',\n 'endpoint',\n 'executionTimeout',\n 'exposeAllEnv',\n 'gitTimeout',\n 'githubTokenWarn',\n 'httpCacheTtlDays',\n 'ignorePrAuthor',\n 'includeMirrors',\n 'localDir',\n 'migratePresets',\n 'onboarding',\n 'onboardingAutoCloseAge',\n 'onboardingBranch',\n 'onboardingCommitMessage',\n 'onboardingConfig',\n 'onboardingConfigFileName',\n 'onboardingNoDeps',\n 'onboardingPrTitle',\n 'platform',\n 'prCacheSyncMaxPages',\n 'presetCachePersistence',\n 'productLinks',\n 'repositoryCacheForceLocal',\n 'requireConfig',\n 's3Endpoint',\n 's3PathStyle',\n 'toolSettings',\n 'userAgent',\n ];\n\n private static config: RepoGlobalConfig = {};\n\n static get(): RepoGlobalConfig;\n static get<Key extends keyof RepoGlobalConfig>(\n key: Key,\n ): Required<RepoGlobalConfig>[Key];\n static get<Key extends keyof RepoGlobalConfig>(\n key: Key,\n ): Required<RepoGlobalConfig>[Key];\n static get<Key extends keyof RepoGlobalConfig>(\n key?: Key,\n ): RepoGlobalConfig | Required<RepoGlobalConfig>[Key] {\n const defaultValue = key\n ? (globalConfigOptionDefaults[key] as Required<RepoGlobalConfig>[Key])\n : undefined;\n\n return key\n ? ((GlobalConfig.config[key] ??\n defaultValue) as Required<RepoGlobalConfig>[Key])\n : GlobalConfig.config;\n }\n\n static set(config: RenovateConfig & RepoGlobalConfig): RenovateConfig {\n GlobalConfig.reset();\n\n const result = { ...config };\n for (const option of GlobalConfig.OPTIONS) {\n GlobalConfig.config[option] = config[option] as never;\n delete result[option];\n }\n\n return result;\n }\n\n static reset(): void {\n GlobalConfig.config = {};\n }\n}\n"],"mappings":";;AAGA,IAAa,eAAb,MAAa,aAAa;CAExB,OAAO,UAA+C;EACpD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,OAAe,SAA2B,CAAC;CAS3C,OAAO,IACL,KACoD;EACpD,MAAM,eAAe,MAChB,2BAA2B,OAC5B,KAAA;EAEJ,OAAO,MACD,aAAa,OAAO,QACpB,eACF,aAAa;CACnB;CAEA,OAAO,IAAI,QAA2D;EACpE,aAAa,MAAM;EAEnB,MAAM,SAAS,EAAE,GAAG,OAAO;EAC3B,KAAK,MAAM,UAAU,aAAa,SAAS;GACzC,aAAa,OAAO,UAAU,OAAO;GACrC,OAAO,OAAO;EAChB;EAEA,OAAO;CACT;CAEA,OAAO,QAAc;EACnB,aAAa,SAAS,CAAC;CACzB;AACF"}
@@ -655,7 +655,7 @@ const options = [
655
655
  name: "dockerSidecarImage",
656
656
  description: "Change this value to override the default Renovate sidecar image.",
657
657
  type: "string",
658
- default: "ghcr.io/renovatebot/base-image:13.61.2",
658
+ default: "ghcr.io/renovatebot/base-image:13.62.0",
659
659
  globalOnly: true,
660
660
  deprecationMsg: "The usage of `binarySource=docker` is deprecated, and will be removed in the future"
661
661
  },