renovate 44.153.1 → 44.154.0

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.
@@ -8,5 +8,9 @@ export declare class GlobalConfig {
8
8
  static set(config: RenovateConfig & RepoGlobalConfig & InternalGlobalConfigOptions): RenovateConfig;
9
9
  static reset(): void;
10
10
  }
11
+ /**
12
+ * Sets the global options which HTTP requests consult, for the requests made before the full global config is set.
13
+ */
14
+ export declare function setHttpGlobalConfig(config: RenovateConfig & RepoGlobalConfig): void;
11
15
  //#endregion
12
16
  //# sourceMappingURL=global.d.ts.map
@@ -79,7 +79,19 @@ var GlobalConfig = class GlobalConfig {
79
79
  GlobalConfig.config = {};
80
80
  }
81
81
  };
82
+ /**
83
+ * Sets the global options which HTTP requests consult, for the requests made before the full global config is set.
84
+ */
85
+ function setHttpGlobalConfig(config) {
86
+ GlobalConfig.set({
87
+ allowedHeaders: config.allowedHeaders,
88
+ endpoint: config.endpoint,
89
+ internalHostAccess: config.internalHostAccess,
90
+ platform: config.platform,
91
+ userAgent: config.userAgent
92
+ });
93
+ }
82
94
  //#endregion
83
- export { GlobalConfig };
95
+ export { GlobalConfig, setHttpGlobalConfig };
84
96
 
85
97
  //# sourceMappingURL=global.js.map
@@ -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 {\n InternalGlobalConfigOptions,\n RenovateConfig,\n RepoGlobalConfig,\n} 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 = [\n 'allowCustomCrateGitRegistries',\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 'checkedBranches',\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 'inheritConfigTrusted',\n 'internalHostAccess',\n /** NOTE that this is not a config option, but an internal variable **/\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 'rebaseAllOpenBranches',\n 'repositoryCacheForceLocal',\n 'requireConfig',\n 's3Endpoint',\n 's3PathStyle',\n 'toolSettings',\n 'userAgent',\n ] as const satisfies readonly (\n keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions\n )[];\n\n private static config: RepoGlobalConfig & InternalGlobalConfigOptions = {};\n\n static get(): RepoGlobalConfig & InternalGlobalConfigOptions;\n static get<\n Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n >(key: Key): Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key];\n static get<\n Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n >(\n key?: Key,\n ):\n | (RepoGlobalConfig & InternalGlobalConfigOptions)\n | Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key] {\n const defaultValue = key\n ? (globalConfigOptionDefaults[key] as Required<\n RepoGlobalConfig & InternalGlobalConfigOptions\n >[Key])\n : undefined;\n\n return key\n ? ((GlobalConfig.config[key] ?? defaultValue) as Required<\n RepoGlobalConfig & InternalGlobalConfigOptions\n >[Key])\n : GlobalConfig.config;\n }\n\n static set(\n config: RenovateConfig & RepoGlobalConfig & InternalGlobalConfigOptions,\n ): 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":";;AAOA,IAAa,eAAb,MAAa,aAAa;CAExB,OAAO,UAAU;EACf;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;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAIA,OAAe,SAAyD,CAAC;CAMzE,OAAO,IAGL,KAGgE;EAChE,MAAM,eAAe,MAChB,2BAA2B,OAG5B,KAAA;EAEJ,OAAO,MACD,aAAa,OAAO,QAAQ,eAG9B,aAAa;CACnB;CAEA,OAAO,IACL,QACgB;EAChB,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 {\n InternalGlobalConfigOptions,\n RenovateConfig,\n RepoGlobalConfig,\n} 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 = [\n 'allowCustomCrateGitRegistries',\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 'checkedBranches',\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 'inheritConfigTrusted',\n 'internalHostAccess',\n /** NOTE that this is not a config option, but an internal variable **/\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 'rebaseAllOpenBranches',\n 'repositoryCacheForceLocal',\n 'requireConfig',\n 's3Endpoint',\n 's3PathStyle',\n 'toolSettings',\n 'userAgent',\n ] as const satisfies readonly (\n keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions\n )[];\n\n private static config: RepoGlobalConfig & InternalGlobalConfigOptions = {};\n\n static get(): RepoGlobalConfig & InternalGlobalConfigOptions;\n static get<\n Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n >(key: Key): Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key];\n static get<\n Key extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n >(\n key?: Key,\n ):\n | (RepoGlobalConfig & InternalGlobalConfigOptions)\n | Required<RepoGlobalConfig & InternalGlobalConfigOptions>[Key] {\n const defaultValue = key\n ? (globalConfigOptionDefaults[key] as Required<\n RepoGlobalConfig & InternalGlobalConfigOptions\n >[Key])\n : undefined;\n\n return key\n ? ((GlobalConfig.config[key] ?? defaultValue) as Required<\n RepoGlobalConfig & InternalGlobalConfigOptions\n >[Key])\n : GlobalConfig.config;\n }\n\n static set(\n config: RenovateConfig & RepoGlobalConfig & InternalGlobalConfigOptions,\n ): 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\n/**\n * Sets the global options which HTTP requests consult, for the requests made before the full global config is set.\n */\nexport function setHttpGlobalConfig(\n config: RenovateConfig & RepoGlobalConfig,\n): void {\n GlobalConfig.set({\n allowedHeaders: config.allowedHeaders,\n endpoint: config.endpoint,\n internalHostAccess: config.internalHostAccess,\n platform: config.platform,\n userAgent: config.userAgent,\n });\n}\n"],"mappings":";;AAOA,IAAa,eAAb,MAAa,aAAa;CAExB,OAAO,UAAU;EACf;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;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAIA,OAAe,SAAyD,CAAC;CAMzE,OAAO,IAGL,KAGgE;EAChE,MAAM,eAAe,MAChB,2BAA2B,OAG5B,KAAA;EAEJ,OAAO,MACD,aAAa,OAAO,QAAQ,eAG9B,aAAa;CACnB;CAEA,OAAO,IACL,QACgB;EAChB,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;;;;AAKA,SAAgB,oBACd,QACM;CACN,aAAa,IAAI;EACf,gBAAgB,OAAO;EACvB,UAAU,OAAO;EACjB,oBAAoB,OAAO;EAC3B,UAAU,OAAO;EACjB,WAAW,OAAO;CACpB,CAAC;AACH"}
@@ -2,10 +2,10 @@ import { logger } from "../../../../logger/index.js";
2
2
  import { toSha256 } from "../../../../util/hash.js";
3
3
  import { cachePathExists, createCacheReadStream, createCacheWriteStream, ensureCacheDir, pipeline, renameCacheFile, rmCache, statCacheFile } from "../../../../util/fs/index.js";
4
4
  import { acquireLock } from "../../../../util/mutex.js";
5
+ import { createDecompressStream } from "../../../../util/compress.js";
5
6
  import { isNullOrUndefined } from "@sindresorhus/is";
6
7
  import { randomUUID } from "node:crypto";
7
8
  import upath from "upath";
8
- import { createGunzip } from "node:zlib";
9
9
  //#region lib/modules/datasource/rpm/providers/common.ts
10
10
  const cacheSubDir = "rpm";
11
11
  function formatRpmVersion(ver, rel) {
@@ -53,7 +53,20 @@ async function downloadFileToCache(url, cachePath, http, lastDownloadTimestamp)
53
53
  return true;
54
54
  }
55
55
  async function decompressFile(compressedFile, decompressedFile) {
56
- await pipeline(createCacheReadStream(compressedFile), createGunzip(), createCacheWriteStream(decompressedFile));
56
+ const readStream = createCacheReadStream(compressedFile);
57
+ const decompressStream = await createDecompressStream(readStream);
58
+ if (decompressStream === readStream) {
59
+ readStream.destroy();
60
+ await renameCacheFile(compressedFile, decompressedFile);
61
+ return;
62
+ }
63
+ const tempFile = `${decompressedFile}.${randomUUID()}.tmp`;
64
+ try {
65
+ await pipeline(decompressStream, createCacheWriteStream(tempFile));
66
+ await renameCacheFile(tempFile, decompressedFile);
67
+ } finally {
68
+ await rmCache(tempFile);
69
+ }
57
70
  }
58
71
  async function getCachedDecompressedFile(http, url, extension) {
59
72
  const releaseLock = await acquireLock(`decompressed-file:${url}:${extension}`, "datasource-rpm");
@@ -63,11 +76,9 @@ async function getCachedDecompressedFile(http, url, extension) {
63
76
  const decompressedFile = upath.join(cacheDir, `${urlHash}.${extension}`);
64
77
  let lastTimestamp = await getFileCreationTime(decompressedFile);
65
78
  const compressedFile = upath.join(cacheDir, `${randomUUID()}_${urlHash}.gz`);
66
- const decompressedTempFile = upath.join(cacheDir, `${randomUUID()}_${urlHash}.${extension}`);
67
79
  try {
68
80
  if (await downloadFileToCache(url, compressedFile, http, lastTimestamp) || !lastTimestamp) try {
69
- await decompressFile(compressedFile, decompressedTempFile);
70
- await renameCacheFile(decompressedTempFile, decompressedFile);
81
+ await decompressFile(compressedFile, decompressedFile);
71
82
  lastTimestamp = await getFileCreationTime(decompressedFile);
72
83
  } catch (err) {
73
84
  logger.warn({
@@ -82,7 +93,6 @@ async function getCachedDecompressedFile(http, url, extension) {
82
93
  return decompressedFile;
83
94
  } finally {
84
95
  if (await cachePathExists(compressedFile)) await rmCache(compressedFile);
85
- if (await cachePathExists(decompressedTempFile)) await rmCache(decompressedTempFile);
86
96
  }
87
97
  } finally {
88
98
  releaseLock();
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["fs.statCacheFile","fs.createCacheWriteStream","fs.pipeline","fs.createCacheReadStream","fs.ensureCacheDir","fs.renameCacheFile","fs.cachePathExists","fs.rmCache"],"sources":["../../../../../lib/modules/datasource/rpm/providers/common.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { createGunzip } from 'node:zlib';\nimport { isNullOrUndefined } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { toSha256 } from '../../../../util/hash.ts';\nimport type { Http, HttpOptions } from '../../../../util/http/index.ts';\nimport { acquireLock } from '../../../../util/mutex.ts';\nimport type { ReleaseResult } from '../../types.ts';\nimport { datasource } from '../common.ts';\n\nconst cacheSubDir = datasource;\n\ntype RpmVersionValue = boolean | number | string | null | undefined;\n\nexport function formatRpmVersion(\n ver: RpmVersionValue,\n rel?: RpmVersionValue,\n): string | null {\n if (isNullOrUndefined(ver)) {\n return null;\n }\n\n const version = String(ver);\n\n if (isNullOrUndefined(rel)) {\n return version;\n }\n\n return `${version}-${String(rel)}`;\n}\n\nexport function buildReleaseResult(\n versions: Iterable<string>,\n): ReleaseResult | null {\n const uniqueVersions = [...new Set(versions)];\n\n if (uniqueVersions.length === 0) {\n return null;\n }\n\n return {\n releases: uniqueVersions.map((version) => ({ version })),\n };\n}\n\nasync function getFileCreationTime(\n filePath: string,\n): Promise<Date | undefined> {\n const stats = await fs.statCacheFile(filePath);\n return stats?.ctime;\n}\n\nasync function checkIfModified(\n url: string,\n lastDownloadTimestamp: Date,\n http: Http,\n): Promise<boolean> {\n const options: HttpOptions = {\n headers: {\n 'If-Modified-Since': lastDownloadTimestamp.toUTCString(),\n },\n };\n\n try {\n const response = await http.head(url, options);\n return response.statusCode !== 304;\n } catch (err) {\n logger.warn(\n {\n err,\n lastDownloadTimestamp,\n url,\n },\n 'Could not determine if metadata file is modified since last download',\n );\n return true;\n }\n}\n\nasync function downloadFileToCache(\n url: string,\n cachePath: string,\n http: Http,\n lastDownloadTimestamp?: Date,\n): Promise<boolean> {\n let needsToDownload = true;\n\n if (lastDownloadTimestamp) {\n needsToDownload = await checkIfModified(url, lastDownloadTimestamp, http);\n }\n\n if (!needsToDownload) {\n logger.debug(`No need to download ${url}, file is up to date.`);\n return false;\n }\n\n const readStream = http.stream(url);\n const writeStream = fs.createCacheWriteStream(cachePath);\n await fs.pipeline(readStream, writeStream);\n\n const compressedStats = await fs.statCacheFile(cachePath);\n if (!compressedStats || compressedStats.size === 0) {\n logger.debug(`Empty response body from getting ${url}.`);\n throw new Error(`Empty response body from getting ${url}.`);\n }\n\n return true;\n}\n\nasync function decompressFile(\n compressedFile: string,\n decompressedFile: string,\n): Promise<void> {\n await fs.pipeline(\n fs.createCacheReadStream(compressedFile),\n createGunzip(),\n fs.createCacheWriteStream(decompressedFile),\n );\n}\n\nexport async function getCachedDecompressedFile(\n http: Http,\n url: string,\n extension: 'xml',\n): Promise<string> {\n const releaseLock = await acquireLock(\n `decompressed-file:${url}:${extension}`,\n 'datasource-rpm',\n );\n\n try {\n const cacheDir = await fs.ensureCacheDir(cacheSubDir);\n const urlHash = toSha256(url);\n const decompressedFile = upath.join(cacheDir, `${urlHash}.${extension}`);\n let lastTimestamp = await getFileCreationTime(decompressedFile);\n\n const compressedFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.gz`,\n );\n const decompressedTempFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.${extension}`,\n );\n\n try {\n const wasUpdated = await downloadFileToCache(\n url,\n compressedFile,\n http,\n lastTimestamp,\n );\n\n if (wasUpdated || !lastTimestamp) {\n try {\n // Only replace the shared cache file after a successful decompress.\n await decompressFile(compressedFile, decompressedTempFile);\n await fs.renameCacheFile(decompressedTempFile, decompressedFile);\n lastTimestamp = await getFileCreationTime(decompressedFile);\n } catch (err) {\n logger.warn(\n {\n compressedFile,\n err,\n extension,\n decompressedFile,\n url,\n },\n 'Failed to extract RPM metadata file from compressed file',\n );\n }\n }\n\n if (!lastTimestamp) {\n throw new Error('Missing metadata in extracted RPM metadata file!');\n }\n\n return decompressedFile;\n } finally {\n if (await fs.cachePathExists(compressedFile)) {\n await fs.rmCache(compressedFile);\n }\n if (await fs.cachePathExists(decompressedTempFile)) {\n await fs.rmCache(decompressedTempFile);\n }\n }\n } finally {\n releaseLock();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"common.js","names":["fs.statCacheFile","fs.createCacheWriteStream","fs.pipeline","fs.createCacheReadStream","fs.renameCacheFile","fs.rmCache","fs.ensureCacheDir","fs.cachePathExists"],"sources":["../../../../../lib/modules/datasource/rpm/providers/common.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { isNullOrUndefined } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport { createDecompressStream } from '../../../../util/compress.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { toSha256 } from '../../../../util/hash.ts';\nimport type { Http, HttpOptions } from '../../../../util/http/index.ts';\nimport { acquireLock } from '../../../../util/mutex.ts';\nimport type { ReleaseResult } from '../../types.ts';\nimport { datasource } from '../common.ts';\n\nconst cacheSubDir = datasource;\n\ntype RpmVersionValue = boolean | number | string | null | undefined;\n\nexport function formatRpmVersion(\n ver: RpmVersionValue,\n rel?: RpmVersionValue,\n): string | null {\n if (isNullOrUndefined(ver)) {\n return null;\n }\n\n const version = String(ver);\n\n if (isNullOrUndefined(rel)) {\n return version;\n }\n\n return `${version}-${String(rel)}`;\n}\n\nexport function buildReleaseResult(\n versions: Iterable<string>,\n): ReleaseResult | null {\n const uniqueVersions = [...new Set(versions)];\n\n if (uniqueVersions.length === 0) {\n return null;\n }\n\n return {\n releases: uniqueVersions.map((version) => ({ version })),\n };\n}\n\nasync function getFileCreationTime(\n filePath: string,\n): Promise<Date | undefined> {\n const stats = await fs.statCacheFile(filePath);\n return stats?.ctime;\n}\n\nasync function checkIfModified(\n url: string,\n lastDownloadTimestamp: Date,\n http: Http,\n): Promise<boolean> {\n const options: HttpOptions = {\n headers: {\n 'If-Modified-Since': lastDownloadTimestamp.toUTCString(),\n },\n };\n\n try {\n const response = await http.head(url, options);\n return response.statusCode !== 304;\n } catch (err) {\n logger.warn(\n {\n err,\n lastDownloadTimestamp,\n url,\n },\n 'Could not determine if metadata file is modified since last download',\n );\n return true;\n }\n}\n\nasync function downloadFileToCache(\n url: string,\n cachePath: string,\n http: Http,\n lastDownloadTimestamp?: Date,\n): Promise<boolean> {\n let needsToDownload = true;\n\n if (lastDownloadTimestamp) {\n needsToDownload = await checkIfModified(url, lastDownloadTimestamp, http);\n }\n\n if (!needsToDownload) {\n logger.debug(`No need to download ${url}, file is up to date.`);\n return false;\n }\n\n const readStream = http.stream(url);\n const writeStream = fs.createCacheWriteStream(cachePath);\n await fs.pipeline(readStream, writeStream);\n\n const compressedStats = await fs.statCacheFile(cachePath);\n if (!compressedStats || compressedStats.size === 0) {\n logger.debug(`Empty response body from getting ${url}.`);\n throw new Error(`Empty response body from getting ${url}.`);\n }\n\n return true;\n}\n\nasync function decompressFile(\n compressedFile: string,\n decompressedFile: string,\n): Promise<void> {\n const readStream = fs.createCacheReadStream(compressedFile);\n const decompressStream = await createDecompressStream(readStream);\n\n if (decompressStream === readStream) {\n // The file is not compressed: rename it into place instead of copying it\n readStream.destroy();\n await fs.renameCacheFile(compressedFile, decompressedFile);\n return;\n }\n\n const tempFile = `${decompressedFile}.${randomUUID()}.tmp`;\n\n try {\n await fs.pipeline(decompressStream, fs.createCacheWriteStream(tempFile));\n // Only replace the shared cache file after a successful decompress.\n await fs.renameCacheFile(tempFile, decompressedFile);\n } finally {\n await fs.rmCache(tempFile);\n }\n}\n\nexport async function getCachedDecompressedFile(\n http: Http,\n url: string,\n extension: 'xml',\n): Promise<string> {\n const releaseLock = await acquireLock(\n `decompressed-file:${url}:${extension}`,\n 'datasource-rpm',\n );\n\n try {\n const cacheDir = await fs.ensureCacheDir(cacheSubDir);\n const urlHash = toSha256(url);\n const decompressedFile = upath.join(cacheDir, `${urlHash}.${extension}`);\n let lastTimestamp = await getFileCreationTime(decompressedFile);\n\n const compressedFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.gz`,\n );\n\n try {\n const wasUpdated = await downloadFileToCache(\n url,\n compressedFile,\n http,\n lastTimestamp,\n );\n\n if (wasUpdated || !lastTimestamp) {\n try {\n await decompressFile(compressedFile, decompressedFile);\n lastTimestamp = await getFileCreationTime(decompressedFile);\n } catch (err) {\n logger.warn(\n {\n compressedFile,\n err,\n extension,\n decompressedFile,\n url,\n },\n 'Failed to extract RPM metadata file from compressed file',\n );\n }\n }\n\n if (!lastTimestamp) {\n throw new Error('Missing metadata in extracted RPM metadata file!');\n }\n\n return decompressedFile;\n } finally {\n if (await fs.cachePathExists(compressedFile)) {\n await fs.rmCache(compressedFile);\n }\n }\n } finally {\n releaseLock();\n }\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { coerceArray, deduplicateArray, isNotNullOrUndefined } from "../../../..
2
2
  import { logger } from "../../../../logger/index.js";
3
3
  import { buildCacheKey } from "../../../../util/cache/package/key.js";
4
4
  import { hashStream } from "../../../../util/hash.js";
5
- import { createCacheWriteStream, ensureCacheDir, pipeline, rmCache } from "../../../../util/fs/index.js";
5
+ import { createCacheWriteStream, ensureCacheDir, pipeline as pipeline$1, rmCache } from "../../../../util/fs/index.js";
6
6
  import { withCache } from "../../../../util/cache/package/with-cache.js";
7
7
  import { Http } from "../../../../util/http/index.js";
8
8
  import { map } from "../../../../util/promises.js";
@@ -82,7 +82,7 @@ var TerraformProviderHash = class TerraformProviderHash {
82
82
  const readStream = TerraformProviderHash.http.stream(build.url);
83
83
  const writeStream = createCacheWriteStream(downloadFileName);
84
84
  try {
85
- await pipeline(readStream, writeStream);
85
+ await pipeline$1(readStream, writeStream);
86
86
  const hash = await this.hashOfZipContent(downloadFileName);
87
87
  logger.debug(`Hash generation for ${build.url} took ${Date.now() - startTime}ms for ${build.name}-${build.version}`);
88
88
  return hash;
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","names":["fs.createCacheWriteStream","fs.pipeline","fs.rmCache","fs.ensureCacheDir","p.map"],"sources":["../../../../../lib/modules/manager/terraform/lockfile/hash.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport { once } from 'node:events';\nimport { Transform, type TransformCallback } from 'node:stream';\nimport { crc32 } from 'node:zlib';\nimport upath from 'upath';\nimport { openPromise, validateFileName } from 'yauzl';\nimport { logger } from '../../../../logger/index.ts';\nimport {\n coerceArray,\n deduplicateArray,\n isNotNullOrUndefined,\n} from '../../../../util/array.ts';\nimport { buildCacheKey } from '../../../../util/cache/package/key.ts';\nimport { withCache } from '../../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { hashStream } from '../../../../util/hash.ts';\nimport { Http } from '../../../../util/http/index.ts';\nimport * as p from '../../../../util/promises.ts';\nimport { TerraformProviderDatasource } from '../../../datasource/terraform-provider/index.ts';\nimport type { TerraformBuild } from '../../../datasource/terraform-provider/schema.ts';\n\nclass Crc32Stream extends Transform {\n checksum = 0;\n\n override _transform(\n chunk: Buffer,\n _encoding: BufferEncoding,\n callback: TransformCallback,\n ): void {\n this.checksum = crc32(chunk, this.checksum);\n callback(null, chunk);\n }\n}\n\nexport class TerraformProviderHash {\n static http = new Http(TerraformProviderDatasource.id);\n\n static terraformDatasource = new TerraformProviderDatasource();\n\n static hashCacheTTL = 10080; // in minutes == 1 week\n\n /**\n * Computes the `h1:` checksum used in Terraform dependency lock files.\n *\n * Terraform verifies extracted providers with Go's `HashDir`, which ignores\n * ZIP directory entries. Ignore them here so the archive produces the same\n * checksum as the extracted provider.\n *\n * See https://github.com/golang/go/issues/53448.\n */\n static async hashOfZipContent(zipFilePath: string): Promise<string> {\n const zipFile = await openPromise(zipFilePath, {\n autoClose: false,\n decodeStrings: false,\n });\n const entryHashes: { path: Buffer; hash: string }[] = [];\n const entryPaths = new Set<string>();\n\n try {\n for await (const entry of zipFile.eachEntry()) {\n // Go's ZIP reader preserves the central-directory name bytes instead of decoding CP437 or Unicode path fields.\n const fileName = entry.fileNameRaw\n .toString('latin1')\n .replaceAll('\\\\', '/');\n\n // Terraform verifies extracted packages with Go HashDir semantics, which omit directory records.\n if (fileName.endsWith('/')) {\n continue;\n }\n if (fileName.includes('\\n')) {\n throw new Error('ZIP entry name contains a newline');\n }\n const fileNameError = validateFileName(fileName);\n if (fileNameError) {\n throw new Error(fileNameError);\n }\n const normalizedPath = upath.normalize(fileName);\n if (entryPaths.has(normalizedPath)) {\n throw new Error(`Duplicate ZIP entry path: ${normalizedPath}`);\n }\n entryPaths.add(normalizedPath);\n const path = Buffer.from(normalizedPath, 'latin1');\n\n const entryStream = await zipFile.openReadStreamPromise(entry);\n const crc32Stream = new Crc32Stream();\n const hash = await hashStream(\n entryStream.compose(crc32Stream),\n 'sha256',\n );\n if (crc32Stream.checksum !== entry.crc32) {\n throw new Error(\n `CRC-32 mismatch for ZIP entry ${entry.fileNameRaw.toString('utf8')}`,\n );\n }\n entryHashes.push({ path, hash });\n }\n } finally {\n const closePromise = once(zipFile, 'close');\n zipFile.close();\n await closePromise;\n }\n\n entryHashes.sort((left, right) => Buffer.compare(left.path, right.path));\n\n const rootHash = crypto.createHash('sha256');\n for (const entry of entryHashes) {\n rootHash.update(`${entry.hash} `);\n rootHash.update(entry.path);\n rootHash.update('\\n');\n }\n\n return rootHash.digest('base64');\n }\n\n private static async _calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n const downloadFileName = upath.join(cacheDir, crypto.randomUUID());\n logger.trace(\n `Downloading archive and generating hash for ${build.name}-${build.version}...`,\n );\n const startTime = Date.now();\n const readStream = TerraformProviderHash.http.stream(build.url);\n const writeStream = fs.createCacheWriteStream(downloadFileName);\n\n try {\n await fs.pipeline(readStream, writeStream);\n\n const hash = await this.hashOfZipContent(downloadFileName);\n logger.debug(\n `Hash generation for ${build.url} took ${Date.now() - startTime}ms for ${build.name}-${build.version}`,\n );\n return hash;\n } finally {\n await fs.rmCache(downloadFileName);\n }\n }\n\n static calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n return withCache(\n {\n namespace: `terraform-provider-hash`,\n key: buildCacheKey('calculateSingleHash', build.url),\n ttlMinutes: TerraformProviderHash.hashCacheTTL,\n },\n () => TerraformProviderHash._calculateSingleHash(build, cacheDir),\n );\n }\n\n static async calculateHashScheme1Hashes(\n builds: TerraformBuild[],\n ): Promise<string[]> {\n logger.debug(`Calculating hashes for ${builds.length} builds`);\n const cacheDir = await fs.ensureCacheDir('terraform');\n\n return p.map(builds, (build) => this.calculateSingleHash(build, cacheDir), {\n concurrency: 4,\n });\n }\n\n static async createHashes(\n registryURL: string,\n repository: string,\n version: string,\n ): Promise<string[] | null> {\n logger.debug(\n `Creating hashes for ${repository}@${version} (${registryURL})`,\n );\n\n if (\n registryURL === TerraformProviderDatasource.openTofuRegistryUrl ||\n registryURL === TerraformProviderDatasource.openTofuApiUrl\n ) {\n const packagesHashes =\n await TerraformProviderHash.terraformDatasource.getProviderPackages(\n repository,\n version,\n );\n if (packagesHashes?.length) {\n logger.debug(\n `Using OpenTofu packages API for ${repository}@${version}`,\n );\n // hashes are a logical set which Terraform deduplicates and sorts\n return deduplicateArray(packagesHashes).sort();\n }\n logger.debug(\n `OpenTofu packages field unavailable for ${repository}@${version}, falling back to zip download`,\n );\n }\n\n const builds = await TerraformProviderHash.terraformDatasource.getBuilds(\n registryURL,\n repository,\n version,\n );\n if (!builds) {\n return null;\n }\n\n // check if the publisher uses one shasum file for all builds or separate ones\n // we deduplicate to reduce the number of API calls\n const shaUrls = deduplicateArray(\n builds.map((build) => build.shasums_url).filter(isNotNullOrUndefined),\n );\n\n logger.debug(\n `Getting zip hashes for ${shaUrls.length} shasum URL(s) for ${repository}@${version}`,\n );\n\n const zhHashes: string[] = [];\n for (const shaUrl of shaUrls) {\n const hashes =\n await TerraformProviderHash.terraformDatasource.getZipHashes(shaUrl);\n\n zhHashes.push(...coerceArray(hashes));\n }\n\n logger.debug(\n `Got ${zhHashes.length} zip hashes for ${repository}@${version}`,\n );\n\n const h1Hashes =\n await TerraformProviderHash.calculateHashScheme1Hashes(builds);\n\n const hashes = [];\n hashes.push(...h1Hashes.map((hash) => `h1:${hash}`));\n hashes.push(...zhHashes.map((hash) => `zh:${hash}`));\n\n // hashes are a logical set which Terraform deduplicates and sorts\n return deduplicateArray(hashes).sort();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"hash.js","names":["fs.createCacheWriteStream","fs.pipeline","fs.rmCache","fs.ensureCacheDir","p.map"],"sources":["../../../../../lib/modules/manager/terraform/lockfile/hash.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport { once } from 'node:events';\nimport { Transform, type TransformCallback } from 'node:stream';\nimport { crc32 } from 'node:zlib';\nimport upath from 'upath';\nimport { openPromise, validateFileName } from 'yauzl';\nimport { logger } from '../../../../logger/index.ts';\nimport {\n coerceArray,\n deduplicateArray,\n isNotNullOrUndefined,\n} from '../../../../util/array.ts';\nimport { buildCacheKey } from '../../../../util/cache/package/key.ts';\nimport { withCache } from '../../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { hashStream } from '../../../../util/hash.ts';\nimport { Http } from '../../../../util/http/index.ts';\nimport * as p from '../../../../util/promises.ts';\nimport { TerraformProviderDatasource } from '../../../datasource/terraform-provider/index.ts';\nimport type { TerraformBuild } from '../../../datasource/terraform-provider/schema.ts';\n\nclass Crc32Stream extends Transform {\n checksum = 0;\n\n override _transform(\n chunk: Buffer,\n _encoding: BufferEncoding,\n callback: TransformCallback,\n ): void {\n this.checksum = crc32(chunk, this.checksum);\n callback(null, chunk);\n }\n}\n\nexport class TerraformProviderHash {\n static http = new Http(TerraformProviderDatasource.id);\n\n static terraformDatasource = new TerraformProviderDatasource();\n\n static hashCacheTTL = 10080; // in minutes == 1 week\n\n /**\n * Computes the `h1:` checksum used in Terraform dependency lock files.\n *\n * Terraform verifies extracted providers with Go's `HashDir`, which ignores\n * ZIP directory entries. Ignore them here so the archive produces the same\n * checksum as the extracted provider.\n *\n * See https://github.com/golang/go/issues/53448.\n */\n static async hashOfZipContent(zipFilePath: string): Promise<string> {\n const zipFile = await openPromise(zipFilePath, {\n autoClose: false,\n decodeStrings: false,\n });\n const entryHashes: { path: Buffer; hash: string }[] = [];\n const entryPaths = new Set<string>();\n\n try {\n for await (const entry of zipFile.eachEntry()) {\n // Go's ZIP reader preserves the central-directory name bytes instead of decoding CP437 or Unicode path fields.\n const fileName = entry.fileNameRaw\n .toString('latin1')\n .replaceAll('\\\\', '/');\n\n // Terraform verifies extracted packages with Go HashDir semantics, which omit directory records.\n if (fileName.endsWith('/')) {\n continue;\n }\n if (fileName.includes('\\n')) {\n throw new Error('ZIP entry name contains a newline');\n }\n const fileNameError = validateFileName(fileName);\n if (fileNameError) {\n throw new Error(fileNameError);\n }\n const normalizedPath = upath.normalize(fileName);\n if (entryPaths.has(normalizedPath)) {\n throw new Error(`Duplicate ZIP entry path: ${normalizedPath}`);\n }\n entryPaths.add(normalizedPath);\n const path = Buffer.from(normalizedPath, 'latin1');\n\n const entryStream = await zipFile.openReadStreamPromise(entry);\n const crc32Stream = new Crc32Stream();\n const hash = await hashStream(\n entryStream.compose(crc32Stream),\n 'sha256',\n );\n if (crc32Stream.checksum !== entry.crc32) {\n throw new Error(\n `CRC-32 mismatch for ZIP entry ${entry.fileNameRaw.toString('utf8')}`,\n );\n }\n entryHashes.push({ path, hash });\n }\n } finally {\n const closePromise = once(zipFile, 'close');\n zipFile.close();\n await closePromise;\n }\n\n entryHashes.sort((left, right) => Buffer.compare(left.path, right.path));\n\n const rootHash = crypto.createHash('sha256');\n for (const entry of entryHashes) {\n rootHash.update(`${entry.hash} `);\n rootHash.update(entry.path);\n rootHash.update('\\n');\n }\n\n return rootHash.digest('base64');\n }\n\n private static async _calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n const downloadFileName = upath.join(cacheDir, crypto.randomUUID());\n logger.trace(\n `Downloading archive and generating hash for ${build.name}-${build.version}...`,\n );\n const startTime = Date.now();\n const readStream = TerraformProviderHash.http.stream(build.url);\n const writeStream = fs.createCacheWriteStream(downloadFileName);\n\n try {\n await fs.pipeline(readStream, writeStream);\n\n const hash = await this.hashOfZipContent(downloadFileName);\n logger.debug(\n `Hash generation for ${build.url} took ${Date.now() - startTime}ms for ${build.name}-${build.version}`,\n );\n return hash;\n } finally {\n await fs.rmCache(downloadFileName);\n }\n }\n\n static calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n return withCache(\n {\n namespace: `terraform-provider-hash`,\n key: buildCacheKey('calculateSingleHash', build.url),\n ttlMinutes: TerraformProviderHash.hashCacheTTL,\n },\n () => TerraformProviderHash._calculateSingleHash(build, cacheDir),\n );\n }\n\n static async calculateHashScheme1Hashes(\n builds: TerraformBuild[],\n ): Promise<string[]> {\n logger.debug(`Calculating hashes for ${builds.length} builds`);\n const cacheDir = await fs.ensureCacheDir('terraform');\n\n return p.map(builds, (build) => this.calculateSingleHash(build, cacheDir), {\n concurrency: 4,\n });\n }\n\n static async createHashes(\n registryURL: string,\n repository: string,\n version: string,\n ): Promise<string[] | null> {\n logger.debug(\n `Creating hashes for ${repository}@${version} (${registryURL})`,\n );\n\n if (\n registryURL === TerraformProviderDatasource.openTofuRegistryUrl ||\n registryURL === TerraformProviderDatasource.openTofuApiUrl\n ) {\n const packagesHashes =\n await TerraformProviderHash.terraformDatasource.getProviderPackages(\n repository,\n version,\n );\n if (packagesHashes?.length) {\n logger.debug(\n `Using OpenTofu packages API for ${repository}@${version}`,\n );\n // hashes are a logical set which Terraform deduplicates and sorts\n return deduplicateArray(packagesHashes).sort();\n }\n logger.debug(\n `OpenTofu packages field unavailable for ${repository}@${version}, falling back to zip download`,\n );\n }\n\n const builds = await TerraformProviderHash.terraformDatasource.getBuilds(\n registryURL,\n repository,\n version,\n );\n if (!builds) {\n return null;\n }\n\n // check if the publisher uses one shasum file for all builds or separate ones\n // we deduplicate to reduce the number of API calls\n const shaUrls = deduplicateArray(\n builds.map((build) => build.shasums_url).filter(isNotNullOrUndefined),\n );\n\n logger.debug(\n `Getting zip hashes for ${shaUrls.length} shasum URL(s) for ${repository}@${version}`,\n );\n\n const zhHashes: string[] = [];\n for (const shaUrl of shaUrls) {\n const hashes =\n await TerraformProviderHash.terraformDatasource.getZipHashes(shaUrl);\n\n zhHashes.push(...coerceArray(hashes));\n }\n\n logger.debug(\n `Got ${zhHashes.length} zip hashes for ${repository}@${version}`,\n );\n\n const h1Hashes =\n await TerraformProviderHash.calculateHashScheme1Hashes(builds);\n\n const hashes = [];\n hashes.push(...h1Hashes.map((hash) => `h1:${hash}`));\n hashes.push(...zhHashes.map((hash) => `zh:${hash}`));\n\n // hashes are a logical set which Terraform deduplicates and sorts\n return deduplicateArray(hashes).sort();\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
+ import { Readable } from "node:stream";
1
2
  //#region lib/util/compress.d.ts
2
3
  export declare function compressToBuffer(input: string, quality?: number): Promise<Buffer>;
3
4
  export declare function decompressFromBuffer(input: Buffer): Promise<string>;
4
5
  export declare function compressToBase64(input: string): Promise<string>;
5
6
  export declare function decompressFromBase64(input: string): Promise<string>;
7
+ export declare function createDecompressStream(input: Readable): Promise<Readable>;
6
8
  //#endregion
7
9
  //# sourceMappingURL=compress.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { promisify } from "node:util";
2
+ import { finished, pipeline } from "node:stream";
2
3
  import zlib, { constants } from "node:zlib";
3
4
  //#region lib/util/compress.ts
4
5
  const brotliCompress = promisify(zlib.brotliCompress);
@@ -18,7 +19,49 @@ async function compressToBase64(input) {
18
19
  async function decompressFromBase64(input) {
19
20
  return await decompressFromBuffer(Buffer.from(input, "base64"));
20
21
  }
22
+ function peekHeader(readable, length) {
23
+ return new Promise((resolve, reject) => {
24
+ function read() {
25
+ const result = readable.read(length);
26
+ if (result) {
27
+ readable.removeListener("readable", read);
28
+ cleanup();
29
+ readable.unshift(result);
30
+ resolve(result);
31
+ }
32
+ }
33
+ readable.on("readable", read);
34
+ const cleanup = finished(readable, {
35
+ readable: true,
36
+ writable: false
37
+ }, (err) => {
38
+ readable.removeListener("readable", read);
39
+ cleanup();
40
+ if (err) reject(err);
41
+ else resolve(Buffer.from([]));
42
+ });
43
+ });
44
+ }
45
+ const algorithms = [{
46
+ header: Uint8Array.from([31, 139]),
47
+ createStream: zlib.createGunzip
48
+ }, {
49
+ header: Uint8Array.from([
50
+ 40,
51
+ 181,
52
+ 47,
53
+ 253
54
+ ]),
55
+ createStream: zlib.createZstdDecompress
56
+ }];
57
+ const maxHeaderLength = algorithms.reduce((maxLength, { header }) => Math.max(maxLength, header.length), 0);
58
+ async function createDecompressStream(input) {
59
+ const header = await peekHeader(input, maxHeaderLength);
60
+ const algorithm = algorithms.find((entry) => header.subarray(0, entry.header.length).compare(entry.header) === 0);
61
+ if (!algorithm) return input;
62
+ return pipeline(input, algorithm.createStream(), () => {});
63
+ }
21
64
  //#endregion
22
- export { compressToBase64, compressToBuffer, decompressFromBase64, decompressFromBuffer };
65
+ export { compressToBase64, compressToBuffer, createDecompressStream, decompressFromBase64, decompressFromBuffer };
23
66
 
24
67
  //# sourceMappingURL=compress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compress.js","names":[],"sources":["../../lib/util/compress.ts"],"sourcesContent":["import { promisify } from 'node:util';\nimport zlib, { constants } from 'node:zlib';\n\nconst brotliCompress = promisify(zlib.brotliCompress);\nconst brotliDecompress = promisify(zlib.brotliDecompress);\n\nexport async function compressToBuffer(\n input: string,\n quality = 8,\n): Promise<Buffer> {\n return await brotliCompress(input, {\n params: {\n [constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT,\n [constants.BROTLI_PARAM_QUALITY]: quality,\n },\n });\n}\n\nexport async function decompressFromBuffer(input: Buffer): Promise<string> {\n const str = await brotliDecompress(input);\n return str.toString('utf8');\n}\n\nexport async function compressToBase64(input: string): Promise<string> {\n const buf = await compressToBuffer(input);\n return buf.toString('base64');\n}\n\nexport async function decompressFromBase64(input: string): Promise<string> {\n return await decompressFromBuffer(Buffer.from(input, 'base64'));\n}\n"],"mappings":";;;AAGA,MAAM,iBAAiB,UAAU,KAAK,cAAc;AACpD,MAAM,mBAAmB,UAAU,KAAK,gBAAgB;AAExD,eAAsB,iBACpB,OACA,UAAU,GACO;CACjB,OAAO,MAAM,eAAe,OAAO,EACjC,QAAQ;GACL,UAAU,oBAAoB,UAAU;GACxC,UAAU,uBAAuB;CACpC,EACF,CAAC;AACH;AAEA,eAAsB,qBAAqB,OAAgC;CAEzE,QAAO,MADW,iBAAiB,KAAK,EAAA,CAC7B,SAAS,MAAM;AAC5B;AAEA,eAAsB,iBAAiB,OAAgC;CAErE,QAAO,MADW,iBAAiB,KAAK,EAAA,CAC7B,SAAS,QAAQ;AAC9B;AAEA,eAAsB,qBAAqB,OAAgC;CACzE,OAAO,MAAM,qBAAqB,OAAO,KAAK,OAAO,QAAQ,CAAC;AAChE"}
1
+ {"version":3,"file":"compress.js","names":[],"sources":["../../lib/util/compress.ts"],"sourcesContent":["import { type Readable, type Transform, finished, pipeline } from 'node:stream';\nimport { promisify } from 'node:util';\nimport zlib, { constants } from 'node:zlib';\n\nconst brotliCompress = promisify(zlib.brotliCompress);\nconst brotliDecompress = promisify(zlib.brotliDecompress);\n\nexport async function compressToBuffer(\n input: string,\n quality = 8,\n): Promise<Buffer> {\n return await brotliCompress(input, {\n params: {\n [constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT,\n [constants.BROTLI_PARAM_QUALITY]: quality,\n },\n });\n}\n\nexport async function decompressFromBuffer(input: Buffer): Promise<string> {\n const str = await brotliDecompress(input);\n return str.toString('utf8');\n}\n\nexport async function compressToBase64(input: string): Promise<string> {\n const buf = await compressToBuffer(input);\n return buf.toString('base64');\n}\n\nexport async function decompressFromBase64(input: string): Promise<string> {\n return await decompressFromBuffer(Buffer.from(input, 'base64'));\n}\n\nfunction peekHeader(readable: Readable, length: number): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n function read(): void {\n const result = readable.read(length);\n if (result) {\n readable.removeListener('readable', read);\n cleanup();\n readable.unshift(result);\n resolve(result);\n }\n }\n\n readable.on('readable', read);\n\n const cleanup = finished(\n readable,\n { readable: true, writable: false },\n (err) => {\n readable.removeListener('readable', read);\n cleanup();\n if (err) {\n reject(err);\n } else {\n resolve(Buffer.from([]));\n }\n },\n );\n });\n}\n\nconst algorithms: { header: Uint8Array; createStream: () => Transform }[] = [\n {\n header: Uint8Array.from([0x1f, 0x8b]),\n createStream: zlib.createGunzip,\n },\n {\n header: Uint8Array.from([0x28, 0xb5, 0x2f, 0xfd]),\n createStream: zlib.createZstdDecompress,\n },\n];\n\nconst maxHeaderLength = algorithms.reduce(\n (maxLength, { header }) => Math.max(maxLength, header.length),\n 0,\n);\n\nexport async function createDecompressStream(\n input: Readable,\n): Promise<Readable> {\n const header = await peekHeader(input, maxHeaderLength);\n const algorithm = algorithms.find(\n (entry) =>\n header.subarray(0, entry.header.length).compare(entry.header) === 0,\n );\n if (!algorithm) {\n return input;\n }\n return pipeline(input, algorithm.createStream(), () => {\n // Nothing to do here, but the callback argument is required\n });\n}\n"],"mappings":";;;;AAIA,MAAM,iBAAiB,UAAU,KAAK,cAAc;AACpD,MAAM,mBAAmB,UAAU,KAAK,gBAAgB;AAExD,eAAsB,iBACpB,OACA,UAAU,GACO;CACjB,OAAO,MAAM,eAAe,OAAO,EACjC,QAAQ;GACL,UAAU,oBAAoB,UAAU;GACxC,UAAU,uBAAuB;CACpC,EACF,CAAC;AACH;AAEA,eAAsB,qBAAqB,OAAgC;CAEzE,QAAO,MADW,iBAAiB,KAAK,EAAA,CAC7B,SAAS,MAAM;AAC5B;AAEA,eAAsB,iBAAiB,OAAgC;CAErE,QAAO,MADW,iBAAiB,KAAK,EAAA,CAC7B,SAAS,QAAQ;AAC9B;AAEA,eAAsB,qBAAqB,OAAgC;CACzE,OAAO,MAAM,qBAAqB,OAAO,KAAK,OAAO,QAAQ,CAAC;AAChE;AAEA,SAAS,WAAW,UAAoB,QAAiC;CACvE,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,SAAS,OAAa;GACpB,MAAM,SAAS,SAAS,KAAK,MAAM;GACnC,IAAI,QAAQ;IACV,SAAS,eAAe,YAAY,IAAI;IACxC,QAAQ;IACR,SAAS,QAAQ,MAAM;IACvB,QAAQ,MAAM;GAChB;EACF;EAEA,SAAS,GAAG,YAAY,IAAI;EAE5B,MAAM,UAAU,SACd,UACA;GAAE,UAAU;GAAM,UAAU;EAAM,IACjC,QAAQ;GACP,SAAS,eAAe,YAAY,IAAI;GACxC,QAAQ;GACR,IAAI,KACF,OAAO,GAAG;QAEV,QAAQ,OAAO,KAAK,CAAC,CAAC,CAAC;EAE3B,CACF;CACF,CAAC;AACH;AAEA,MAAM,aAAsE,CAC1E;CACE,QAAQ,WAAW,KAAK,CAAC,IAAM,GAAI,CAAC;CACpC,cAAc,KAAK;AACrB,GACA;CACE,QAAQ,WAAW,KAAK;EAAC;EAAM;EAAM;EAAM;CAAI,CAAC;CAChD,cAAc,KAAK;AACrB,CACF;AAEA,MAAM,kBAAkB,WAAW,QAChC,WAAW,EAAE,aAAa,KAAK,IAAI,WAAW,OAAO,MAAM,GAC5D,CACF;AAEA,eAAsB,uBACpB,OACmB;CACnB,MAAM,SAAS,MAAM,WAAW,OAAO,eAAe;CACtD,MAAM,YAAY,WAAW,MAC1B,UACC,OAAO,SAAS,GAAG,MAAM,OAAO,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM,MAAM,CACtE;CACA,IAAI,CAAC,WACH,OAAO;CAET,OAAO,SAAS,OAAO,UAAU,aAAa,SAAS,CAEvD,CAAC;AACH"}
@@ -9,7 +9,7 @@ import stream from "node:stream";
9
9
  import upath from "upath";
10
10
  import { findUp } from "find-up";
11
11
  //#region lib/util/fs/index.ts
12
- const pipeline = util.promisify(stream.pipeline);
12
+ const pipeline$1 = util.promisify(stream.pipeline);
13
13
  function getParentDir(fileName) {
14
14
  return upath.parse(fileName).dir;
15
15
  }
@@ -221,6 +221,6 @@ async function getLocalFiles(fileNames) {
221
221
  return fileContentMap;
222
222
  }
223
223
  //#endregion
224
- export { cachePathExists, chmodLocalFile, createCacheReadStream, createCacheWriteStream, deleteLocalFile, ensureCacheDir, ensureDir, ensureLocalDir, findLocalSiblingOrParent, findUpLocal, getLocalFiles, getParentDir, getSiblingFileName, isValidLocalPath, localPathExists, localPathIsFile, localPathIsSymbolicLink, outputCacheFile, pipeline, privateCacheDir, readCacheFile, readLocalDirectory, readLocalFile, readLocalSymlink, readSystemFile, renameCacheFile, renameLocalFile, rmCache, statCacheFile, statLocalFile, writeLocalFile, writeSystemFile };
224
+ export { cachePathExists, chmodLocalFile, createCacheReadStream, createCacheWriteStream, deleteLocalFile, ensureCacheDir, ensureDir, ensureLocalDir, findLocalSiblingOrParent, findUpLocal, getLocalFiles, getParentDir, getSiblingFileName, isValidLocalPath, localPathExists, localPathIsFile, localPathIsSymbolicLink, outputCacheFile, pipeline$1 as pipeline, privateCacheDir, readCacheFile, readLocalDirectory, readLocalFile, readLocalSymlink, readSystemFile, renameCacheFile, renameLocalFile, rmCache, statCacheFile, statLocalFile, writeLocalFile, writeSystemFile };
225
225
 
226
226
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../lib/util/fs/index.ts"],"sourcesContent":["import stream from 'node:stream';\nimport util from 'node:util';\nimport { isNonEmptyString } from '@sindresorhus/is';\nimport { findUp } from 'find-up';\nimport fs from 'fs-extra';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport { logWarningIfUnicodeHiddenCharactersInPackageFile } from '../unicode.ts';\nimport { ensureCachePath, ensureLocalPath, isValidPath } from './util.ts';\n\nexport const pipeline = util.promisify(stream.pipeline);\n\nexport function getParentDir(fileName: string): string {\n return upath.parse(fileName).dir;\n}\n\nexport function getSiblingFileName(\n fileName: string,\n siblingName: string,\n): string {\n const subDirectory = getParentDir(fileName);\n return upath.join(subDirectory, siblingName);\n}\n\nexport async function readLocalFile(fileName: string): Promise<Buffer | null>;\nexport async function readLocalFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string | null>;\nexport async function readLocalFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer | null> {\n const localFileName = ensureLocalPath(fileName);\n try {\n const fileContent = encoding\n ? await fs.readFile(localFileName, encoding)\n : await fs.readFile(localFileName);\n\n logWarningIfUnicodeHiddenCharactersInPackageFile(fileName, fileContent);\n\n return fileContent;\n } catch (err) {\n logger.trace({ err }, 'Error reading local file');\n return null;\n }\n}\n\nexport async function readLocalSymlink(\n fileName: string,\n): Promise<string | null> {\n const localFileName = ensureLocalPath(fileName);\n try {\n const linkContent = await fs.readlink(localFileName);\n return linkContent;\n } catch (err) {\n logger.trace({ err }, 'Error reading local symlink');\n return null;\n }\n}\n\nexport async function writeLocalFile(\n fileName: string,\n fileContent: string | Buffer,\n): Promise<void> {\n const localFileName = ensureLocalPath(fileName);\n await fs.outputFile(localFileName, fileContent);\n}\n\nexport async function deleteLocalFile(fileName: string): Promise<void> {\n // This a failsafe and hopefully will never be triggered\n if (GlobalConfig.get('platform') === 'local') {\n throw new Error('Cannot delete file when platform=local');\n }\n const localDir = GlobalConfig.get('localDir');\n if (localDir) {\n const localFileName = ensureLocalPath(fileName);\n await fs.remove(localFileName);\n }\n}\n\nexport async function renameLocalFile(\n fromFile: string,\n toFile: string,\n): Promise<void> {\n const fromPath = ensureLocalPath(fromFile);\n const toPath = ensureLocalPath(toFile);\n await fs.move(fromPath, toPath);\n}\n\nexport async function renameCacheFile(\n fromFile: string,\n toFile: string,\n): Promise<void> {\n const fromPath = ensureCachePath(fromFile);\n const toPath = ensureCachePath(toFile);\n await fs.rename(fromPath, toPath);\n}\n\nexport async function ensureDir(dirName: string): Promise<void> {\n // v8 ignore else -- TODO: add test #40625\n if (isNonEmptyString(dirName)) {\n await fs.ensureDir(dirName);\n }\n}\n\nexport async function ensureLocalDir(dirName: string): Promise<string> {\n const fullPath = ensureLocalPath(dirName);\n await fs.ensureDir(fullPath);\n return fullPath;\n}\n\nexport async function ensureCacheDir(name: string): Promise<string> {\n const cacheDirName = ensureCachePath(`others/${name}`);\n await fs.ensureDir(cacheDirName);\n return cacheDirName;\n}\n\n/**\n * Return the path of the private cache directory. This directory is wiped\n * between repositories, so they can be used to store private registries' index\n * without risk of that information leaking to other repositories/users.\n */\nexport function privateCacheDir(): string {\n // TODO: types (#22198)\n const cacheDir = GlobalConfig.get('cacheDir');\n return upath.join(cacheDir, '__renovate-private-cache');\n}\n\nexport async function localPathExists(pathName: string): Promise<boolean> {\n // Works for both files as well as directories\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.stat(path);\n return !!s;\n } catch {\n return false;\n }\n}\n\n/**\n * Validate local path without throwing.\n * @param path Path to check\n * @returns `true` if given `path` is a valid local path, otherwise `false`.\n */\nexport function isValidLocalPath(path: string): boolean {\n return isValidPath(path, 'localDir');\n}\n\n/**\n * Tries to find `otherFileName` in the directory where\n * `existingFileNameWithPath` is, then in its parent directory, then in the\n * grandparent, until we reach the top-level directory. All paths\n * must be relative to `localDir`.\n */\nexport async function findLocalSiblingOrParent(\n existingFileNameWithPath: string,\n otherFileName: string,\n): Promise<string | null> {\n if (upath.isAbsolute(existingFileNameWithPath)) {\n return null;\n }\n if (upath.isAbsolute(otherFileName)) {\n return null;\n }\n\n let current = existingFileNameWithPath;\n while (current !== '') {\n current = getParentDir(current);\n const candidate = upath.join(current, otherFileName);\n if (await localPathExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Get files by name from directory\n */\nexport async function readLocalDirectory(path: string): Promise<string[]> {\n const localPath = ensureLocalPath(path);\n const fileList = await fs.readdir(localPath);\n return fileList;\n}\n\nexport function createCacheWriteStream(path: string): fs.WriteStream {\n const fullPath = ensureCachePath(path);\n return fs.createWriteStream(fullPath);\n}\n\nexport function createCacheReadStream(path: string): fs.ReadStream {\n const fullPath = ensureCachePath(path);\n return fs.createReadStream(fullPath);\n}\n\nexport async function localPathIsFile(pathName: string): Promise<boolean> {\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.stat(path);\n return s.isFile();\n } catch {\n return false;\n }\n}\n\nexport async function localPathIsSymbolicLink(\n pathName: string,\n): Promise<boolean> {\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.lstat(path);\n return s.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * Find a file or directory by walking up parent directories within localDir\n */\n\nexport async function findUpLocal(\n fileName: string | string[],\n cwd: string,\n): Promise<string | null> {\n // TODO: types (#22198)\n const localDir = GlobalConfig.get('localDir');\n const absoluteCwd = upath.join(localDir, cwd);\n const normalizedAbsoluteCwd = upath.normalizeSafe(absoluteCwd);\n const res = await findUp(fileName, {\n cwd: normalizedAbsoluteCwd,\n type: 'file',\n });\n // Return null if nothing found\n if (!isNonEmptyString(res) || !isNonEmptyString(localDir)) {\n return null;\n }\n const safePath = upath.normalizeSafe(res);\n // Return relative path if file is inside of local dir\n if (safePath.startsWith(localDir)) {\n let relativePath = safePath.replace(localDir, '');\n // v8 ignore else -- TODO: add test #40625\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substring(1);\n }\n return relativePath;\n }\n // Return null if found file is outside of localDir\n return null;\n}\n\nexport function chmodLocalFile(\n fileName: string,\n mode: string | number,\n): Promise<void> {\n const fullFileName = ensureLocalPath(fileName);\n return fs.chmod(fullFileName, mode);\n}\n\nexport async function statLocalFile(\n fileName: string,\n): Promise<fs.Stats | null> {\n const fullFileName = ensureLocalPath(fileName);\n try {\n return await fs.stat(fullFileName);\n } catch {\n return null;\n }\n}\n\nexport async function statCacheFile(\n pathName: string,\n): Promise<fs.Stats | null> {\n const path = ensureCachePath(pathName);\n try {\n return await fs.stat(path);\n } catch {\n return null;\n }\n}\n\nexport function listCacheDir(\n path: string,\n options: { recursive: boolean } = { recursive: false },\n): Promise<string[]> {\n const fullPath = ensureCachePath(path);\n return fs.readdir(fullPath, {\n encoding: 'utf-8',\n recursive: options.recursive,\n });\n}\n\nexport async function rmCache(path: string): Promise<void> {\n const fullPath = ensureCachePath(path);\n // force: a missing path is a no-op, callers use this for cleanup\n await fs.rm(fullPath, { recursive: true, force: true });\n}\n\nexport async function cachePathExists(pathName: string): Promise<boolean> {\n const path = ensureCachePath(pathName);\n try {\n const s = await fs.stat(path);\n return !!s;\n } catch {\n return false;\n }\n}\n\nexport async function cachePathIsFile(pathName: string): Promise<boolean> {\n const path = ensureCachePath(pathName);\n try {\n const s = await fs.stat(path);\n return s.isFile();\n } catch {\n return false;\n }\n}\n\nexport async function readCacheFile(fileName: string): Promise<Buffer>;\nexport async function readCacheFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string>;\nexport function readCacheFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer> {\n const fullPath = ensureCachePath(fileName);\n return encoding ? fs.readFile(fullPath, encoding) : fs.readFile(fullPath);\n}\n\nexport function outputCacheFile(\n file: string,\n data: string | NodeJS.ArrayBufferView,\n): Promise<void> {\n const filePath = ensureCachePath(file);\n return fs.outputFile(filePath, data);\n}\n\nexport async function readSystemFile(fileName: string): Promise<Buffer>;\nexport async function readSystemFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string>;\nexport function readSystemFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer> {\n return encoding ? fs.readFile(fileName, encoding) : fs.readFile(fileName);\n}\n\nexport async function writeSystemFile(\n fileName: string,\n data: string | Buffer,\n): Promise<void> {\n await fs.outputFile(fileName, data);\n}\n\nexport async function getLocalFiles(\n fileNames: string[],\n): Promise<Record<string, string | null>> {\n const fileContentMap: Record<string, string | null> = {};\n\n for (const fileName of fileNames) {\n fileContentMap[fileName] = await readLocalFile(fileName, 'utf8');\n }\n\n return fileContentMap;\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,WAAW,KAAK,UAAU,OAAO,QAAQ;AAEtD,SAAgB,aAAa,UAA0B;CACrD,OAAO,MAAM,MAAM,QAAQ,CAAC,CAAC;AAC/B;AAEA,SAAgB,mBACd,UACA,aACQ;CACR,MAAM,eAAe,aAAa,QAAQ;CAC1C,OAAO,MAAM,KAAK,cAAc,WAAW;AAC7C;AAOA,eAAsB,cACpB,UACA,UACiC;CACjC,MAAM,gBAAgB,gBAAgB,QAAQ;CAC9C,IAAI;EACF,MAAM,cAAc,WAChB,MAAM,GAAG,SAAS,eAAe,QAAQ,IACzC,MAAM,GAAG,SAAS,aAAa;EAEnC,iDAAiD,UAAU,WAAW;EAEtE,OAAO;CACT,SAAS,KAAK;EACZ,OAAO,MAAM,EAAE,IAAI,GAAG,0BAA0B;EAChD,OAAO;CACT;AACF;AAEA,eAAsB,iBACpB,UACwB;CACxB,MAAM,gBAAgB,gBAAgB,QAAQ;CAC9C,IAAI;EAEF,OAAO,MADmB,GAAG,SAAS,aAAa;CAErD,SAAS,KAAK;EACZ,OAAO,MAAM,EAAE,IAAI,GAAG,6BAA6B;EACnD,OAAO;CACT;AACF;AAEA,eAAsB,eACpB,UACA,aACe;CACf,MAAM,gBAAgB,gBAAgB,QAAQ;CAC9C,MAAM,GAAG,WAAW,eAAe,WAAW;AAChD;AAEA,eAAsB,gBAAgB,UAAiC;CAErE,IAAI,aAAa,IAAI,UAAU,MAAM,SACnC,MAAM,IAAI,MAAM,wCAAwC;CAG1D,IADiB,aAAa,IAAI,UACvB,GAAG;EACZ,MAAM,gBAAgB,gBAAgB,QAAQ;EAC9C,MAAM,GAAG,OAAO,aAAa;CAC/B;AACF;AAEA,eAAsB,gBACpB,UACA,QACe;CACf,MAAM,WAAW,gBAAgB,QAAQ;CACzC,MAAM,SAAS,gBAAgB,MAAM;CACrC,MAAM,GAAG,KAAK,UAAU,MAAM;AAChC;AAEA,eAAsB,gBACpB,UACA,QACe;CACf,MAAM,WAAW,gBAAgB,QAAQ;CACzC,MAAM,SAAS,gBAAgB,MAAM;CACrC,MAAM,GAAG,OAAO,UAAU,MAAM;AAClC;AAEA,eAAsB,UAAU,SAAgC;;CAE9D,IAAI,iBAAiB,OAAO,GAC1B,MAAM,GAAG,UAAU,OAAO;AAE9B;AAEA,eAAsB,eAAe,SAAkC;CACrE,MAAM,WAAW,gBAAgB,OAAO;CACxC,MAAM,GAAG,UAAU,QAAQ;CAC3B,OAAO;AACT;AAEA,eAAsB,eAAe,MAA+B;CAClE,MAAM,eAAe,gBAAgB,UAAU,MAAM;CACrD,MAAM,GAAG,UAAU,YAAY;CAC/B,OAAO;AACT;;;;;;AAOA,SAAgB,kBAA0B;CAExC,MAAM,WAAW,aAAa,IAAI,UAAU;CAC5C,OAAO,MAAM,KAAK,UAAU,0BAA0B;AACxD;AAEA,eAAsB,gBAAgB,UAAoC;CAExE,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI;EAEF,OAAO,CAAC,CAAC,MADO,GAAG,KAAK,IAAI;CAE9B,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAgB,iBAAiB,MAAuB;CACtD,OAAO,YAAY,MAAM,UAAU;AACrC;;;;;;;AAQA,eAAsB,yBACpB,0BACA,eACwB;CACxB,IAAI,MAAM,WAAW,wBAAwB,GAC3C,OAAO;CAET,IAAI,MAAM,WAAW,aAAa,GAChC,OAAO;CAGT,IAAI,UAAU;CACd,OAAO,YAAY,IAAI;EACrB,UAAU,aAAa,OAAO;EAC9B,MAAM,YAAY,MAAM,KAAK,SAAS,aAAa;EACnD,IAAI,MAAM,gBAAgB,SAAS,GACjC,OAAO;CAEX;CAEA,OAAO;AACT;;;;AAKA,eAAsB,mBAAmB,MAAiC;CACxE,MAAM,YAAY,gBAAgB,IAAI;CAEtC,OAAO,MADgB,GAAG,QAAQ,SAAS;AAE7C;AAEA,SAAgB,uBAAuB,MAA8B;CACnE,MAAM,WAAW,gBAAgB,IAAI;CACrC,OAAO,GAAG,kBAAkB,QAAQ;AACtC;AAEA,SAAgB,sBAAsB,MAA6B;CACjE,MAAM,WAAW,gBAAgB,IAAI;CACrC,OAAO,GAAG,iBAAiB,QAAQ;AACrC;AAEA,eAAsB,gBAAgB,UAAoC;CACxE,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI;EAEF,QAAO,MADS,GAAG,KAAK,IAAI,EAAA,CACnB,OAAO;CAClB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAsB,wBACpB,UACkB;CAClB,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI;EAEF,QAAO,MADS,GAAG,MAAM,IAAI,EAAA,CACpB,eAAe;CAC1B,QAAQ;EACN,OAAO;CACT;AACF;;;;AAMA,eAAsB,YACpB,UACA,KACwB;CAExB,MAAM,WAAW,aAAa,IAAI,UAAU;CAC5C,MAAM,cAAc,MAAM,KAAK,UAAU,GAAG;CAC5C,MAAM,wBAAwB,MAAM,cAAc,WAAW;CAC7D,MAAM,MAAM,MAAM,OAAO,UAAU;EACjC,KAAK;EACL,MAAM;CACR,CAAC;CAED,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,QAAQ,GACtD,OAAO;CAET,MAAM,WAAW,MAAM,cAAc,GAAG;CAExC,IAAI,SAAS,WAAW,QAAQ,GAAG;EACjC,IAAI,eAAe,SAAS,QAAQ,UAAU,EAAE;;EAEhD,IAAI,aAAa,WAAW,GAAG,GAC7B,eAAe,aAAa,UAAU,CAAC;EAEzC,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAgB,eACd,UACA,MACe;CACf,MAAM,eAAe,gBAAgB,QAAQ;CAC7C,OAAO,GAAG,MAAM,cAAc,IAAI;AACpC;AAEA,eAAsB,cACpB,UAC0B;CAC1B,MAAM,eAAe,gBAAgB,QAAQ;CAC7C,IAAI;EACF,OAAO,MAAM,GAAG,KAAK,YAAY;CACnC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAsB,cACpB,UAC0B;CAC1B,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI;EACF,OAAO,MAAM,GAAG,KAAK,IAAI;CAC3B,QAAQ;EACN,OAAO;CACT;AACF;AAaA,eAAsB,QAAQ,MAA6B;CACzD,MAAM,WAAW,gBAAgB,IAAI;CAErC,MAAM,GAAG,GAAG,UAAU;EAAE,WAAW;EAAM,OAAO;CAAK,CAAC;AACxD;AAEA,eAAsB,gBAAgB,UAAoC;CACxE,MAAM,OAAO,gBAAgB,QAAQ;CACrC,IAAI;EAEF,OAAO,CAAC,CAAC,MADO,GAAG,KAAK,IAAI;CAE9B,QAAQ;EACN,OAAO;CACT;AACF;AAiBA,SAAgB,cACd,UACA,UAC0B;CAC1B,MAAM,WAAW,gBAAgB,QAAQ;CACzC,OAAO,WAAW,GAAG,SAAS,UAAU,QAAQ,IAAI,GAAG,SAAS,QAAQ;AAC1E;AAEA,SAAgB,gBACd,MACA,MACe;CACf,MAAM,WAAW,gBAAgB,IAAI;CACrC,OAAO,GAAG,WAAW,UAAU,IAAI;AACrC;AAOA,SAAgB,eACd,UACA,UAC0B;CAC1B,OAAO,WAAW,GAAG,SAAS,UAAU,QAAQ,IAAI,GAAG,SAAS,QAAQ;AAC1E;AAEA,eAAsB,gBACpB,UACA,MACe;CACf,MAAM,GAAG,WAAW,UAAU,IAAI;AACpC;AAEA,eAAsB,cACpB,WACwC;CACxC,MAAM,iBAAgD,CAAC;CAEvD,KAAK,MAAM,YAAY,WACrB,eAAe,YAAY,MAAM,cAAc,UAAU,MAAM;CAGjE,OAAO;AACT"}
1
+ {"version":3,"file":"index.js","names":["pipeline"],"sources":["../../../lib/util/fs/index.ts"],"sourcesContent":["import stream from 'node:stream';\nimport util from 'node:util';\nimport { isNonEmptyString } from '@sindresorhus/is';\nimport { findUp } from 'find-up';\nimport fs from 'fs-extra';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../config/global.ts';\nimport { logger } from '../../logger/index.ts';\nimport { logWarningIfUnicodeHiddenCharactersInPackageFile } from '../unicode.ts';\nimport { ensureCachePath, ensureLocalPath, isValidPath } from './util.ts';\n\nexport const pipeline = util.promisify(stream.pipeline);\n\nexport function getParentDir(fileName: string): string {\n return upath.parse(fileName).dir;\n}\n\nexport function getSiblingFileName(\n fileName: string,\n siblingName: string,\n): string {\n const subDirectory = getParentDir(fileName);\n return upath.join(subDirectory, siblingName);\n}\n\nexport async function readLocalFile(fileName: string): Promise<Buffer | null>;\nexport async function readLocalFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string | null>;\nexport async function readLocalFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer | null> {\n const localFileName = ensureLocalPath(fileName);\n try {\n const fileContent = encoding\n ? await fs.readFile(localFileName, encoding)\n : await fs.readFile(localFileName);\n\n logWarningIfUnicodeHiddenCharactersInPackageFile(fileName, fileContent);\n\n return fileContent;\n } catch (err) {\n logger.trace({ err }, 'Error reading local file');\n return null;\n }\n}\n\nexport async function readLocalSymlink(\n fileName: string,\n): Promise<string | null> {\n const localFileName = ensureLocalPath(fileName);\n try {\n const linkContent = await fs.readlink(localFileName);\n return linkContent;\n } catch (err) {\n logger.trace({ err }, 'Error reading local symlink');\n return null;\n }\n}\n\nexport async function writeLocalFile(\n fileName: string,\n fileContent: string | Buffer,\n): Promise<void> {\n const localFileName = ensureLocalPath(fileName);\n await fs.outputFile(localFileName, fileContent);\n}\n\nexport async function deleteLocalFile(fileName: string): Promise<void> {\n // This a failsafe and hopefully will never be triggered\n if (GlobalConfig.get('platform') === 'local') {\n throw new Error('Cannot delete file when platform=local');\n }\n const localDir = GlobalConfig.get('localDir');\n if (localDir) {\n const localFileName = ensureLocalPath(fileName);\n await fs.remove(localFileName);\n }\n}\n\nexport async function renameLocalFile(\n fromFile: string,\n toFile: string,\n): Promise<void> {\n const fromPath = ensureLocalPath(fromFile);\n const toPath = ensureLocalPath(toFile);\n await fs.move(fromPath, toPath);\n}\n\nexport async function renameCacheFile(\n fromFile: string,\n toFile: string,\n): Promise<void> {\n const fromPath = ensureCachePath(fromFile);\n const toPath = ensureCachePath(toFile);\n await fs.rename(fromPath, toPath);\n}\n\nexport async function ensureDir(dirName: string): Promise<void> {\n // v8 ignore else -- TODO: add test #40625\n if (isNonEmptyString(dirName)) {\n await fs.ensureDir(dirName);\n }\n}\n\nexport async function ensureLocalDir(dirName: string): Promise<string> {\n const fullPath = ensureLocalPath(dirName);\n await fs.ensureDir(fullPath);\n return fullPath;\n}\n\nexport async function ensureCacheDir(name: string): Promise<string> {\n const cacheDirName = ensureCachePath(`others/${name}`);\n await fs.ensureDir(cacheDirName);\n return cacheDirName;\n}\n\n/**\n * Return the path of the private cache directory. This directory is wiped\n * between repositories, so they can be used to store private registries' index\n * without risk of that information leaking to other repositories/users.\n */\nexport function privateCacheDir(): string {\n // TODO: types (#22198)\n const cacheDir = GlobalConfig.get('cacheDir');\n return upath.join(cacheDir, '__renovate-private-cache');\n}\n\nexport async function localPathExists(pathName: string): Promise<boolean> {\n // Works for both files as well as directories\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.stat(path);\n return !!s;\n } catch {\n return false;\n }\n}\n\n/**\n * Validate local path without throwing.\n * @param path Path to check\n * @returns `true` if given `path` is a valid local path, otherwise `false`.\n */\nexport function isValidLocalPath(path: string): boolean {\n return isValidPath(path, 'localDir');\n}\n\n/**\n * Tries to find `otherFileName` in the directory where\n * `existingFileNameWithPath` is, then in its parent directory, then in the\n * grandparent, until we reach the top-level directory. All paths\n * must be relative to `localDir`.\n */\nexport async function findLocalSiblingOrParent(\n existingFileNameWithPath: string,\n otherFileName: string,\n): Promise<string | null> {\n if (upath.isAbsolute(existingFileNameWithPath)) {\n return null;\n }\n if (upath.isAbsolute(otherFileName)) {\n return null;\n }\n\n let current = existingFileNameWithPath;\n while (current !== '') {\n current = getParentDir(current);\n const candidate = upath.join(current, otherFileName);\n if (await localPathExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Get files by name from directory\n */\nexport async function readLocalDirectory(path: string): Promise<string[]> {\n const localPath = ensureLocalPath(path);\n const fileList = await fs.readdir(localPath);\n return fileList;\n}\n\nexport function createCacheWriteStream(path: string): fs.WriteStream {\n const fullPath = ensureCachePath(path);\n return fs.createWriteStream(fullPath);\n}\n\nexport function createCacheReadStream(path: string): fs.ReadStream {\n const fullPath = ensureCachePath(path);\n return fs.createReadStream(fullPath);\n}\n\nexport async function localPathIsFile(pathName: string): Promise<boolean> {\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.stat(path);\n return s.isFile();\n } catch {\n return false;\n }\n}\n\nexport async function localPathIsSymbolicLink(\n pathName: string,\n): Promise<boolean> {\n const path = ensureLocalPath(pathName);\n try {\n const s = await fs.lstat(path);\n return s.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * Find a file or directory by walking up parent directories within localDir\n */\n\nexport async function findUpLocal(\n fileName: string | string[],\n cwd: string,\n): Promise<string | null> {\n // TODO: types (#22198)\n const localDir = GlobalConfig.get('localDir');\n const absoluteCwd = upath.join(localDir, cwd);\n const normalizedAbsoluteCwd = upath.normalizeSafe(absoluteCwd);\n const res = await findUp(fileName, {\n cwd: normalizedAbsoluteCwd,\n type: 'file',\n });\n // Return null if nothing found\n if (!isNonEmptyString(res) || !isNonEmptyString(localDir)) {\n return null;\n }\n const safePath = upath.normalizeSafe(res);\n // Return relative path if file is inside of local dir\n if (safePath.startsWith(localDir)) {\n let relativePath = safePath.replace(localDir, '');\n // v8 ignore else -- TODO: add test #40625\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substring(1);\n }\n return relativePath;\n }\n // Return null if found file is outside of localDir\n return null;\n}\n\nexport function chmodLocalFile(\n fileName: string,\n mode: string | number,\n): Promise<void> {\n const fullFileName = ensureLocalPath(fileName);\n return fs.chmod(fullFileName, mode);\n}\n\nexport async function statLocalFile(\n fileName: string,\n): Promise<fs.Stats | null> {\n const fullFileName = ensureLocalPath(fileName);\n try {\n return await fs.stat(fullFileName);\n } catch {\n return null;\n }\n}\n\nexport async function statCacheFile(\n pathName: string,\n): Promise<fs.Stats | null> {\n const path = ensureCachePath(pathName);\n try {\n return await fs.stat(path);\n } catch {\n return null;\n }\n}\n\nexport function listCacheDir(\n path: string,\n options: { recursive: boolean } = { recursive: false },\n): Promise<string[]> {\n const fullPath = ensureCachePath(path);\n return fs.readdir(fullPath, {\n encoding: 'utf-8',\n recursive: options.recursive,\n });\n}\n\nexport async function rmCache(path: string): Promise<void> {\n const fullPath = ensureCachePath(path);\n // force: a missing path is a no-op, callers use this for cleanup\n await fs.rm(fullPath, { recursive: true, force: true });\n}\n\nexport async function cachePathExists(pathName: string): Promise<boolean> {\n const path = ensureCachePath(pathName);\n try {\n const s = await fs.stat(path);\n return !!s;\n } catch {\n return false;\n }\n}\n\nexport async function cachePathIsFile(pathName: string): Promise<boolean> {\n const path = ensureCachePath(pathName);\n try {\n const s = await fs.stat(path);\n return s.isFile();\n } catch {\n return false;\n }\n}\n\nexport async function readCacheFile(fileName: string): Promise<Buffer>;\nexport async function readCacheFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string>;\nexport function readCacheFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer> {\n const fullPath = ensureCachePath(fileName);\n return encoding ? fs.readFile(fullPath, encoding) : fs.readFile(fullPath);\n}\n\nexport function outputCacheFile(\n file: string,\n data: string | NodeJS.ArrayBufferView,\n): Promise<void> {\n const filePath = ensureCachePath(file);\n return fs.outputFile(filePath, data);\n}\n\nexport async function readSystemFile(fileName: string): Promise<Buffer>;\nexport async function readSystemFile(\n fileName: string,\n encoding: 'utf8',\n): Promise<string>;\nexport function readSystemFile(\n fileName: string,\n encoding?: BufferEncoding,\n): Promise<string | Buffer> {\n return encoding ? fs.readFile(fileName, encoding) : fs.readFile(fileName);\n}\n\nexport async function writeSystemFile(\n fileName: string,\n data: string | Buffer,\n): Promise<void> {\n await fs.outputFile(fileName, data);\n}\n\nexport async function getLocalFiles(\n fileNames: string[],\n): Promise<Record<string, string | null>> {\n const fileContentMap: Record<string, string | null> = {};\n\n for (const fileName of fileNames) {\n fileContentMap[fileName] = await readLocalFile(fileName, 'utf8');\n }\n\n return fileContentMap;\n}\n"],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  import { CONFIG_PRESETS_INVALID } from "../../../../constants/error-messages.js";
2
2
  import { setCustomEnv } from "../../../../util/env.js";
3
3
  import { setUserConfigFileNames } from "../../../../config/app-strings.js";
4
+ import { GlobalConfig, setHttpGlobalConfig } from "../../../../config/global.js";
4
5
  import { coerceArray } from "../../../../util/array.js";
5
6
  import { addSecretForSanitizing } from "../../../../util/sanitize.js";
6
7
  import { logger, setContext } from "../../../../logger/index.js";
8
+ import { clone } from "../../../../util/clone.js";
7
9
  import { ensureTrailingSlash } from "../../../../util/url.js";
8
10
  import { mergeChildConfig } from "../../../../config/utils.js";
11
+ import { add, clear } from "../../../../util/host-rules.js";
9
12
  import { resolveConfigPresets } from "../../../../config/presets/index.js";
10
13
  import { readSystemFile } from "../../../../util/fs/index.js";
11
14
  import { deleteNonDefaultConfig, getConfig } from "./file.js";
@@ -30,6 +33,42 @@ async function resolveGlobalExtends(globalExtends, ignorePresets) {
30
33
  throw new Error(CONFIG_PRESETS_INVALID);
31
34
  }
32
35
  }
36
+ /**
37
+ * Returns the administrator's `hostRules` whose secrets and variables can be applied yet, or none if a rule which restricts access cannot.
38
+ */
39
+ function getInterpolatedHostRules(config) {
40
+ const interpolated = [];
41
+ for (const rule of coerceArray(config.hostRules)) try {
42
+ const { hostRules } = applySecretsAndVariablesToConfig({
43
+ config: { hostRules: [clone(rule)] },
44
+ secrets: config.secrets,
45
+ variables: config.variables,
46
+ deleteSecrets: true,
47
+ deleteVariables: true
48
+ });
49
+ interpolated.push(...coerceArray(hostRules));
50
+ } catch (err) {
51
+ if (rule.allowInternal === false || rule.enabled === false) {
52
+ logger.debug({ err }, "Not applying hostRules to globalExtends, as a rule which restricts access cannot be resolved yet");
53
+ return [];
54
+ }
55
+ logger.debug({ err }, "Not applying a hostRule to globalExtends, as its secrets or variables cannot be resolved yet");
56
+ }
57
+ return interpolated;
58
+ }
59
+ /**
60
+ * Resolves `globalExtends` presets with the administrator's own `hostRules` and `internalHostAccess` in effect.
61
+ */
62
+ async function resolveGlobalExtendsAsAdmin(globalExtends, config) {
63
+ try {
64
+ setHttpGlobalConfig(config);
65
+ for (const rule of getInterpolatedHostRules(config)) add(rule, { trusted: true });
66
+ return await resolveGlobalExtends(globalExtends, config.ignorePresets);
67
+ } finally {
68
+ clear();
69
+ GlobalConfig.reset();
70
+ }
71
+ }
33
72
  async function parseConfigs(env, argv) {
34
73
  logger.debug("Parsing configs");
35
74
  const defaultConfig = getConfig$1();
@@ -44,7 +83,7 @@ async function parseConfigs(env, argv) {
44
83
  config = await setConfig(config);
45
84
  let resolvedGlobalExtends;
46
85
  if (isNonEmptyArray(config?.globalExtends)) {
47
- resolvedGlobalExtends = await resolveGlobalExtends(config.globalExtends, config.ignorePresets);
86
+ resolvedGlobalExtends = await resolveGlobalExtendsAsAdmin(config.globalExtends, config);
48
87
  config = mergeChildConfig(resolvedGlobalExtends, config);
49
88
  delete config.globalExtends;
50
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["defaultsParser.getConfig","fileParser.getConfig","additionalConfigFileParser.getConfig","cliParser.getConfig","envParser.getConfig","codespaces.setConfig","fileParser.deleteNonDefaultConfig","additionalConfigFileParser.deleteNonDefaultConfig"],"sources":["../../../../../lib/workers/global/config/parse/index.ts"],"sourcesContent":["import { isNonEmptyArray, isNonEmptyObject, isString } from '@sindresorhus/is';\nimport { setUserConfigFileNames } from '../../../../config/app-strings.ts';\nimport { setPrivateKeys } from '../../../../config/decrypt.ts';\nimport * as defaultsParser from '../../../../config/defaults.ts';\nimport { resolveConfigPresets } from '../../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../../config/secrets.ts';\nimport type { AllConfig } from '../../../../config/types.ts';\nimport { mergeChildConfig } from '../../../../config/utils.ts';\nimport { CONFIG_PRESETS_INVALID } from '../../../../constants/error-messages.ts';\nimport { logger, setContext } from '../../../../logger/index.ts';\nimport { coerceArray } from '../../../../util/array.ts';\nimport { setCustomEnv } from '../../../../util/env.ts';\nimport { readSystemFile } from '../../../../util/fs/index.ts';\nimport { addSecretForSanitizing } from '../../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../../util/url.ts';\nimport * as additionalConfigFileParser from './additional-config-file.ts';\nimport * as cliParser from './cli.ts';\nimport * as codespaces from './codespaces.ts';\nimport * as envParser from './env.ts';\nimport * as fileParser from './file.ts';\n\nexport async function resolveGlobalExtends(\n globalExtends: string[],\n ignorePresets?: string[],\n): Promise<AllConfig> {\n try {\n // Make a \"fake\" config to pass to resolveConfigPresets and resolve globalPresets\n const config = { extends: globalExtends, ignorePresets };\n const { config: resolvedConfig } = await resolveConfigPresets(config);\n return resolvedConfig;\n } catch (err) {\n logger.error({ err }, 'Error resolving config preset');\n throw new Error(CONFIG_PRESETS_INVALID);\n }\n}\n\nexport async function parseConfigs(\n env: NodeJS.ProcessEnv,\n argv: string[],\n): Promise<AllConfig> {\n logger.debug('Parsing configs');\n\n // Get configs\n const defaultConfig = defaultsParser.getConfig();\n const fileConfig = await fileParser.getConfig(env);\n const additionalFileConfig = await additionalConfigFileParser.getConfig(env);\n const cliConfig = cliParser.getConfig(argv);\n const envConfig = await envParser.getConfig(env);\n\n let config: AllConfig = mergeChildConfig(fileConfig, additionalFileConfig);\n // merge extends from file config and additional file config\n if (\n isNonEmptyArray(fileConfig.extends) &&\n isNonEmptyArray(additionalFileConfig.extends)\n ) {\n config.extends = [...fileConfig.extends, ...coerceArray(config.extends)];\n }\n config = mergeChildConfig(config, envConfig);\n config = mergeChildConfig(config, cliConfig);\n\n config = await codespaces.setConfig(config);\n\n let resolvedGlobalExtends: AllConfig | undefined;\n\n if (isNonEmptyArray(config?.globalExtends)) {\n // resolve global presets immediately\n resolvedGlobalExtends = await resolveGlobalExtends(\n config.globalExtends,\n config.ignorePresets,\n );\n config = mergeChildConfig(resolvedGlobalExtends, config);\n delete config.globalExtends;\n }\n\n const combinedConfig = config;\n\n config = mergeChildConfig(defaultConfig, config);\n\n if (config.forceCli) {\n const forcedCli = { ...cliConfig };\n delete forcedCli.token;\n delete forcedCli.hostRules;\n if (config.force) {\n config.force = { ...config.force, ...forcedCli };\n } else {\n config.force = forcedCli;\n }\n }\n\n if (!config.privateKey && config.privateKeyPath) {\n config.privateKey = await readSystemFile(config.privateKeyPath, 'utf8');\n delete config.privateKeyPath;\n }\n\n if (!config.privateKeyOld && config.privateKeyPathOld) {\n config.privateKeyOld = await readSystemFile(\n config.privateKeyPathOld,\n 'utf8',\n );\n delete config.privateKeyPathOld;\n }\n\n // Add private keys for sanitizing then set and delete them\n addSecretForSanitizing(config.privateKey, 'global');\n addSecretForSanitizing(config.privateKeyOld, 'global');\n setPrivateKeys(config.privateKey, config.privateKeyOld);\n delete config.privateKey;\n delete config.privateKeyOld;\n\n if (config.logContext) {\n // This only has an effect if logContext was defined via file or CLI, otherwise it would already have been detected in env\n setContext(config.logContext);\n }\n\n logger.trace({ config: defaultConfig }, 'Default config');\n logger.debug({ config: fileConfig }, 'File config');\n logger.debug({ config: additionalFileConfig }, 'Additional file config');\n logger.debug({ config: cliConfig }, 'CLI config');\n logger.debug({ config: envConfig }, 'Env config');\n logger.debug({ config: resolvedGlobalExtends }, 'Resolved global extends');\n logger.debug({ config: combinedConfig }, 'Combined config');\n\n // TODO #41551\n if (isNonEmptyArray(cliConfig.repositories)) {\n const existingRepos = [\n ...coerceArray(fileConfig.repositories),\n ...coerceArray(additionalFileConfig.repositories),\n ...coerceArray(envConfig.repositories),\n ];\n\n if (isNonEmptyArray(existingRepos)) {\n const allStrings = existingRepos.every((repo) => isString(repo));\n let shouldWarn = true;\n\n if (allStrings) {\n const areEqual =\n cliConfig.repositories.length === existingRepos.length &&\n cliConfig.repositories.every(\n (repo, idx) => repo === existingRepos[idx],\n );\n\n if (areEqual) {\n shouldWarn = false;\n }\n }\n\n if (shouldWarn) {\n logger.warn(\n 'CLI config is overridding the `repositories` config previously set',\n );\n }\n }\n }\n\n if (config.detectGlobalManagerConfig) {\n logger.debug('Detecting global manager config');\n const { detectAllGlobalConfig } =\n await import('../../../../modules/manager/index.ts');\n const globalManagerConfig = await detectAllGlobalConfig();\n logger.debug({ config: globalManagerConfig }, 'Global manager config');\n config = mergeChildConfig(config, globalManagerConfig);\n }\n\n if (config.detectHostRulesFromEnv) {\n const { hostRulesFromEnv } = await import('./host-rules-from-env.ts');\n const hostRules = hostRulesFromEnv(env);\n config.hostRules = [...coerceArray(config.hostRules), ...hostRules];\n }\n // Get global config\n logger.trace({ config }, 'Full config');\n\n // Massage endpoint to have a trailing slash\n if (config.endpoint) {\n logger.debug('Adding trailing slash to endpoint');\n config.endpoint = ensureTrailingSlash(config.endpoint);\n }\n\n // Massage forkProcessing\n if (!config.autodiscover && config.forkProcessing !== 'disabled') {\n logger.debug('Enabling forkProcessing while in non-autodiscover mode');\n config.forkProcessing = 'enabled';\n }\n\n // Only try deletion if RENOVATE_CONFIG_FILE is set\n await fileParser.deleteNonDefaultConfig(env, !!config.deleteConfigFile);\n\n // Only try deletion if RENOVATE_ADDITIONAL_CONFIG_FILE is set\n await additionalConfigFileParser.deleteNonDefaultConfig(\n env,\n !!config.deleteAdditionalConfigFile,\n );\n\n // Massage onboardingNoDeps\n if (!config.autodiscover && config.onboardingNoDeps !== 'disabled') {\n logger.debug('Enabling onboardingNoDeps while in non-autodiscover mode');\n config.onboardingNoDeps = 'enabled';\n }\n\n // do not add these secrets to repoSecrets and,\n // do not delete the secrets/variables object after applying on global config as it needs to be re-used for repo config\n if (isNonEmptyObject(config.secrets) || isNonEmptyObject(config.variables)) {\n config = applySecretsAndVariablesToConfig({\n config,\n secrets: config.secrets,\n variables: config.variables,\n deleteSecrets: false,\n deleteVariables: false,\n });\n // adding these secrets to the globalSecrets set so that they can be redacted from logs\n for (const secret of Object.values(config.secrets!)) {\n addSecretForSanitizing(secret, 'global');\n }\n }\n\n if (isNonEmptyObject(config.customEnvVariables)) {\n setCustomEnv(config.customEnvVariables);\n }\n\n if (isNonEmptyArray(config.configFileNames)) {\n logger.debug(\n { configFileNames: config.configFileNames },\n 'Updated the config filenames list',\n );\n setUserConfigFileNames(config.configFileNames);\n delete config.configFileNames;\n }\n\n return config;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["defaultsParser.getConfig","fileParser.getConfig","additionalConfigFileParser.getConfig","cliParser.getConfig","envParser.getConfig","codespaces.setConfig","fileParser.deleteNonDefaultConfig","additionalConfigFileParser.deleteNonDefaultConfig"],"sources":["../../../../../lib/workers/global/config/parse/index.ts"],"sourcesContent":["import { isNonEmptyArray, isNonEmptyObject, isString } from '@sindresorhus/is';\nimport { setUserConfigFileNames } from '../../../../config/app-strings.ts';\nimport { setPrivateKeys } from '../../../../config/decrypt.ts';\nimport * as defaultsParser from '../../../../config/defaults.ts';\nimport {\n GlobalConfig,\n setHttpGlobalConfig,\n} from '../../../../config/global.ts';\nimport { resolveConfigPresets } from '../../../../config/presets/index.ts';\nimport { applySecretsAndVariablesToConfig } from '../../../../config/secrets.ts';\nimport type { AllConfig } from '../../../../config/types.ts';\nimport { mergeChildConfig } from '../../../../config/utils.ts';\nimport { CONFIG_PRESETS_INVALID } from '../../../../constants/error-messages.ts';\nimport { logger, setContext } from '../../../../logger/index.ts';\nimport type { HostRule } from '../../../../types/host-rules.ts';\nimport { coerceArray } from '../../../../util/array.ts';\nimport { clone } from '../../../../util/clone.ts';\nimport { setCustomEnv } from '../../../../util/env.ts';\nimport { readSystemFile } from '../../../../util/fs/index.ts';\nimport {\n add as addHostRule,\n clear as clearHostRules,\n} from '../../../../util/host-rules.ts';\nimport { addSecretForSanitizing } from '../../../../util/sanitize.ts';\nimport { ensureTrailingSlash } from '../../../../util/url.ts';\nimport * as additionalConfigFileParser from './additional-config-file.ts';\nimport * as cliParser from './cli.ts';\nimport * as codespaces from './codespaces.ts';\nimport * as envParser from './env.ts';\nimport * as fileParser from './file.ts';\n\nexport async function resolveGlobalExtends(\n globalExtends: string[],\n ignorePresets?: string[],\n): Promise<AllConfig> {\n try {\n // Make a \"fake\" config to pass to resolveConfigPresets and resolve globalPresets\n const config = { extends: globalExtends, ignorePresets };\n const { config: resolvedConfig } = await resolveConfigPresets(config);\n return resolvedConfig;\n } catch (err) {\n logger.error({ err }, 'Error resolving config preset');\n throw new Error(CONFIG_PRESETS_INVALID);\n }\n}\n\n/**\n * Returns the administrator's `hostRules` whose secrets and variables can be applied yet, or none if a rule which restricts access cannot.\n */\nfunction getInterpolatedHostRules(config: AllConfig): HostRule[] {\n const interpolated: HostRule[] = [];\n for (const rule of coerceArray(config.hostRules)) {\n try {\n const { hostRules } = applySecretsAndVariablesToConfig({\n config: { hostRules: [clone(rule)] },\n secrets: config.secrets,\n variables: config.variables,\n deleteSecrets: true,\n deleteVariables: true,\n });\n interpolated.push(...coerceArray(hostRules));\n } catch (err) {\n // skipping only this rule would let a broader rule apply where it was meant to restrict, so apply none of them, as before admin `hostRules` were applied here\n if (rule.allowInternal === false || rule.enabled === false) {\n logger.debug(\n { err },\n 'Not applying hostRules to globalExtends, as a rule which restricts access cannot be resolved yet',\n );\n return [];\n }\n logger.debug(\n { err },\n 'Not applying a hostRule to globalExtends, as its secrets or variables cannot be resolved yet',\n );\n }\n }\n return interpolated;\n}\n\n/**\n * Resolves `globalExtends` presets with the administrator's own `hostRules` and `internalHostAccess` in effect.\n */\nasync function resolveGlobalExtendsAsAdmin(\n globalExtends: string[],\n config: AllConfig,\n): Promise<AllConfig> {\n // `globalExtends` is fetched before `start()` sets `GlobalConfig` and `globalInitialize()` registers `hostRules`, so the administrator's own `internalHostAccess`, `endpoint` and `hostRules` are applied for the duration of that fetch only - `globalInitialize()` then registers the final, merged `hostRules`\n try {\n setHttpGlobalConfig(config);\n for (const rule of getInterpolatedHostRules(config)) {\n // the same `trusted` tier as `setGlobalHostRules()`, so that `allowInternal` is kept and can grant\n addHostRule(rule, { trusted: true });\n }\n return await resolveGlobalExtends(globalExtends, config.ignorePresets);\n } finally {\n clearHostRules();\n GlobalConfig.reset();\n }\n}\n\nexport async function parseConfigs(\n env: NodeJS.ProcessEnv,\n argv: string[],\n): Promise<AllConfig> {\n logger.debug('Parsing configs');\n\n // Get configs\n const defaultConfig = defaultsParser.getConfig();\n const fileConfig = await fileParser.getConfig(env);\n const additionalFileConfig = await additionalConfigFileParser.getConfig(env);\n const cliConfig = cliParser.getConfig(argv);\n const envConfig = await envParser.getConfig(env);\n\n let config: AllConfig = mergeChildConfig(fileConfig, additionalFileConfig);\n // merge extends from file config and additional file config\n if (\n isNonEmptyArray(fileConfig.extends) &&\n isNonEmptyArray(additionalFileConfig.extends)\n ) {\n config.extends = [...fileConfig.extends, ...coerceArray(config.extends)];\n }\n config = mergeChildConfig(config, envConfig);\n config = mergeChildConfig(config, cliConfig);\n\n config = await codespaces.setConfig(config);\n\n let resolvedGlobalExtends: AllConfig | undefined;\n\n if (isNonEmptyArray(config?.globalExtends)) {\n // resolve global presets immediately\n resolvedGlobalExtends = await resolveGlobalExtendsAsAdmin(\n config.globalExtends,\n config,\n );\n config = mergeChildConfig(resolvedGlobalExtends, config);\n delete config.globalExtends;\n }\n\n const combinedConfig = config;\n\n config = mergeChildConfig(defaultConfig, config);\n\n if (config.forceCli) {\n const forcedCli = { ...cliConfig };\n delete forcedCli.token;\n delete forcedCli.hostRules;\n if (config.force) {\n config.force = { ...config.force, ...forcedCli };\n } else {\n config.force = forcedCli;\n }\n }\n\n if (!config.privateKey && config.privateKeyPath) {\n config.privateKey = await readSystemFile(config.privateKeyPath, 'utf8');\n delete config.privateKeyPath;\n }\n\n if (!config.privateKeyOld && config.privateKeyPathOld) {\n config.privateKeyOld = await readSystemFile(\n config.privateKeyPathOld,\n 'utf8',\n );\n delete config.privateKeyPathOld;\n }\n\n // Add private keys for sanitizing then set and delete them\n addSecretForSanitizing(config.privateKey, 'global');\n addSecretForSanitizing(config.privateKeyOld, 'global');\n setPrivateKeys(config.privateKey, config.privateKeyOld);\n delete config.privateKey;\n delete config.privateKeyOld;\n\n if (config.logContext) {\n // This only has an effect if logContext was defined via file or CLI, otherwise it would already have been detected in env\n setContext(config.logContext);\n }\n\n logger.trace({ config: defaultConfig }, 'Default config');\n logger.debug({ config: fileConfig }, 'File config');\n logger.debug({ config: additionalFileConfig }, 'Additional file config');\n logger.debug({ config: cliConfig }, 'CLI config');\n logger.debug({ config: envConfig }, 'Env config');\n logger.debug({ config: resolvedGlobalExtends }, 'Resolved global extends');\n logger.debug({ config: combinedConfig }, 'Combined config');\n\n // TODO #41551\n if (isNonEmptyArray(cliConfig.repositories)) {\n const existingRepos = [\n ...coerceArray(fileConfig.repositories),\n ...coerceArray(additionalFileConfig.repositories),\n ...coerceArray(envConfig.repositories),\n ];\n\n if (isNonEmptyArray(existingRepos)) {\n const allStrings = existingRepos.every((repo) => isString(repo));\n let shouldWarn = true;\n\n if (allStrings) {\n const areEqual =\n cliConfig.repositories.length === existingRepos.length &&\n cliConfig.repositories.every(\n (repo, idx) => repo === existingRepos[idx],\n );\n\n if (areEqual) {\n shouldWarn = false;\n }\n }\n\n if (shouldWarn) {\n logger.warn(\n 'CLI config is overridding the `repositories` config previously set',\n );\n }\n }\n }\n\n if (config.detectGlobalManagerConfig) {\n logger.debug('Detecting global manager config');\n const { detectAllGlobalConfig } =\n await import('../../../../modules/manager/index.ts');\n const globalManagerConfig = await detectAllGlobalConfig();\n logger.debug({ config: globalManagerConfig }, 'Global manager config');\n config = mergeChildConfig(config, globalManagerConfig);\n }\n\n if (config.detectHostRulesFromEnv) {\n const { hostRulesFromEnv } = await import('./host-rules-from-env.ts');\n const hostRules = hostRulesFromEnv(env);\n config.hostRules = [...coerceArray(config.hostRules), ...hostRules];\n }\n // Get global config\n logger.trace({ config }, 'Full config');\n\n // Massage endpoint to have a trailing slash\n if (config.endpoint) {\n logger.debug('Adding trailing slash to endpoint');\n config.endpoint = ensureTrailingSlash(config.endpoint);\n }\n\n // Massage forkProcessing\n if (!config.autodiscover && config.forkProcessing !== 'disabled') {\n logger.debug('Enabling forkProcessing while in non-autodiscover mode');\n config.forkProcessing = 'enabled';\n }\n\n // Only try deletion if RENOVATE_CONFIG_FILE is set\n await fileParser.deleteNonDefaultConfig(env, !!config.deleteConfigFile);\n\n // Only try deletion if RENOVATE_ADDITIONAL_CONFIG_FILE is set\n await additionalConfigFileParser.deleteNonDefaultConfig(\n env,\n !!config.deleteAdditionalConfigFile,\n );\n\n // Massage onboardingNoDeps\n if (!config.autodiscover && config.onboardingNoDeps !== 'disabled') {\n logger.debug('Enabling onboardingNoDeps while in non-autodiscover mode');\n config.onboardingNoDeps = 'enabled';\n }\n\n // do not add these secrets to repoSecrets and,\n // do not delete the secrets/variables object after applying on global config as it needs to be re-used for repo config\n if (isNonEmptyObject(config.secrets) || isNonEmptyObject(config.variables)) {\n config = applySecretsAndVariablesToConfig({\n config,\n secrets: config.secrets,\n variables: config.variables,\n deleteSecrets: false,\n deleteVariables: false,\n });\n // adding these secrets to the globalSecrets set so that they can be redacted from logs\n for (const secret of Object.values(config.secrets!)) {\n addSecretForSanitizing(secret, 'global');\n }\n }\n\n if (isNonEmptyObject(config.customEnvVariables)) {\n setCustomEnv(config.customEnvVariables);\n }\n\n if (isNonEmptyArray(config.configFileNames)) {\n logger.debug(\n { configFileNames: config.configFileNames },\n 'Updated the config filenames list',\n );\n setUserConfigFileNames(config.configFileNames);\n delete config.configFileNames;\n }\n\n return config;\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { CONFIG_PRESETS_INVALID } from "../../constants/error-messages.js";
2
2
  import { pkg } from "../../expose.js";
3
3
  import { getEnv } from "../../util/env.js";
4
4
  import { regexEngineStatus } from "../../util/regex.js";
5
- import { GlobalConfig } from "../../config/global.js";
5
+ import { GlobalConfig, setHttpGlobalConfig } from "../../config/global.js";
6
6
  import { setGlobalLogLevelRemaps } from "../../logger/remap.js";
7
7
  import { coerceString } from "../../util/string.js";
8
8
  import { addSecretForSanitizing } from "../../util/sanitize.js";
@@ -100,21 +100,9 @@ async function start() {
100
100
  if (isNonEmptyStringAndNotWhitespace(env.COREPACK_NPM_PASSWORD)) addSecretForSanitizing(env.COREPACK_NPM_PASSWORD, "global");
101
101
  await instrument("config", async () => {
102
102
  config = await getGlobalConfig();
103
- GlobalConfig.set({
104
- allowedHeaders: config.allowedHeaders,
105
- endpoint: config.endpoint,
106
- internalHostAccess: config.internalHostAccess,
107
- platform: config.platform,
108
- userAgent: config.userAgent
109
- });
103
+ setHttpGlobalConfig(config);
110
104
  config = await globalInitialize(config);
111
- GlobalConfig.set({
112
- allowedHeaders: config.allowedHeaders,
113
- platform: config.platform,
114
- endpoint: config.endpoint,
115
- internalHostAccess: config.internalHostAccess,
116
- userAgent: config.userAgent
117
- });
105
+ setHttpGlobalConfig(config);
118
106
  await validatePresets(config);
119
107
  setGlobalLogLevelRemaps(config.logLevelRemap);
120
108
  checkEnv();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["configParser.filterConfig","repositoryWorker.renovateRepository"],"sources":["../../../lib/workers/global/index.ts"],"sourcesContent":["import {\n ATTR_VCS_OWNER_NAME,\n ATTR_VCS_PROVIDER_NAME,\n ATTR_VCS_REPOSITORY_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport {\n isNonEmptyObject,\n isNonEmptyString,\n isNonEmptyStringAndNotWhitespace,\n isString,\n} from '@sindresorhus/is';\nimport { ERROR } from 'bunyan';\nimport fs from 'fs-extra';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../config/global.ts';\nimport * as configParser from '../../config/index.ts';\nimport { resolveConfigPresets } from '../../config/presets/index.ts';\nimport { validateConfigSecretsAndVariables } from '../../config/secrets.ts';\nimport type {\n AllConfig,\n InternalGlobalConfigOptions,\n RenovateConfig,\n RenovateRepository,\n RepoGlobalConfig,\n} from '../../config/types.ts';\nimport { CONFIG_PRESETS_INVALID } from '../../constants/error-messages.ts';\nimport { pkg } from '../../expose.ts';\nimport { instrument } from '../../instrumentation/index.ts';\nimport {\n exportStats,\n finalizeReport,\n} from '../../instrumentation/reporting.ts';\nimport { getProblems, logLevel, logger, setMeta } from '../../logger/index.ts';\nimport { setGlobalLogLevelRemaps } from '../../logger/remap.ts';\nimport { getEnv } from '../../util/env.ts';\nimport * as hostRules from '../../util/host-rules.ts';\nimport * as queue from '../../util/http/queue.ts';\nimport * as throttle from '../../util/http/throttle.ts';\nimport { regexEngineStatus } from '../../util/regex.ts';\nimport { addSecretForSanitizing } from '../../util/sanitize.ts';\nimport { coerceString } from '../../util/string.ts';\nimport * as repositoryWorker from '../repository/index.ts';\nimport type { RepositoryWorkerConfig } from '../repository/init/types.ts';\nimport { autodiscoverRepositories } from './autodiscover.ts';\nimport { parseConfigs } from './config/parse/index.ts';\nimport { globalFinalize, globalInitialize } from './initialize.ts';\nimport { isLimitReached } from './limits.ts';\n\nfunction applyGlobalOption<\n K extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n>(\n target: RepoGlobalConfig & InternalGlobalConfigOptions,\n source: RepoGlobalConfig & InternalGlobalConfigOptions,\n key: K,\n): void {\n target[key] = source[key];\n delete source[key];\n}\n\nexport async function getRepositoryConfig(\n globalConfig: RenovateConfig,\n repository: RenovateRepository,\n): Promise<RepositoryWorkerConfig> {\n const repoIsString = isString(repository);\n const repoName = repoIsString ? repository : repository.repository;\n\n const repoConfig: RepositoryWorkerConfig = {\n ...globalConfig,\n repository: repoName,\n };\n\n if (!repoIsString) {\n const { repository: _repository, ...repositoryEntryConfig } = repository;\n\n // Promote GlobalConfig.OPTIONS keys into repoConfig directly so that\n // GlobalConfig.set(repoConfig) in the repository worker picks them up\n // with per-repo overrides before onboarding checks run.\n for (const option of GlobalConfig.OPTIONS) {\n if (option in repositoryEntryConfig) {\n applyGlobalOption(repoConfig, repositoryEntryConfig, option);\n }\n }\n\n if (isNonEmptyObject(repositoryEntryConfig)) {\n // mergeRenovateConfig later resolves this repositories[] object-entry\n // config in the correct order\n repoConfig.repositoryEntryConfig = repositoryEntryConfig;\n }\n }\n\n const repoParts = repoName.split('/');\n repoParts.pop();\n repoConfig.parentOrg = repoParts.join('/');\n repoConfig.topLevelOrg = repoParts.shift();\n const platform = GlobalConfig.get('platform');\n repoConfig.localDir =\n platform === 'local'\n ? process.cwd()\n : // TODO: types (#22198)\n upath.join(repoConfig.baseDir!, `./repos/${platform}/${repoName}`);\n await fs.ensureDir(repoConfig.localDir);\n delete repoConfig.baseDir;\n return configParser.filterConfig(repoConfig, 'repository');\n}\n\nfunction getGlobalConfig(): Promise<RenovateConfig> {\n return parseConfigs(getEnv(), process.argv);\n}\n\nfunction haveReachedLimits(): boolean {\n if (isLimitReached('Commits')) {\n logger.info('Max commits created for this run.');\n return true;\n }\n return false;\n}\n\n/* istanbul ignore next */\nfunction checkEnv(): void {\n const range = pkg.engines.node;\n if (process.release?.name !== 'node' || !process.versions?.node) {\n logger.warn(\n { release: process.release, versions: process.versions },\n 'Unknown node environment detected.',\n );\n } else if (!semver.satisfies(process.versions?.node, range)) {\n logger.error(\n { versions: process.versions, range },\n 'Unsupported node environment detected. Please update your node version.',\n );\n }\n}\n\nexport async function validatePresets(config: AllConfig): Promise<void> {\n logger.debug('validatePresets()');\n try {\n await resolveConfigPresets(config);\n } catch (err) /* istanbul ignore next */ {\n logger.error({ err }, CONFIG_PRESETS_INVALID);\n throw new Error(CONFIG_PRESETS_INVALID);\n }\n}\n\nexport async function start(): Promise<number> {\n logger.info({ renovateVersion: pkg.version }, 'Renovate started');\n // istanbul ignore next\n if (regexEngineStatus.type === 'available') {\n logger.debug('Using RE2 regex engine');\n } else if (regexEngineStatus.type === 'unavailable') {\n logger.warn(\n { err: regexEngineStatus.err },\n 'RE2 not usable, falling back to RegExp',\n );\n } else if (regexEngineStatus.type === 'ignored') {\n logger.debug('RE2 regex engine is ignored via RENOVATE_X_IGNORE_RE2');\n }\n\n let config: AllConfig;\n let repoExitCode = 0;\n const env = getEnv();\n try {\n if (isNonEmptyStringAndNotWhitespace(env.AWS_SECRET_ACCESS_KEY)) {\n addSecretForSanitizing(env.AWS_SECRET_ACCESS_KEY, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.AWS_SESSION_TOKEN)) {\n addSecretForSanitizing(env.AWS_SESSION_TOKEN, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.COREPACK_NPM_TOKEN)) {\n addSecretForSanitizing(env.COREPACK_NPM_TOKEN, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.COREPACK_NPM_PASSWORD)) {\n addSecretForSanitizing(env.COREPACK_NPM_PASSWORD, 'global');\n }\n\n await instrument('config', async () => {\n // read global config from file, env and cli args\n config = await getGlobalConfig();\n\n // Set allowedHeaders and userAgent in case hostRules headers are configured in file config\n // `platform`, `endpoint` and `internalHostAccess` are set here too, so that the platform's own initialization requests - which happen inside `globalInitialize()`, before the config below is set - are judged by the administrator's `internalHostAccess` setting, and are recognized as going to the platform endpoint\n GlobalConfig.set({\n allowedHeaders: config.allowedHeaders,\n endpoint: config.endpoint,\n internalHostAccess: config.internalHostAccess,\n platform: config.platform,\n userAgent: config.userAgent,\n });\n // initialize all submodules\n config = await globalInitialize(config);\n\n // Set platform, endpoint, allowedHeaders and userAgent in case local presets are used, now that platform initialization may have changed them\n GlobalConfig.set({\n allowedHeaders: config.allowedHeaders,\n platform: config.platform,\n endpoint: config.endpoint,\n internalHostAccess: config.internalHostAccess,\n userAgent: config.userAgent,\n });\n\n await validatePresets(config);\n\n setGlobalLogLevelRemaps(config.logLevelRemap);\n\n checkEnv();\n\n // validate secrets and variables. Will throw and abort if invalid\n validateConfigSecretsAndVariables(config);\n });\n\n // autodiscover repositories (needs to come after platform initialization)\n config = await instrument('discover', () =>\n autodiscoverRepositories(config),\n );\n\n if (isNonEmptyString(config.writeDiscoveredRepos)) {\n const content = JSON.stringify(config.repositories);\n await fs.writeFile(config.writeDiscoveredRepos, content);\n logger.info(\n `Written discovered repositories to ${config.writeDiscoveredRepos}`,\n );\n return 0;\n }\n\n // Iterate through repositories sequentially\n for (const repository of config.repositories!) {\n if (haveReachedLimits()) {\n break;\n }\n\n const { owner, repo } = repositoryToOwnerAndRepo(\n isString(repository) ? repository : repository.repository,\n );\n\n await instrument(\n 'repository',\n async () => {\n const repoConfig = await getRepositoryConfig(config, repository);\n if (repoConfig.hostRules) {\n logger.debug('Reinitializing hostRules for repo');\n hostRules.clear();\n for (const rule of repoConfig.hostRules) {\n // the self-hosted admin's own rules: `trusted`, so that their `headers` are applied over any a repository or preset sets for the same host, and exempt from `allowedHeaders` altogether\n hostRules.add(rule, { trusted: true });\n }\n repoConfig.hostRules = [];\n }\n\n // host rules can change concurrency\n queue.clear();\n throttle.clear();\n\n const repoResult =\n await repositoryWorker.renovateRepository(repoConfig);\n if (config.exitCodeForErrors && !repoExitCode) {\n repoExitCode = repoResult?.exitCode ?? 0;\n }\n setMeta({});\n },\n {\n attributes: {\n [ATTR_VCS_PROVIDER_NAME]: config.platform,\n [ATTR_VCS_OWNER_NAME]: owner,\n [ATTR_VCS_REPOSITORY_NAME]: repo,\n /** @deprecated TODO remove */\n repository: isString(repository)\n ? repository\n : repository.repository,\n },\n },\n );\n }\n\n finalizeReport();\n await exportStats(config);\n } catch (err) /* istanbul ignore next */ {\n if (err.message.startsWith('Init: ')) {\n logger.fatal(\n { errorMessage: err.message.substring(6) },\n 'Initialization error',\n );\n } else {\n logger.fatal({ err }, 'Unknown error');\n }\n if (!config!) {\n // return early if we can't parse config options\n logger.debug(`Missing config`);\n return 2;\n }\n } finally {\n await globalFinalize(config!);\n if (logLevel() === 'info') {\n logger.info(\n `Renovate was run at log level \"${logLevel()}\". Set LOG_LEVEL=debug in environment variables to see extended debug logs.`,\n );\n }\n }\n if (repoExitCode) {\n logger.info(\n { exitCode: repoExitCode },\n 'Renovate is exiting with an error-specific code due to a repository error',\n );\n return repoExitCode;\n }\n const loggerErrors = getProblems().filter((p) => p.level >= ERROR);\n if (loggerErrors.length) {\n logger.info(\n { loggerErrors },\n 'Renovate is exiting with a non-zero code due to the following logged errors',\n );\n return 1;\n }\n return 0;\n}\n\nfunction repositoryToOwnerAndRepo(fullName: string): {\n owner: string;\n repo: string;\n} {\n const parts = fullName.split('/');\n const repo = coerceString(parts.pop());\n const owner = parts.join('/');\n return { owner, repo };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["configParser.filterConfig","repositoryWorker.renovateRepository"],"sources":["../../../lib/workers/global/index.ts"],"sourcesContent":["import {\n ATTR_VCS_OWNER_NAME,\n ATTR_VCS_PROVIDER_NAME,\n ATTR_VCS_REPOSITORY_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport {\n isNonEmptyObject,\n isNonEmptyString,\n isNonEmptyStringAndNotWhitespace,\n isString,\n} from '@sindresorhus/is';\nimport { ERROR } from 'bunyan';\nimport fs from 'fs-extra';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { GlobalConfig, setHttpGlobalConfig } from '../../config/global.ts';\nimport * as configParser from '../../config/index.ts';\nimport { resolveConfigPresets } from '../../config/presets/index.ts';\nimport { validateConfigSecretsAndVariables } from '../../config/secrets.ts';\nimport type {\n AllConfig,\n InternalGlobalConfigOptions,\n RenovateConfig,\n RenovateRepository,\n RepoGlobalConfig,\n} from '../../config/types.ts';\nimport { CONFIG_PRESETS_INVALID } from '../../constants/error-messages.ts';\nimport { pkg } from '../../expose.ts';\nimport { instrument } from '../../instrumentation/index.ts';\nimport {\n exportStats,\n finalizeReport,\n} from '../../instrumentation/reporting.ts';\nimport { getProblems, logLevel, logger, setMeta } from '../../logger/index.ts';\nimport { setGlobalLogLevelRemaps } from '../../logger/remap.ts';\nimport { getEnv } from '../../util/env.ts';\nimport * as hostRules from '../../util/host-rules.ts';\nimport * as queue from '../../util/http/queue.ts';\nimport * as throttle from '../../util/http/throttle.ts';\nimport { regexEngineStatus } from '../../util/regex.ts';\nimport { addSecretForSanitizing } from '../../util/sanitize.ts';\nimport { coerceString } from '../../util/string.ts';\nimport * as repositoryWorker from '../repository/index.ts';\nimport type { RepositoryWorkerConfig } from '../repository/init/types.ts';\nimport { autodiscoverRepositories } from './autodiscover.ts';\nimport { parseConfigs } from './config/parse/index.ts';\nimport { globalFinalize, globalInitialize } from './initialize.ts';\nimport { isLimitReached } from './limits.ts';\n\nfunction applyGlobalOption<\n K extends keyof RepoGlobalConfig | keyof InternalGlobalConfigOptions,\n>(\n target: RepoGlobalConfig & InternalGlobalConfigOptions,\n source: RepoGlobalConfig & InternalGlobalConfigOptions,\n key: K,\n): void {\n target[key] = source[key];\n delete source[key];\n}\n\nexport async function getRepositoryConfig(\n globalConfig: RenovateConfig,\n repository: RenovateRepository,\n): Promise<RepositoryWorkerConfig> {\n const repoIsString = isString(repository);\n const repoName = repoIsString ? repository : repository.repository;\n\n const repoConfig: RepositoryWorkerConfig = {\n ...globalConfig,\n repository: repoName,\n };\n\n if (!repoIsString) {\n const { repository: _repository, ...repositoryEntryConfig } = repository;\n\n // Promote GlobalConfig.OPTIONS keys into repoConfig directly so that\n // GlobalConfig.set(repoConfig) in the repository worker picks them up\n // with per-repo overrides before onboarding checks run.\n for (const option of GlobalConfig.OPTIONS) {\n if (option in repositoryEntryConfig) {\n applyGlobalOption(repoConfig, repositoryEntryConfig, option);\n }\n }\n\n if (isNonEmptyObject(repositoryEntryConfig)) {\n // mergeRenovateConfig later resolves this repositories[] object-entry\n // config in the correct order\n repoConfig.repositoryEntryConfig = repositoryEntryConfig;\n }\n }\n\n const repoParts = repoName.split('/');\n repoParts.pop();\n repoConfig.parentOrg = repoParts.join('/');\n repoConfig.topLevelOrg = repoParts.shift();\n const platform = GlobalConfig.get('platform');\n repoConfig.localDir =\n platform === 'local'\n ? process.cwd()\n : // TODO: types (#22198)\n upath.join(repoConfig.baseDir!, `./repos/${platform}/${repoName}`);\n await fs.ensureDir(repoConfig.localDir);\n delete repoConfig.baseDir;\n return configParser.filterConfig(repoConfig, 'repository');\n}\n\nfunction getGlobalConfig(): Promise<RenovateConfig> {\n return parseConfigs(getEnv(), process.argv);\n}\n\nfunction haveReachedLimits(): boolean {\n if (isLimitReached('Commits')) {\n logger.info('Max commits created for this run.');\n return true;\n }\n return false;\n}\n\n/* istanbul ignore next */\nfunction checkEnv(): void {\n const range = pkg.engines.node;\n if (process.release?.name !== 'node' || !process.versions?.node) {\n logger.warn(\n { release: process.release, versions: process.versions },\n 'Unknown node environment detected.',\n );\n } else if (!semver.satisfies(process.versions?.node, range)) {\n logger.error(\n { versions: process.versions, range },\n 'Unsupported node environment detected. Please update your node version.',\n );\n }\n}\n\nexport async function validatePresets(config: AllConfig): Promise<void> {\n logger.debug('validatePresets()');\n try {\n await resolveConfigPresets(config);\n } catch (err) /* istanbul ignore next */ {\n logger.error({ err }, CONFIG_PRESETS_INVALID);\n throw new Error(CONFIG_PRESETS_INVALID);\n }\n}\n\nexport async function start(): Promise<number> {\n logger.info({ renovateVersion: pkg.version }, 'Renovate started');\n // istanbul ignore next\n if (regexEngineStatus.type === 'available') {\n logger.debug('Using RE2 regex engine');\n } else if (regexEngineStatus.type === 'unavailable') {\n logger.warn(\n { err: regexEngineStatus.err },\n 'RE2 not usable, falling back to RegExp',\n );\n } else if (regexEngineStatus.type === 'ignored') {\n logger.debug('RE2 regex engine is ignored via RENOVATE_X_IGNORE_RE2');\n }\n\n let config: AllConfig;\n let repoExitCode = 0;\n const env = getEnv();\n try {\n if (isNonEmptyStringAndNotWhitespace(env.AWS_SECRET_ACCESS_KEY)) {\n addSecretForSanitizing(env.AWS_SECRET_ACCESS_KEY, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.AWS_SESSION_TOKEN)) {\n addSecretForSanitizing(env.AWS_SESSION_TOKEN, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.COREPACK_NPM_TOKEN)) {\n addSecretForSanitizing(env.COREPACK_NPM_TOKEN, 'global');\n }\n if (isNonEmptyStringAndNotWhitespace(env.COREPACK_NPM_PASSWORD)) {\n addSecretForSanitizing(env.COREPACK_NPM_PASSWORD, 'global');\n }\n\n await instrument('config', async () => {\n // read global config from file, env and cli args\n config = await getGlobalConfig();\n\n // set before `globalInitialize()`, so that `hostRules` headers from file config are checked against `allowedHeaders`, and the platform's own initialization requests are judged by the administrator's `internalHostAccess` setting and recognized as going to the platform endpoint\n setHttpGlobalConfig(config);\n // initialize all submodules\n config = await globalInitialize(config);\n\n // set again in case local presets are used, now that platform initialization may have changed `platform` and `endpoint`\n setHttpGlobalConfig(config);\n\n await validatePresets(config);\n\n setGlobalLogLevelRemaps(config.logLevelRemap);\n\n checkEnv();\n\n // validate secrets and variables. Will throw and abort if invalid\n validateConfigSecretsAndVariables(config);\n });\n\n // autodiscover repositories (needs to come after platform initialization)\n config = await instrument('discover', () =>\n autodiscoverRepositories(config),\n );\n\n if (isNonEmptyString(config.writeDiscoveredRepos)) {\n const content = JSON.stringify(config.repositories);\n await fs.writeFile(config.writeDiscoveredRepos, content);\n logger.info(\n `Written discovered repositories to ${config.writeDiscoveredRepos}`,\n );\n return 0;\n }\n\n // Iterate through repositories sequentially\n for (const repository of config.repositories!) {\n if (haveReachedLimits()) {\n break;\n }\n\n const { owner, repo } = repositoryToOwnerAndRepo(\n isString(repository) ? repository : repository.repository,\n );\n\n await instrument(\n 'repository',\n async () => {\n const repoConfig = await getRepositoryConfig(config, repository);\n if (repoConfig.hostRules) {\n logger.debug('Reinitializing hostRules for repo');\n hostRules.clear();\n for (const rule of repoConfig.hostRules) {\n // the self-hosted admin's own rules: `trusted`, so that their `headers` are applied over any a repository or preset sets for the same host, and exempt from `allowedHeaders` altogether\n hostRules.add(rule, { trusted: true });\n }\n repoConfig.hostRules = [];\n }\n\n // host rules can change concurrency\n queue.clear();\n throttle.clear();\n\n const repoResult =\n await repositoryWorker.renovateRepository(repoConfig);\n if (config.exitCodeForErrors && !repoExitCode) {\n repoExitCode = repoResult?.exitCode ?? 0;\n }\n setMeta({});\n },\n {\n attributes: {\n [ATTR_VCS_PROVIDER_NAME]: config.platform,\n [ATTR_VCS_OWNER_NAME]: owner,\n [ATTR_VCS_REPOSITORY_NAME]: repo,\n /** @deprecated TODO remove */\n repository: isString(repository)\n ? repository\n : repository.repository,\n },\n },\n );\n }\n\n finalizeReport();\n await exportStats(config);\n } catch (err) /* istanbul ignore next */ {\n if (err.message.startsWith('Init: ')) {\n logger.fatal(\n { errorMessage: err.message.substring(6) },\n 'Initialization error',\n );\n } else {\n logger.fatal({ err }, 'Unknown error');\n }\n if (!config!) {\n // return early if we can't parse config options\n logger.debug(`Missing config`);\n return 2;\n }\n } finally {\n await globalFinalize(config!);\n if (logLevel() === 'info') {\n logger.info(\n `Renovate was run at log level \"${logLevel()}\". Set LOG_LEVEL=debug in environment variables to see extended debug logs.`,\n );\n }\n }\n if (repoExitCode) {\n logger.info(\n { exitCode: repoExitCode },\n 'Renovate is exiting with an error-specific code due to a repository error',\n );\n return repoExitCode;\n }\n const loggerErrors = getProblems().filter((p) => p.level >= ERROR);\n if (loggerErrors.length) {\n logger.info(\n { loggerErrors },\n 'Renovate is exiting with a non-zero code due to the following logged errors',\n );\n return 1;\n }\n return 0;\n}\n\nfunction repositoryToOwnerAndRepo(fullName: string): {\n owner: string;\n repo: string;\n} {\n const parts = fullName.split('/');\n const repo = coerceString(parts.pop());\n const owner = parts.join('/');\n return { owner, repo };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "renovate",
3
3
  "description": "Automated dependency updates. Flexible so you don't need to be.",
4
- "version": "44.153.1",
4
+ "version": "44.154.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "renovate": "dist/renovate.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$id": "https://docs.renovatebot.com/renovate-schema.json",
3
- "title": "JSON schema for Renovate 44.153.1 config files (https://renovatebot.com/)",
3
+ "title": "JSON schema for Renovate 44.154.0 config files (https://renovatebot.com/)",
4
4
  "$schema": "http://json-schema.org/draft-07/schema#",
5
- "x-renovate-version": "44.153.1",
5
+ "x-renovate-version": "44.154.0",
6
6
  "allowComments": true,
7
7
  "type": "object",
8
8
  "definitions": {