renovate 43.206.0 → 43.206.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/types.d.ts +2 -1
- package/dist/config/types.js.map +1 -1
- package/dist/modules/datasource/nuget/v3.js +2 -2
- package/dist/modules/datasource/nuget/v3.js.map +1 -1
- package/dist/modules/manager/terraform/lockfile/hash.js +2 -2
- package/dist/modules/manager/terraform/lockfile/hash.js.map +1 -1
- package/dist/util/fingerprint.js +58 -4
- package/dist/util/fingerprint.js.map +1 -1
- package/package.json +3 -2
package/dist/config/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { ManagerName } from "../manager-list.generated.js";
|
|
|
5
5
|
import { AdditionalConstraintName, ConstraintName, ToolName } from "../util/exec/types.js";
|
|
6
6
|
import { Timestamp } from "../util/timestamp.js";
|
|
7
7
|
import { GitNoVerifyOption } from "../util/git/types.js";
|
|
8
|
-
import { RepoSortMethod, SortMethod } from "../modules/platform/types.js";
|
|
8
|
+
import { GitUrlOption, RepoSortMethod, SortMethod } from "../modules/platform/types.js";
|
|
9
9
|
import { MergeConfidence } from "../util/merge-confidence/types.js";
|
|
10
10
|
import { HostRule } from "../types/host-rules.js";
|
|
11
11
|
import { SkipReason, StageName } from "../types/skip-reason.js";
|
|
@@ -411,6 +411,7 @@ interface CustomDatasourceConfig {
|
|
|
411
411
|
*
|
|
412
412
|
*/
|
|
413
413
|
interface AllConfig extends RenovateConfig, GlobalOnlyConfigLegacy, RepoGlobalConfig {
|
|
414
|
+
gitUrl?: GitUrlOption;
|
|
414
415
|
password?: string;
|
|
415
416
|
token?: string;
|
|
416
417
|
username?: string;
|
package/dist/config/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../lib/config/types.ts"],"sourcesContent":["import type { Category, PlatformId } from '../constants/index.ts';\nimport type { LogLevelRemap } from '../logger/types.ts';\nimport type { ManagerName } from '../manager-list.generated.ts';\nimport type { CustomManager } from '../modules/manager/custom/types.ts';\nimport type { RepoSortMethod, SortMethod } from '../modules/platform/types.ts';\nimport type {\n AutoMergeType,\n HostRule,\n Nullish,\n RangeStrategy,\n SkipReason,\n} from '../types/index.ts';\nimport type { StageName } from '../types/skip-reason.ts';\nimport type {\n AdditionalConstraintName,\n ConstraintName,\n ToolName,\n} from '../util/exec/types.ts';\nimport type { GitNoVerifyOption } from '../util/git/types.ts';\nimport type { MergeConfidence } from '../util/merge-confidence/types.ts';\nimport type { Timestamp } from '../util/timestamp.ts';\n\nexport type RenovateConfigStage =\n | 'global'\n | 'inherit'\n | 'repository'\n | 'package'\n | 'branch'\n | 'pr';\n\nexport type RenovateSplit =\n | 'init'\n | 'onboarding'\n | 'extract'\n | 'lookup'\n | 'update';\n\nexport type RepositoryCacheConfig = 'disabled' | 'enabled' | 'reset';\nexport type RepositoryCacheType = 'local' | (string & {});\nexport type DryRunConfig = 'extract' | 'lookup' | 'full';\nexport type RequiredConfig = 'required' | 'optional' | 'ignored';\n\nexport interface GroupConfig extends Record<string, unknown> {\n branchName?: string;\n branchTopic?: string;\n}\n\nexport type RecreateWhen = 'auto' | 'never' | 'always';\nexport type PlatformCommitOptions = 'auto' | 'disabled' | 'enabled';\n\nexport type BinarySource = 'docker' | 'global' | 'install' | 'hermit';\n\n// TODO: Proper typings\n/**\n * Any configuration that could be used either top-level in a repository config (or Global, Inherited or Shareable Preset configuration), or:\n *\n * - in a datasource-specific configuration\n * - in a manager-specific configuration\n * - in a Package Rule\n *\n * @see RenovateConfig for the superset of all configuration allowed in a given repository\n *\n */\nexport interface RenovateSharedConfig {\n $schema?: string;\n abandonmentThreshold?: Nullish<string>;\n addLabels?: string[];\n assignAutomerge?: boolean;\n autoApprove?: boolean;\n autoReplaceGlobalMatch?: boolean;\n automerge?: boolean;\n automergeSchedule?: string[];\n automergeStrategy?: MergeStrategy;\n automergeType?: AutoMergeType;\n azureWorkItemId?: number;\n branchName?: string;\n branchNameStrict?: boolean;\n branchPrefix?: string;\n branchPrefixOld?: string;\n bumpVersions?: BumpVersionConfig[];\n commitBody?: string;\n commitBodyTable?: boolean;\n commitMessage?: string;\n commitMessageAction?: string;\n commitMessageExtra?: string;\n commitMessageLowerCase?: 'auto' | 'never';\n commitMessagePrefix?: string;\n commitMessageTopic?: string;\n confidential?: boolean;\n configValidationError?: boolean;\n changelogUrl?: string;\n dependencyDashboardApproval?: boolean;\n draftPR?: boolean;\n enabled?: boolean;\n enabledManagers?: string[];\n encrypted?: Record<string, string>;\n extends?: string[];\n extractVersion?: string;\n managerFilePatterns?: string[];\n followTag?: string;\n force?: RenovateConfig;\n gitIgnoredAuthors?: string[];\n group?: GroupConfig;\n groupName?: string;\n groupSlug?: string;\n hashedBranchLength?: number;\n ignoreDeps?: string[];\n ignorePaths?: string[];\n ignoreTests?: boolean;\n ignoreUnstable?: boolean;\n includePaths?: string[];\n internalChecksAsSuccess?: boolean;\n internalChecksFilter?: 'strict' | 'flexible' | 'none';\n keepUpdatedLabel?: string;\n labels?: string[];\n manager?: string;\n milestone?: number;\n minimumReleaseAge?: Nullish<string>;\n npmrc?: string;\n npmrcMerge?: boolean;\n npmToken?: string;\n\n pinDigests?: boolean;\n platformAutomerge?: boolean;\n platformCommit?: PlatformCommitOptions;\n postUpgradeTasks?: PostUpgradeTasks;\n prBodyColumns?: string[];\n prBodyDefinitions?: Record<string, string>;\n prBodyHeadingDefinitions?: Record<string, string>;\n prBodyNotes?: string[];\n prCreation?: 'immediate' | 'not-pending' | 'status-success' | 'approval';\n prFooter?: string;\n prHeader?: string;\n prPriority?: number;\n prTitle?: string;\n prTitleStrict?: boolean;\n productLinks?: Record<string, string>;\n pruneBranchAfterAutomerge?: boolean;\n rangeStrategy?: RangeStrategy;\n rebaseLabel?: string;\n rebaseWhen?: string;\n recreateClosed?: boolean;\n recreateWhen?: RecreateWhen;\n repository?: string;\n repositoryCache?: RepositoryCacheConfig;\n repositoryCacheType?: RepositoryCacheType;\n respectLatest?: boolean;\n rollbackPrs?: boolean;\n schedule?: string[];\n semanticCommitScope?: string | null;\n semanticCommitType?: string;\n semanticCommits?: 'auto' | 'enabled' | 'disabled';\n separateMajorMinor?: boolean;\n separateMinorPatch?: boolean;\n separateMultipleMajor?: boolean;\n separateMultipleMinor?: boolean;\n skipArtifactsUpdate?: boolean;\n stopUpdatingLabel?: string;\n suppressNotifications?: string[];\n timezone?: string;\n unicodeEmoji?: boolean;\n updateNotScheduled?: boolean;\n versioning?: string;\n versionCompatibility?: string;\n}\n\n/**\n * Contains all options with globalOnly=true && inheritConfigSupport=true\n */\nexport interface GlobalInheritableConfig {\n bbUseDevelopmentBranch?: boolean;\n configFileNames?: string[];\n onboarding?: boolean;\n onboardingAutoCloseAge?: number;\n onboardingBranch?: string;\n onboardingCommitMessage?: string;\n onboardingConfig?: RenovateConfig;\n onboardingConfigFileName?: string;\n onboardingNoDeps?: 'auto' | 'enabled' | 'disabled';\n onboardingPrTitle?: string;\n requireConfig?: RequiredConfig;\n}\n\n// Config options used only within the global worker\n// The below should contain config options where stage=global\n/** @deprecated use `RepoGlobalConfig` instead **/\nexport interface GlobalOnlyConfigLegacy {\n autodiscover?: boolean;\n autodiscoverFilter?: string[] | string;\n autodiscoverNamespaces?: string[];\n autodiscoverProjects?: string[];\n autodiscoverTopics?: string[];\n baseDir?: string;\n cacheDir?: string;\n containerbaseDir?: string;\n detectHostRulesFromEnv?: boolean;\n dockerCliOptions?: string;\n endpoint?: string;\n forceCli?: boolean;\n gitNoVerify?: GitNoVerifyOption[];\n gitPrivateKey?: string;\n gitPrivateKeyPassphrase?: string;\n globalExtends?: string[];\n mergeConfidenceDatasources?: string[];\n mergeConfidenceEndpoint?: string;\n platform?: PlatformId;\n processEnv?: Record<string, string>;\n prCommitsPerRunLimit?: number;\n privateKey?: string;\n privateKeyOld?: string;\n privateKeyPath?: string;\n privateKeyPathOld?: string;\n redisPrefix?: string;\n redisUrl?: string;\n repositories?: RenovateRepository[];\n useCloudMetadataServices?: boolean;\n deleteConfigFile?: boolean;\n deleteAdditionalConfigFile?: boolean;\n}\n\n/**\n * Any global-only configuration set by self-hosted administrators.\n *\n * Used within the repository worker.\n *\n * Should only contain config options where globalOnly=true.\n */\nexport interface RepoGlobalConfig extends GlobalInheritableConfig {\n allowedCommands?: string[];\n allowCustomCrateRegistries?: boolean;\n allowPlugins?: boolean;\n allowScripts?: boolean;\n allowShellExecutorForPostUpgradeCommands?: boolean;\n allowedEnv?: string[];\n allowedHeaders?: string[];\n binarySource?: BinarySource;\n cacheDir?: string;\n cacheHardTtlMinutes?: number;\n cacheTtlOverride?: Record<string, number>;\n containerbaseDir?: string;\n customEnvVariables?: Record<string, string>;\n dockerChildPrefix?: string;\n dockerCliOptions?: string;\n dockerSidecarImage?: string;\n dockerUser?: string;\n dryRun?: DryRunConfig;\n encryptedWarning?: string;\n endpoint?: string;\n executionTimeout?: number;\n exposeAllEnv?: boolean;\n gitTimeout?: number;\n githubTokenWarn?: boolean;\n includeMirrors?: boolean;\n localDir?: string;\n migratePresets?: Record<string, string>;\n platform?: PlatformId;\n prCacheSyncMaxPages?: number;\n presetCachePersistence?: boolean;\n httpCacheTtlDays?: number;\n autodiscoverRepoSort?: RepoSortMethod;\n autodiscoverRepoOrder?: SortMethod;\n userAgent?: string;\n dockerMaxPages?: number;\n s3Endpoint?: string;\n s3PathStyle?: boolean;\n cachePrivatePackages?: boolean;\n repositoryCacheForceLocal?: boolean;\n configFileNames?: string[];\n ignorePrAuthor?: boolean;\n allowedUnsafeExecutions?: AllowedUnsafeExecution[];\n onboardingAutoCloseAge?: number;\n toolSettings?: ToolSettingsOptions;\n}\n\n/**\n * Those options are global only but still passed into the repository worker config.\n *\n * @deprecated https://github.com/renovatebot/renovate/issues/39693\n */\nexport interface LegacyAdminConfig {\n baseDir?: string;\n localDir?: string;\n\n logContext?: string;\n\n onboarding?: boolean;\n onboardingBranch?: string;\n onboardingNoDeps?: 'auto' | 'enabled' | 'disabled';\n onboardingRebaseCheckbox?: boolean;\n onboardingConfig?: RenovateConfig;\n onboardingConfigFileName?: string;\n\n optimizeForDisabled?: boolean;\n\n persistRepoData?: boolean;\n\n prCommitsPerRunLimit?: number;\n\n requireConfig?: RequiredConfig;\n\n useCloudMetadataServices?: boolean;\n\n writeDiscoveredRepos?: string;\n}\n\nexport type ExecutionMode = 'branch' | 'update';\n\nexport interface PostUpgradeTasks {\n commands?: string[];\n workingDirTemplate?: string;\n dataFileTemplate?: string;\n fileFilters?: string[];\n executionMode: ExecutionMode;\n installTools?: Partial<Record<ToolName, Record<never, never>>>;\n}\n\nexport type UpdateConfig<\n T extends RenovateSharedConfig = RenovateSharedConfig,\n> = Partial<Record<UpdateType, T | null>>;\n\nexport type RenovateRepository =\n | string\n | (RenovateConfig & {\n repository: string;\n });\n\nexport type UseBaseBranchConfigType = 'merge' | 'none';\nexport type ConstraintsFilter = 'strict' | 'none';\nexport type MinimumReleaseAgeBehaviour =\n | 'timestamp-required'\n | 'timestamp-optional';\n\nexport const allowedStatusCheckStrings = [\n 'minimumReleaseAge',\n 'mergeConfidence',\n 'configValidation',\n 'artifactError',\n] as const;\nexport type StatusCheckKey = (typeof allowedStatusCheckStrings)[number];\ntype UserEnv = Record<string, string>;\n\n/**\n * Computed properties, for internal use only\n */\nexport interface RenovateInternalConfig {\n /** computed base branch from patterns - for internal use only */\n baseBranches?: string[];\n currentCompatibility?: string;\n datasource?: string;\n hasBaseBranches?: boolean;\n isFork?: boolean;\n isVulnerabilityAlert?: boolean;\n\n /** What is this used for? */\n remediations?: unknown;\n /** What is this used for? */\n vulnerabilityAlertsOnly?: boolean;\n}\n\n// TODO: Proper typings\n/**\n * Configuration that could be used either top-level in a repository config (or Global, Inherited or Shareable Preset configuration).\n *\n * This is a superset of any configuration that a Renovate user (not self-hosted administrator) can set.\n */\nexport interface RenovateConfig\n extends\n LegacyAdminConfig,\n RenovateSharedConfig,\n UpdateConfig<PackageRule>,\n AssigneesAndReviewersConfig,\n ConfigMigration,\n RenovateInternalConfig {\n s3Endpoint?: string;\n s3PathStyle?: boolean;\n reportFormatting?: boolean;\n reportPath?: string;\n reportType?: 'logging' | 'file' | 's3' | null;\n depName?: string;\n /** user configurable base branch patterns*/\n baseBranchPatterns?: string[];\n useBaseBranchConfig?: UseBaseBranchConfigType;\n baseBranch?: string;\n defaultBranch?: string;\n branchList?: string[];\n cloneSubmodules?: boolean;\n cloneSubmodulesFilter?: string[];\n description?: string | string[];\n detectGlobalManagerConfig?: boolean;\n errors?: ValidationMessage[];\n forkModeDisallowMaintainerEdits?: boolean;\n forkProcessing?: 'auto' | 'enabled' | 'disabled';\n forkToken?: string;\n\n gitAuthor?: string;\n\n hostRules?: HostRule[];\n\n inheritConfig?: boolean;\n inheritConfigFileName?: string;\n inheritConfigRepoName?: string;\n inheritConfigStrict?: boolean;\n\n ignorePresets?: string[];\n\n fileList?: string[];\n configWarningReuseIssue?: boolean;\n dependencyDashboard?: boolean;\n dependencyDashboardAutoclose?: boolean;\n dependencyDashboardChecks?: Record<string, string>;\n dependencyDashboardIssue?: number;\n dependencyDashboardTitle?: string;\n dependencyDashboardHeader?: string;\n dependencyDashboardFooter?: string;\n dependencyDashboardLabels?: string[];\n dependencyDashboardOSVVulnerabilitySummary?: 'none' | 'all' | 'unresolved';\n dependencyDashboardReportAbandonment?: boolean;\n mode?: 'silent' | 'full';\n packageFile?: string;\n packageRules?: PackageRule[];\n postUpdateOptions?: string[];\n branchConcurrentLimit?: number | null;\n parentOrg?: string;\n prConcurrentLimit?: number;\n commitHourlyLimit?: number;\n prHourlyLimit?: number;\n\n printConfig?: boolean;\n\n pruneStaleBranches?: boolean;\n\n defaultRegistryUrls?: string[];\n registryUrls?: string[] | null;\n registryAliases?: Record<string, string>;\n\n /**\n * What is this used for?\n * @deprecated\n */\n renovateJsonPresent?: boolean;\n\n repoIsOnboarded?: boolean;\n repoIsActivated?: boolean;\n\n topLevelOrg?: string;\n updateInternalDeps?: boolean;\n updateType?: UpdateType;\n\n warnings?: ValidationMessage[];\n vulnerabilityAlerts?: RenovateSharedConfig;\n osvVulnerabilityAlerts?: boolean;\n vulnerabilitySeverity?: string;\n customManagers?: CustomManager[];\n customDatasources?: Record<string, CustomDatasourceConfig>;\n\n fetchChangeLogs?: FetchChangeLogsOptions;\n secrets?: Record<string, string>;\n variables?: Record<string, string>;\n\n constraints?: Partial<Record<ConstraintName, string>>;\n /**\n * Any specific overrides for the versioning for the `AdditionalConstraintName`s.\n */\n constraintsVersioning?: Partial<Record<AdditionalConstraintName, string>>;\n skipInstalls?: boolean | null;\n\n constraintsFiltering?: ConstraintsFilter;\n\n checkedBranches?: string[];\n customizeDashboard?: Record<string, string>;\n\n statusCheckNames?: Record<StatusCheckKey, string | null>;\n /**\n * User configured environment variables that Renovate uses when executing package manager commands\n */\n env?: UserEnv;\n logLevelRemap?: LogLevelRemap[];\n\n branchTopic?: string;\n additionalBranchPrefix?: string;\n sharedVariableName?: string;\n minimumGroupSize?: number;\n configFileNames?: string[];\n minimumReleaseAgeBehaviour?: MinimumReleaseAgeBehaviour;\n toolSettings?: ToolSettingsOptions;\n}\n\nconst CustomDatasourceFormats = [\n 'html',\n 'json',\n 'plain',\n 'toml',\n 'yaml',\n] as const;\nexport type CustomDatasourceFormats = (typeof CustomDatasourceFormats)[number];\n\nexport interface CustomDatasourceConfig {\n defaultRegistryUrlTemplate?: string;\n format?: CustomDatasourceFormats;\n transformTemplates?: string[];\n}\n\n/**\n * The superset of all configuration that a self-hosted administrator can set, alongside all repository-level configuration.\n *\n */\nexport interface AllConfig\n extends RenovateConfig, GlobalOnlyConfigLegacy, RepoGlobalConfig {\n password?: string;\n token?: string;\n username?: string;\n}\n\nexport interface AssigneesAndReviewersConfig {\n assigneesFromCodeOwners?: boolean;\n expandCodeOwnersGroups?: boolean;\n assignees?: string[];\n assigneesSampleSize?: number;\n ignoreReviewers?: string[];\n reviewersFromCodeOwners?: boolean;\n reviewers?: string[];\n reviewersSampleSize?: number;\n additionalReviewers?: string[];\n filterUnavailableUsers?: boolean;\n}\n\nexport type UpdateType =\n | 'major'\n | 'minor'\n | 'patch'\n | 'pin'\n | 'digest'\n | 'pinDigest'\n | 'lockFileMaintenance'\n | 'lockfileUpdate'\n | 'rollback'\n | 'bump'\n | 'replacement';\n\n// These are the update types which can have configuration\nexport const UpdateTypesOptions = [\n 'major',\n 'minor',\n 'patch',\n 'pin',\n 'digest',\n 'pinDigest',\n 'lockFileMaintenance',\n 'rollback',\n 'replacement',\n] as const;\n\nexport type UpdateTypeOptions = (typeof UpdateTypesOptions)[number];\n\nexport type FetchChangeLogsOptions = 'off' | 'branch' | 'pr';\n\nexport type MatchStringsStrategy = 'any' | 'recursive' | 'combination';\n\nexport type MergeStrategy =\n | 'auto'\n | 'fast-forward'\n | 'merge-commit'\n | 'rebase'\n | 'rebase-merge'\n | 'squash';\n\n// This list should be added to as any new unsafe execution commands should be permitted\nexport type AllowedUnsafeExecution =\n | 'bazelModDeps'\n | 'goGenerate'\n | 'gradleWrapper';\n\n// TODO: Proper typings\nexport interface PackageRule\n extends RenovateSharedConfig, RenovateInternalConfig, UpdateConfig {\n allowedVersions?: string;\n description?: string | string[];\n matchBaseBranches?: string[];\n matchCategories?: string[];\n matchConfidence?: MergeConfidence[];\n matchCurrentAge?: string;\n matchCurrentValue?: string;\n matchCurrentVersion?: string;\n matchDatasources?: string[];\n matchDepNames?: string[];\n matchDepTypes?: string[];\n matchFileNames?: string[];\n matchManagers?: string[];\n matchNewValue?: string;\n matchPackageNames?: string[];\n matchRepositories?: string[];\n matchSourceUrls?: string[];\n matchRegistryUrls?: string[];\n matchUpdateTypes?: UpdateType[];\n matchJsonata?: string[];\n overrideDatasource?: string;\n overrideDepName?: string;\n overridePackageName?: string;\n registryUrls?: string[] | null;\n replacementName?: string;\n replacementVersion?: string;\n sourceUrl?: string;\n sourceDirectory?: string;\n vulnerabilitySeverity?: string;\n vulnerabilityFixVersion?: string;\n}\n\nexport interface ValidationMessage {\n topic: string;\n message: string;\n}\n\nexport type AllowedParents =\n | '.'\n | 'bumpVersions'\n | 'customDatasources'\n | 'customManagers'\n | 'hostRules'\n | 'logLevelRemap'\n | 'packageRules'\n | 'postUpgradeTasks'\n | 'vulnerabilityAlerts'\n | 'toolSettings'\n | ManagerName\n | UpdateTypeOptions;\nexport interface RenovateOptionBase {\n /**\n * If true, the option can only be configured by people with access to the Renovate instance.\n * Furthermore, the option should be documented in docs/usage/self-hosted-configuration.md.\n */\n globalOnly?: boolean;\n\n inheritConfigSupport?: boolean;\n\n allowedValues?: string[];\n\n allowString?: boolean;\n\n cli?: boolean;\n\n description: string;\n\n env?: false | string;\n\n /**\n * Do not validate object children\n */\n freeChoice?: boolean;\n\n mergeable?: boolean;\n\n autogenerated?: boolean;\n\n name: string;\n\n parents?: AllowedParents[];\n\n stage?: RenovateConfigStage;\n\n experimental?: boolean;\n\n experimentalDescription?: string;\n\n experimentalIssues?: number[];\n\n advancedUse?: boolean;\n\n /**\n * This is used to add a deprecation message in the docs\n */\n deprecationMsg?: string;\n\n /**\n * For internal use only: add it to any config option that supports regex or glob matching\n */\n patternMatch?: boolean;\n\n /**\n * For internal use only: add it to any config option of type integer that supports negative integers\n */\n allowNegative?: boolean;\n\n /**\n * Managers which support this option, leave undefined if all managers support it.\n */\n supportedManagers?: string[];\n\n /**\n * Platforms which support this option, leave undefined if all platforms support it.\n */\n supportedPlatforms?: PlatformId[];\n\n /**\n * Conditions that must be met for this option to be required.\n */\n requiredIf?: RenovateRequiredOption[];\n\n /**\n * If true, the option's value supports Renovate templating.\n * @see https://docs.renovatebot.com/templates/\n */\n supportsTemplating?: boolean;\n}\n\nexport interface RenovateRequiredOption {\n siblingProperties: { property: string; value: string }[];\n}\n\nexport interface RenovateArrayOption<\n T extends string | number | Record<string, unknown> = Record<string, unknown>,\n> extends RenovateOptionBase {\n default?: T[] | null;\n mergeable?: boolean;\n type: 'array';\n subType?: 'string' | 'object' | 'number';\n}\n\nexport interface RenovateStringArrayOption extends RenovateArrayOption<string> {\n format?: 'regex';\n subType: 'string';\n}\n\nexport interface RenovateNumberArrayOption extends RenovateArrayOption<number> {\n subType: 'number';\n}\n\nexport interface RenovateBooleanOption extends RenovateOptionBase {\n default?: boolean | null;\n type: 'boolean';\n}\n\nexport interface RenovateIntegerOption extends RenovateOptionBase {\n default?: number | null;\n type: 'integer';\n}\n\nexport interface RenovateStringOption extends RenovateOptionBase {\n default?: string | null;\n format?: 'regex';\n\n // Not used\n replaceLineReturns?: boolean;\n type: 'string';\n}\n\nexport interface RenovateObjectOption extends RenovateOptionBase {\n default?: any;\n additionalProperties?: Record<string, unknown> | boolean;\n mergeable?: boolean;\n type: 'object';\n}\n\nexport type RenovateOptions =\n | RenovateStringOption\n | RenovateNumberArrayOption\n | RenovateStringArrayOption\n | RenovateIntegerOption\n | RenovateBooleanOption\n | RenovateArrayOption\n | RenovateObjectOption;\n\nexport interface PackageRuleInputConfig extends RenovateConfig {\n versioning?: string;\n packageFile?: string;\n lockFiles?: string[];\n depType?: string;\n depTypes?: string[];\n depName?: string;\n packageName?: string | null;\n newValue?: string | null;\n currentValue?: string | null;\n currentVersion?: string;\n lockedVersion?: string;\n updateType?: UpdateType;\n mergeConfidenceLevel?: MergeConfidence | undefined;\n isBump?: boolean;\n sourceUrl?: string | null;\n categories?: string[];\n baseBranch?: string;\n manager?: string;\n datasource?: string;\n packageRules?: (PackageRule & PackageRuleInputConfig)[];\n releaseTimestamp?: Timestamp | null;\n repository?: string;\n currentVersionAgeInDays?: number;\n currentVersionTimestamp?: string;\n enabled?: boolean;\n skipReason?: SkipReason;\n skipStage?: StageName;\n}\n\nexport interface ConfigMigration {\n configMigration?: boolean;\n}\n\nexport interface MigratedConfig {\n /**\n * Indicates whether there was a migration applied to the configuration.\n *\n * @returns\n * `false` if the configuration does not need migrating, and `migratedConfig` can be ignored\n * `true` if the configuration was migrated, and if so, `migratedConfig` should be used instead of the provided config\n */\n isMigrated: boolean;\n migratedConfig: RenovateConfig;\n}\n\nexport interface MigratedRenovateConfig extends RenovateConfig {\n endpoints?: HostRule[];\n pathRules: PackageRule[];\n packages: PackageRule[];\n\n node?: RenovateConfig;\n travis?: RenovateConfig;\n gradle?: RenovateConfig;\n}\n\nexport interface ManagerConfig extends RenovateConfig {\n manager: string;\n categories?: Category[];\n}\n\nexport interface ValidationResult {\n errors: ValidationMessage[];\n warnings: ValidationMessage[];\n}\n\nexport interface BumpVersionConfig {\n bumpType?: string;\n filePatterns: string[];\n matchStrings: string[];\n name?: string;\n}\n\nexport interface ToolSettingsOptions {\n jvmMaxMemory?: number;\n jvmMemory?: number;\n nodeMaxMemory?: number;\n}\n"],"mappings":";AA4UA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;AACF;AA2MA,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../lib/config/types.ts"],"sourcesContent":["import type { Category, PlatformId } from '../constants/index.ts';\nimport type { LogLevelRemap } from '../logger/types.ts';\nimport type { ManagerName } from '../manager-list.generated.ts';\nimport type { CustomManager } from '../modules/manager/custom/types.ts';\nimport type {\n GitUrlOption,\n RepoSortMethod,\n SortMethod,\n} from '../modules/platform/types.ts';\nimport type {\n AutoMergeType,\n HostRule,\n Nullish,\n RangeStrategy,\n SkipReason,\n} from '../types/index.ts';\nimport type { StageName } from '../types/skip-reason.ts';\nimport type {\n AdditionalConstraintName,\n ConstraintName,\n ToolName,\n} from '../util/exec/types.ts';\nimport type { GitNoVerifyOption } from '../util/git/types.ts';\nimport type { MergeConfidence } from '../util/merge-confidence/types.ts';\nimport type { Timestamp } from '../util/timestamp.ts';\n\nexport type RenovateConfigStage =\n | 'global'\n | 'inherit'\n | 'repository'\n | 'package'\n | 'branch'\n | 'pr';\n\nexport type RenovateSplit =\n | 'init'\n | 'onboarding'\n | 'extract'\n | 'lookup'\n | 'update';\n\nexport type RepositoryCacheConfig = 'disabled' | 'enabled' | 'reset';\nexport type RepositoryCacheType = 'local' | (string & {});\nexport type DryRunConfig = 'extract' | 'lookup' | 'full';\nexport type RequiredConfig = 'required' | 'optional' | 'ignored';\n\nexport interface GroupConfig extends Record<string, unknown> {\n branchName?: string;\n branchTopic?: string;\n}\n\nexport type RecreateWhen = 'auto' | 'never' | 'always';\nexport type PlatformCommitOptions = 'auto' | 'disabled' | 'enabled';\n\nexport type BinarySource = 'docker' | 'global' | 'install' | 'hermit';\n\n// TODO: Proper typings\n/**\n * Any configuration that could be used either top-level in a repository config (or Global, Inherited or Shareable Preset configuration), or:\n *\n * - in a datasource-specific configuration\n * - in a manager-specific configuration\n * - in a Package Rule\n *\n * @see RenovateConfig for the superset of all configuration allowed in a given repository\n *\n */\nexport interface RenovateSharedConfig {\n $schema?: string;\n abandonmentThreshold?: Nullish<string>;\n addLabels?: string[];\n assignAutomerge?: boolean;\n autoApprove?: boolean;\n autoReplaceGlobalMatch?: boolean;\n automerge?: boolean;\n automergeSchedule?: string[];\n automergeStrategy?: MergeStrategy;\n automergeType?: AutoMergeType;\n azureWorkItemId?: number;\n branchName?: string;\n branchNameStrict?: boolean;\n branchPrefix?: string;\n branchPrefixOld?: string;\n bumpVersions?: BumpVersionConfig[];\n commitBody?: string;\n commitBodyTable?: boolean;\n commitMessage?: string;\n commitMessageAction?: string;\n commitMessageExtra?: string;\n commitMessageLowerCase?: 'auto' | 'never';\n commitMessagePrefix?: string;\n commitMessageTopic?: string;\n confidential?: boolean;\n configValidationError?: boolean;\n changelogUrl?: string;\n dependencyDashboardApproval?: boolean;\n draftPR?: boolean;\n enabled?: boolean;\n enabledManagers?: string[];\n encrypted?: Record<string, string>;\n extends?: string[];\n extractVersion?: string;\n managerFilePatterns?: string[];\n followTag?: string;\n force?: RenovateConfig;\n gitIgnoredAuthors?: string[];\n group?: GroupConfig;\n groupName?: string;\n groupSlug?: string;\n hashedBranchLength?: number;\n ignoreDeps?: string[];\n ignorePaths?: string[];\n ignoreTests?: boolean;\n ignoreUnstable?: boolean;\n includePaths?: string[];\n internalChecksAsSuccess?: boolean;\n internalChecksFilter?: 'strict' | 'flexible' | 'none';\n keepUpdatedLabel?: string;\n labels?: string[];\n manager?: string;\n milestone?: number;\n minimumReleaseAge?: Nullish<string>;\n npmrc?: string;\n npmrcMerge?: boolean;\n npmToken?: string;\n\n pinDigests?: boolean;\n platformAutomerge?: boolean;\n platformCommit?: PlatformCommitOptions;\n postUpgradeTasks?: PostUpgradeTasks;\n prBodyColumns?: string[];\n prBodyDefinitions?: Record<string, string>;\n prBodyHeadingDefinitions?: Record<string, string>;\n prBodyNotes?: string[];\n prCreation?: 'immediate' | 'not-pending' | 'status-success' | 'approval';\n prFooter?: string;\n prHeader?: string;\n prPriority?: number;\n prTitle?: string;\n prTitleStrict?: boolean;\n productLinks?: Record<string, string>;\n pruneBranchAfterAutomerge?: boolean;\n rangeStrategy?: RangeStrategy;\n rebaseLabel?: string;\n rebaseWhen?: string;\n recreateClosed?: boolean;\n recreateWhen?: RecreateWhen;\n repository?: string;\n repositoryCache?: RepositoryCacheConfig;\n repositoryCacheType?: RepositoryCacheType;\n respectLatest?: boolean;\n rollbackPrs?: boolean;\n schedule?: string[];\n semanticCommitScope?: string | null;\n semanticCommitType?: string;\n semanticCommits?: 'auto' | 'enabled' | 'disabled';\n separateMajorMinor?: boolean;\n separateMinorPatch?: boolean;\n separateMultipleMajor?: boolean;\n separateMultipleMinor?: boolean;\n skipArtifactsUpdate?: boolean;\n stopUpdatingLabel?: string;\n suppressNotifications?: string[];\n timezone?: string;\n unicodeEmoji?: boolean;\n updateNotScheduled?: boolean;\n versioning?: string;\n versionCompatibility?: string;\n}\n\n/**\n * Contains all options with globalOnly=true && inheritConfigSupport=true\n */\nexport interface GlobalInheritableConfig {\n bbUseDevelopmentBranch?: boolean;\n configFileNames?: string[];\n onboarding?: boolean;\n onboardingAutoCloseAge?: number;\n onboardingBranch?: string;\n onboardingCommitMessage?: string;\n onboardingConfig?: RenovateConfig;\n onboardingConfigFileName?: string;\n onboardingNoDeps?: 'auto' | 'enabled' | 'disabled';\n onboardingPrTitle?: string;\n requireConfig?: RequiredConfig;\n}\n\n// Config options used only within the global worker\n// The below should contain config options where stage=global\n/** @deprecated use `RepoGlobalConfig` instead **/\nexport interface GlobalOnlyConfigLegacy {\n autodiscover?: boolean;\n autodiscoverFilter?: string[] | string;\n autodiscoverNamespaces?: string[];\n autodiscoverProjects?: string[];\n autodiscoverTopics?: string[];\n baseDir?: string;\n cacheDir?: string;\n containerbaseDir?: string;\n detectHostRulesFromEnv?: boolean;\n dockerCliOptions?: string;\n endpoint?: string;\n forceCli?: boolean;\n gitNoVerify?: GitNoVerifyOption[];\n gitPrivateKey?: string;\n gitPrivateKeyPassphrase?: string;\n globalExtends?: string[];\n mergeConfidenceDatasources?: string[];\n mergeConfidenceEndpoint?: string;\n platform?: PlatformId;\n processEnv?: Record<string, string>;\n prCommitsPerRunLimit?: number;\n privateKey?: string;\n privateKeyOld?: string;\n privateKeyPath?: string;\n privateKeyPathOld?: string;\n redisPrefix?: string;\n redisUrl?: string;\n repositories?: RenovateRepository[];\n useCloudMetadataServices?: boolean;\n deleteConfigFile?: boolean;\n deleteAdditionalConfigFile?: boolean;\n}\n\n/**\n * Any global-only configuration set by self-hosted administrators.\n *\n * Used within the repository worker.\n *\n * Should only contain config options where globalOnly=true.\n */\nexport interface RepoGlobalConfig extends GlobalInheritableConfig {\n allowedCommands?: string[];\n allowCustomCrateRegistries?: boolean;\n allowPlugins?: boolean;\n allowScripts?: boolean;\n allowShellExecutorForPostUpgradeCommands?: boolean;\n allowedEnv?: string[];\n allowedHeaders?: string[];\n binarySource?: BinarySource;\n cacheDir?: string;\n cacheHardTtlMinutes?: number;\n cacheTtlOverride?: Record<string, number>;\n containerbaseDir?: string;\n customEnvVariables?: Record<string, string>;\n dockerChildPrefix?: string;\n dockerCliOptions?: string;\n dockerSidecarImage?: string;\n dockerUser?: string;\n dryRun?: DryRunConfig;\n encryptedWarning?: string;\n endpoint?: string;\n executionTimeout?: number;\n exposeAllEnv?: boolean;\n gitTimeout?: number;\n githubTokenWarn?: boolean;\n includeMirrors?: boolean;\n localDir?: string;\n migratePresets?: Record<string, string>;\n platform?: PlatformId;\n prCacheSyncMaxPages?: number;\n presetCachePersistence?: boolean;\n httpCacheTtlDays?: number;\n autodiscoverRepoSort?: RepoSortMethod;\n autodiscoverRepoOrder?: SortMethod;\n userAgent?: string;\n dockerMaxPages?: number;\n s3Endpoint?: string;\n s3PathStyle?: boolean;\n cachePrivatePackages?: boolean;\n repositoryCacheForceLocal?: boolean;\n configFileNames?: string[];\n ignorePrAuthor?: boolean;\n allowedUnsafeExecutions?: AllowedUnsafeExecution[];\n onboardingAutoCloseAge?: number;\n toolSettings?: ToolSettingsOptions;\n}\n\n/**\n * Those options are global only but still passed into the repository worker config.\n *\n * @deprecated https://github.com/renovatebot/renovate/issues/39693\n */\nexport interface LegacyAdminConfig {\n baseDir?: string;\n localDir?: string;\n\n logContext?: string;\n\n onboarding?: boolean;\n onboardingBranch?: string;\n onboardingNoDeps?: 'auto' | 'enabled' | 'disabled';\n onboardingRebaseCheckbox?: boolean;\n onboardingConfig?: RenovateConfig;\n onboardingConfigFileName?: string;\n\n optimizeForDisabled?: boolean;\n\n persistRepoData?: boolean;\n\n prCommitsPerRunLimit?: number;\n\n requireConfig?: RequiredConfig;\n\n useCloudMetadataServices?: boolean;\n\n writeDiscoveredRepos?: string;\n}\n\nexport type ExecutionMode = 'branch' | 'update';\n\nexport interface PostUpgradeTasks {\n commands?: string[];\n workingDirTemplate?: string;\n dataFileTemplate?: string;\n fileFilters?: string[];\n executionMode: ExecutionMode;\n installTools?: Partial<Record<ToolName, Record<never, never>>>;\n}\n\nexport type UpdateConfig<\n T extends RenovateSharedConfig = RenovateSharedConfig,\n> = Partial<Record<UpdateType, T | null>>;\n\nexport type RenovateRepository =\n | string\n | (RenovateConfig & {\n repository: string;\n });\n\nexport type UseBaseBranchConfigType = 'merge' | 'none';\nexport type ConstraintsFilter = 'strict' | 'none';\nexport type MinimumReleaseAgeBehaviour =\n | 'timestamp-required'\n | 'timestamp-optional';\n\nexport const allowedStatusCheckStrings = [\n 'minimumReleaseAge',\n 'mergeConfidence',\n 'configValidation',\n 'artifactError',\n] as const;\nexport type StatusCheckKey = (typeof allowedStatusCheckStrings)[number];\ntype UserEnv = Record<string, string>;\n\n/**\n * Computed properties, for internal use only\n */\nexport interface RenovateInternalConfig {\n /** computed base branch from patterns - for internal use only */\n baseBranches?: string[];\n currentCompatibility?: string;\n datasource?: string;\n hasBaseBranches?: boolean;\n isFork?: boolean;\n isVulnerabilityAlert?: boolean;\n\n /** What is this used for? */\n remediations?: unknown;\n /** What is this used for? */\n vulnerabilityAlertsOnly?: boolean;\n}\n\n// TODO: Proper typings\n/**\n * Configuration that could be used either top-level in a repository config (or Global, Inherited or Shareable Preset configuration).\n *\n * This is a superset of any configuration that a Renovate user (not self-hosted administrator) can set.\n */\nexport interface RenovateConfig\n extends\n LegacyAdminConfig,\n RenovateSharedConfig,\n UpdateConfig<PackageRule>,\n AssigneesAndReviewersConfig,\n ConfigMigration,\n RenovateInternalConfig {\n s3Endpoint?: string;\n s3PathStyle?: boolean;\n reportFormatting?: boolean;\n reportPath?: string;\n reportType?: 'logging' | 'file' | 's3' | null;\n depName?: string;\n /** user configurable base branch patterns*/\n baseBranchPatterns?: string[];\n useBaseBranchConfig?: UseBaseBranchConfigType;\n baseBranch?: string;\n defaultBranch?: string;\n branchList?: string[];\n cloneSubmodules?: boolean;\n cloneSubmodulesFilter?: string[];\n description?: string | string[];\n detectGlobalManagerConfig?: boolean;\n errors?: ValidationMessage[];\n forkModeDisallowMaintainerEdits?: boolean;\n forkProcessing?: 'auto' | 'enabled' | 'disabled';\n forkToken?: string;\n\n gitAuthor?: string;\n\n hostRules?: HostRule[];\n\n inheritConfig?: boolean;\n inheritConfigFileName?: string;\n inheritConfigRepoName?: string;\n inheritConfigStrict?: boolean;\n\n ignorePresets?: string[];\n\n fileList?: string[];\n configWarningReuseIssue?: boolean;\n dependencyDashboard?: boolean;\n dependencyDashboardAutoclose?: boolean;\n dependencyDashboardChecks?: Record<string, string>;\n dependencyDashboardIssue?: number;\n dependencyDashboardTitle?: string;\n dependencyDashboardHeader?: string;\n dependencyDashboardFooter?: string;\n dependencyDashboardLabels?: string[];\n dependencyDashboardOSVVulnerabilitySummary?: 'none' | 'all' | 'unresolved';\n dependencyDashboardReportAbandonment?: boolean;\n mode?: 'silent' | 'full';\n packageFile?: string;\n packageRules?: PackageRule[];\n postUpdateOptions?: string[];\n branchConcurrentLimit?: number | null;\n parentOrg?: string;\n prConcurrentLimit?: number;\n commitHourlyLimit?: number;\n prHourlyLimit?: number;\n\n printConfig?: boolean;\n\n pruneStaleBranches?: boolean;\n\n defaultRegistryUrls?: string[];\n registryUrls?: string[] | null;\n registryAliases?: Record<string, string>;\n\n /**\n * What is this used for?\n * @deprecated\n */\n renovateJsonPresent?: boolean;\n\n repoIsOnboarded?: boolean;\n repoIsActivated?: boolean;\n\n topLevelOrg?: string;\n updateInternalDeps?: boolean;\n updateType?: UpdateType;\n\n warnings?: ValidationMessage[];\n vulnerabilityAlerts?: RenovateSharedConfig;\n osvVulnerabilityAlerts?: boolean;\n vulnerabilitySeverity?: string;\n customManagers?: CustomManager[];\n customDatasources?: Record<string, CustomDatasourceConfig>;\n\n fetchChangeLogs?: FetchChangeLogsOptions;\n secrets?: Record<string, string>;\n variables?: Record<string, string>;\n\n constraints?: Partial<Record<ConstraintName, string>>;\n /**\n * Any specific overrides for the versioning for the `AdditionalConstraintName`s.\n */\n constraintsVersioning?: Partial<Record<AdditionalConstraintName, string>>;\n skipInstalls?: boolean | null;\n\n constraintsFiltering?: ConstraintsFilter;\n\n checkedBranches?: string[];\n customizeDashboard?: Record<string, string>;\n\n statusCheckNames?: Record<StatusCheckKey, string | null>;\n /**\n * User configured environment variables that Renovate uses when executing package manager commands\n */\n env?: UserEnv;\n logLevelRemap?: LogLevelRemap[];\n\n branchTopic?: string;\n additionalBranchPrefix?: string;\n sharedVariableName?: string;\n minimumGroupSize?: number;\n configFileNames?: string[];\n minimumReleaseAgeBehaviour?: MinimumReleaseAgeBehaviour;\n toolSettings?: ToolSettingsOptions;\n}\n\nconst CustomDatasourceFormats = [\n 'html',\n 'json',\n 'plain',\n 'toml',\n 'yaml',\n] as const;\nexport type CustomDatasourceFormats = (typeof CustomDatasourceFormats)[number];\n\nexport interface CustomDatasourceConfig {\n defaultRegistryUrlTemplate?: string;\n format?: CustomDatasourceFormats;\n transformTemplates?: string[];\n}\n\n/**\n * The superset of all configuration that a self-hosted administrator can set, alongside all repository-level configuration.\n *\n */\nexport interface AllConfig\n extends RenovateConfig, GlobalOnlyConfigLegacy, RepoGlobalConfig {\n gitUrl?: GitUrlOption;\n password?: string;\n token?: string;\n username?: string;\n}\n\nexport interface AssigneesAndReviewersConfig {\n assigneesFromCodeOwners?: boolean;\n expandCodeOwnersGroups?: boolean;\n assignees?: string[];\n assigneesSampleSize?: number;\n ignoreReviewers?: string[];\n reviewersFromCodeOwners?: boolean;\n reviewers?: string[];\n reviewersSampleSize?: number;\n additionalReviewers?: string[];\n filterUnavailableUsers?: boolean;\n}\n\nexport type UpdateType =\n | 'major'\n | 'minor'\n | 'patch'\n | 'pin'\n | 'digest'\n | 'pinDigest'\n | 'lockFileMaintenance'\n | 'lockfileUpdate'\n | 'rollback'\n | 'bump'\n | 'replacement';\n\n// These are the update types which can have configuration\nexport const UpdateTypesOptions = [\n 'major',\n 'minor',\n 'patch',\n 'pin',\n 'digest',\n 'pinDigest',\n 'lockFileMaintenance',\n 'rollback',\n 'replacement',\n] as const;\n\nexport type UpdateTypeOptions = (typeof UpdateTypesOptions)[number];\n\nexport type FetchChangeLogsOptions = 'off' | 'branch' | 'pr';\n\nexport type MatchStringsStrategy = 'any' | 'recursive' | 'combination';\n\nexport type MergeStrategy =\n | 'auto'\n | 'fast-forward'\n | 'merge-commit'\n | 'rebase'\n | 'rebase-merge'\n | 'squash';\n\n// This list should be added to as any new unsafe execution commands should be permitted\nexport type AllowedUnsafeExecution =\n | 'bazelModDeps'\n | 'goGenerate'\n | 'gradleWrapper';\n\n// TODO: Proper typings\nexport interface PackageRule\n extends RenovateSharedConfig, RenovateInternalConfig, UpdateConfig {\n allowedVersions?: string;\n description?: string | string[];\n matchBaseBranches?: string[];\n matchCategories?: string[];\n matchConfidence?: MergeConfidence[];\n matchCurrentAge?: string;\n matchCurrentValue?: string;\n matchCurrentVersion?: string;\n matchDatasources?: string[];\n matchDepNames?: string[];\n matchDepTypes?: string[];\n matchFileNames?: string[];\n matchManagers?: string[];\n matchNewValue?: string;\n matchPackageNames?: string[];\n matchRepositories?: string[];\n matchSourceUrls?: string[];\n matchRegistryUrls?: string[];\n matchUpdateTypes?: UpdateType[];\n matchJsonata?: string[];\n overrideDatasource?: string;\n overrideDepName?: string;\n overridePackageName?: string;\n registryUrls?: string[] | null;\n replacementName?: string;\n replacementVersion?: string;\n sourceUrl?: string;\n sourceDirectory?: string;\n vulnerabilitySeverity?: string;\n vulnerabilityFixVersion?: string;\n}\n\nexport interface ValidationMessage {\n topic: string;\n message: string;\n}\n\nexport type AllowedParents =\n | '.'\n | 'bumpVersions'\n | 'customDatasources'\n | 'customManagers'\n | 'hostRules'\n | 'logLevelRemap'\n | 'packageRules'\n | 'postUpgradeTasks'\n | 'vulnerabilityAlerts'\n | 'toolSettings'\n | ManagerName\n | UpdateTypeOptions;\nexport interface RenovateOptionBase {\n /**\n * If true, the option can only be configured by people with access to the Renovate instance.\n * Furthermore, the option should be documented in docs/usage/self-hosted-configuration.md.\n */\n globalOnly?: boolean;\n\n inheritConfigSupport?: boolean;\n\n allowedValues?: string[];\n\n allowString?: boolean;\n\n cli?: boolean;\n\n description: string;\n\n env?: false | string;\n\n /**\n * Do not validate object children\n */\n freeChoice?: boolean;\n\n mergeable?: boolean;\n\n autogenerated?: boolean;\n\n name: string;\n\n parents?: AllowedParents[];\n\n stage?: RenovateConfigStage;\n\n experimental?: boolean;\n\n experimentalDescription?: string;\n\n experimentalIssues?: number[];\n\n advancedUse?: boolean;\n\n /**\n * This is used to add a deprecation message in the docs\n */\n deprecationMsg?: string;\n\n /**\n * For internal use only: add it to any config option that supports regex or glob matching\n */\n patternMatch?: boolean;\n\n /**\n * For internal use only: add it to any config option of type integer that supports negative integers\n */\n allowNegative?: boolean;\n\n /**\n * Managers which support this option, leave undefined if all managers support it.\n */\n supportedManagers?: string[];\n\n /**\n * Platforms which support this option, leave undefined if all platforms support it.\n */\n supportedPlatforms?: PlatformId[];\n\n /**\n * Conditions that must be met for this option to be required.\n */\n requiredIf?: RenovateRequiredOption[];\n\n /**\n * If true, the option's value supports Renovate templating.\n * @see https://docs.renovatebot.com/templates/\n */\n supportsTemplating?: boolean;\n}\n\nexport interface RenovateRequiredOption {\n siblingProperties: { property: string; value: string }[];\n}\n\nexport interface RenovateArrayOption<\n T extends string | number | Record<string, unknown> = Record<string, unknown>,\n> extends RenovateOptionBase {\n default?: T[] | null;\n mergeable?: boolean;\n type: 'array';\n subType?: 'string' | 'object' | 'number';\n}\n\nexport interface RenovateStringArrayOption extends RenovateArrayOption<string> {\n format?: 'regex';\n subType: 'string';\n}\n\nexport interface RenovateNumberArrayOption extends RenovateArrayOption<number> {\n subType: 'number';\n}\n\nexport interface RenovateBooleanOption extends RenovateOptionBase {\n default?: boolean | null;\n type: 'boolean';\n}\n\nexport interface RenovateIntegerOption extends RenovateOptionBase {\n default?: number | null;\n type: 'integer';\n}\n\nexport interface RenovateStringOption extends RenovateOptionBase {\n default?: string | null;\n format?: 'regex';\n\n // Not used\n replaceLineReturns?: boolean;\n type: 'string';\n}\n\nexport interface RenovateObjectOption extends RenovateOptionBase {\n default?: any;\n additionalProperties?: Record<string, unknown> | boolean;\n mergeable?: boolean;\n type: 'object';\n}\n\nexport type RenovateOptions =\n | RenovateStringOption\n | RenovateNumberArrayOption\n | RenovateStringArrayOption\n | RenovateIntegerOption\n | RenovateBooleanOption\n | RenovateArrayOption\n | RenovateObjectOption;\n\nexport interface PackageRuleInputConfig extends RenovateConfig {\n versioning?: string;\n packageFile?: string;\n lockFiles?: string[];\n depType?: string;\n depTypes?: string[];\n depName?: string;\n packageName?: string | null;\n newValue?: string | null;\n currentValue?: string | null;\n currentVersion?: string;\n lockedVersion?: string;\n updateType?: UpdateType;\n mergeConfidenceLevel?: MergeConfidence | undefined;\n isBump?: boolean;\n sourceUrl?: string | null;\n categories?: string[];\n baseBranch?: string;\n manager?: string;\n datasource?: string;\n packageRules?: (PackageRule & PackageRuleInputConfig)[];\n releaseTimestamp?: Timestamp | null;\n repository?: string;\n currentVersionAgeInDays?: number;\n currentVersionTimestamp?: string;\n enabled?: boolean;\n skipReason?: SkipReason;\n skipStage?: StageName;\n}\n\nexport interface ConfigMigration {\n configMigration?: boolean;\n}\n\nexport interface MigratedConfig {\n /**\n * Indicates whether there was a migration applied to the configuration.\n *\n * @returns\n * `false` if the configuration does not need migrating, and `migratedConfig` can be ignored\n * `true` if the configuration was migrated, and if so, `migratedConfig` should be used instead of the provided config\n */\n isMigrated: boolean;\n migratedConfig: RenovateConfig;\n}\n\nexport interface MigratedRenovateConfig extends RenovateConfig {\n endpoints?: HostRule[];\n pathRules: PackageRule[];\n packages: PackageRule[];\n\n node?: RenovateConfig;\n travis?: RenovateConfig;\n gradle?: RenovateConfig;\n}\n\nexport interface ManagerConfig extends RenovateConfig {\n manager: string;\n categories?: Category[];\n}\n\nexport interface ValidationResult {\n errors: ValidationMessage[];\n warnings: ValidationMessage[];\n}\n\nexport interface BumpVersionConfig {\n bumpType?: string;\n filePatterns: string[];\n matchStrings: string[];\n name?: string;\n}\n\nexport interface ToolSettingsOptions {\n jvmMaxMemory?: number;\n jvmMemory?: number;\n nodeMaxMemory?: number;\n}\n"],"mappings":";AAgVA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;AACF;AA4MA,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -17,7 +17,7 @@ import { isNonEmptyString } from "@sindresorhus/is";
|
|
|
17
17
|
import upath from "upath";
|
|
18
18
|
import semver from "semver";
|
|
19
19
|
import { XmlDocument } from "xmldoc";
|
|
20
|
-
import
|
|
20
|
+
import AdmZip from "adm-zip";
|
|
21
21
|
//#region lib/modules/datasource/nuget/v3.ts
|
|
22
22
|
var NugetV3Api = class NugetV3Api {
|
|
23
23
|
static cacheNamespace = "datasource-nuget-v3";
|
|
@@ -152,7 +152,7 @@ var NugetV3Api = class NugetV3Api {
|
|
|
152
152
|
const readStream = http.stream(nupkgUrl);
|
|
153
153
|
try {
|
|
154
154
|
await pipeline(readStream, createCacheWriteStream(nupkgFile));
|
|
155
|
-
|
|
155
|
+
new AdmZip(nupkgFile).extractAllTo(nupkgContentsDir);
|
|
156
156
|
return new XmlDocument(await readCacheFile(upath.join(nupkgContentsDir, `${packageName}.nuspec`), "utf8")).valueWithPath("metadata.repository@url") ?? null;
|
|
157
157
|
} finally {
|
|
158
158
|
await rmCache(nupkgFile);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.js","names":["packageCache.get","packageCache.set","p.all","versioning","HttpError","fs.createCacheWriteStream","fs.pipeline","fs.readCacheFile","fs.rmCache"],"sources":["../../../../lib/modules/datasource/nuget/v3.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport extract from 'extract-zip';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { api as versioning } from '../../versioning/nuget/index.ts';\nimport type { Release, ReleaseResult } from '../types.ts';\nimport { massageUrl, removeBuildMeta, sortNugetVersions } from './common.ts';\nimport type {\n CatalogEntry,\n CatalogPage,\n PackageRegistration,\n ServicesIndexRaw,\n} from './types.ts';\n\nexport class NugetV3Api {\n static readonly cacheNamespace = 'datasource-nuget-v3';\n\n async getResourceUrl(\n http: Http,\n url: string,\n resourceType = 'RegistrationsBaseUrl',\n ): Promise<string | null> {\n // https://learn.microsoft.com/nuget/api/service-index\n const resultCacheKey = `${url}:${resourceType}`;\n const cachedResult = await packageCache.get<string>(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n );\n\n /* v8 ignore next 3 -- TODO: add test */\n if (cachedResult) {\n return cachedResult;\n }\n let servicesIndexRaw: ServicesIndexRaw | undefined;\n try {\n const responseCacheKey = url;\n servicesIndexRaw = await packageCache.get<ServicesIndexRaw>(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n );\n if (!servicesIndexRaw) {\n servicesIndexRaw = (\n await http.getJsonUnchecked<ServicesIndexRaw>(url, {\n cacheProvider: memCacheProvider,\n })\n ).body;\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n servicesIndexRaw,\n 3 * 24 * 60,\n );\n }\n\n const services = servicesIndexRaw.resources\n .map(({ '@id': serviceId, '@type': t }) => ({\n serviceId,\n type: t?.split('/')?.shift(),\n version: t?.split('/')?.pop(),\n }))\n .filter(\n ({ type, version }) => type === resourceType && semver.valid(version),\n )\n .sort((x, y) =>\n x.version && y.version\n ? semver.compare(x.version, y.version)\n : /* istanbul ignore next: hard to test */ 0,\n );\n\n if (services.length === 0) {\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n null,\n 60,\n );\n logger.debug(\n { url, servicesIndexRaw },\n `no ${resourceType} services found`,\n );\n return null;\n }\n\n const { serviceId, version } = services.pop()!;\n\n // istanbul ignore if\n if (\n resourceType === 'RegistrationsBaseUrl' &&\n version &&\n !version.startsWith('3.0.0-') &&\n !semver.satisfies(version, '^3.0.0')\n ) {\n logger.warn(\n { url, version },\n `Nuget: Unknown version returned. Only v3 is supported`,\n );\n }\n\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n serviceId,\n 60,\n );\n return serviceId;\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { err, url, servicesIndexRaw },\n `nuget registry failure: can't get ${resourceType}`,\n );\n return null;\n }\n }\n\n async getCatalogEntry(\n http: Http,\n catalogPage: CatalogPage,\n ): Promise<CatalogEntry[]> {\n let items = catalogPage.items;\n if (!items) {\n const url = catalogPage['@id'];\n const catalogPageFull = await http.getJsonUnchecked<CatalogPage>(url);\n items = catalogPageFull.body.items;\n }\n return items.map(({ catalogEntry }) => catalogEntry);\n }\n\n async getReleases(\n http: Http,\n registryUrl: string,\n feedUrl: string,\n pkgName: string,\n ): Promise<ReleaseResult | null> {\n const baseUrl = feedUrl.replace(regEx(/\\/*$/), '');\n const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`;\n const packageRegistration =\n await http.getJsonUnchecked<PackageRegistration>(url);\n const catalogPages = packageRegistration.body.items || [];\n const catalogPagesQueue = catalogPages.map(\n (page) => (): Promise<CatalogEntry[]> => this.getCatalogEntry(http, page),\n );\n const catalogEntries = (await p.all(catalogPagesQueue))\n .flat()\n .sort((a, b) => sortNugetVersions(a.version, b.version));\n\n let homepage: string | null = null;\n let latestStable: string | null = null;\n let nupkgUrl: string | null = null;\n const releases = catalogEntries.map(\n ({\n version,\n published,\n projectUrl,\n listed,\n packageContent,\n deprecation,\n }) => {\n const release: Release = { version: removeBuildMeta(version) };\n const releaseTimestamp = asTimestamp(published);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n if (\n versioning.isValid(version) &&\n versioning.isStable(version) &&\n listed\n ) {\n latestStable = removeBuildMeta(version);\n homepage = projectUrl ? massageUrl(projectUrl) : homepage;\n nupkgUrl = massageUrl(packageContent);\n }\n\n if (listed === false || deprecation) {\n release.isDeprecated = true;\n }\n return release;\n },\n );\n\n if (!releases.length) {\n return null;\n }\n\n // istanbul ignore next: only happens when no stable version exists\n if (latestStable === null && catalogPages.length) {\n const last = catalogEntries.pop()!;\n latestStable = removeBuildMeta(last.version);\n homepage ??= last.projectUrl ?? null;\n nupkgUrl ??= massageUrl(last.packageContent);\n }\n\n const dep: ReleaseResult = {\n releases,\n };\n\n if (releases.every((release) => release.isDeprecated === true)) {\n dep.deprecationMessage = this.getDeprecationMessage(pkgName);\n }\n\n try {\n const packageBaseAddress = await this.getResourceUrl(\n http,\n registryUrl,\n 'PackageBaseAddress',\n );\n if (isNonEmptyString(packageBaseAddress)) {\n const nuspecUrl = `${ensureTrailingSlash(\n packageBaseAddress,\n )}${pkgName.toLowerCase()}/${\n // TODO: types (#22198)\n latestStable\n }/${pkgName.toLowerCase()}.nuspec`;\n const metaresult = await http.getText(nuspecUrl, {\n cacheProvider: memCacheProvider,\n });\n const nuspec = new XmlDocument(metaresult.body);\n const releaseNotes = nuspec.valueWithPath('metadata.releaseNotes');\n if (releaseNotes) {\n dep.changelogContent = releaseNotes;\n }\n const sourceUrl = nuspec.valueWithPath('metadata.repository@url');\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n }\n } else if (nupkgUrl) {\n const sourceUrl = await this.getSourceUrlFromNupkg(\n http,\n registryUrl,\n pkgName,\n latestStable,\n nupkgUrl,\n );\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n logger.debug(`Determined sourceUrl ${sourceUrl} from ${nupkgUrl}`);\n }\n }\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n // ignore / silence 404. Seen on proget, if remote connector is used and package is not yet cached\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n logger.debug(\n { err, registryUrl, pkgName, pkgVersion: latestStable },\n `Cannot obtain sourceUrl`,\n );\n }\n }\n\n if (homepage) {\n // only assign if not assigned\n dep.sourceUrl ??= homepage;\n dep.homepage ??= homepage;\n }\n\n return dep;\n }\n\n private async _getSourceUrlFromNupkg(\n http: Http,\n _registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n /* v8 ignore next 4 */\n if (!getEnv().RENOVATE_X_NUGET_DOWNLOAD_NUPKGS) {\n logger.once.debug('RENOVATE_X_NUGET_DOWNLOAD_NUPKGS is not set');\n return null;\n }\n const cacheDir = await ensureCacheDir('nuget');\n const nupkgFile = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}.nupkg`,\n );\n const nupkgContentsDir = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}`,\n );\n const readStream = http.stream(nupkgUrl);\n try {\n const writeStream = fs.createCacheWriteStream(nupkgFile);\n await fs.pipeline(readStream, writeStream);\n await extract(nupkgFile, { dir: nupkgContentsDir });\n const nuspecFile = upath.join(nupkgContentsDir, `${packageName}.nuspec`);\n const nuspec = new XmlDocument(\n await fs.readCacheFile(nuspecFile, 'utf8'),\n );\n return nuspec.valueWithPath('metadata.repository@url') ?? null;\n } finally {\n await fs.rmCache(nupkgFile);\n await fs.rmCache(nupkgContentsDir);\n }\n }\n\n getSourceUrlFromNupkg(\n http: Http,\n registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n return withCache(\n {\n namespace: NugetV3Api.cacheNamespace,\n key: `source-url:${registryUrl}:${packageName}`,\n ttlMinutes: 10080, // 1 week\n },\n () =>\n this._getSourceUrlFromNupkg(\n http,\n registryUrl,\n packageName,\n packageVersion,\n nupkgUrl,\n ),\n );\n }\n\n getDeprecationMessage(packageName: string): string {\n return `The package \\`${packageName}\\` is deprecated.`;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"v3.js","names":["packageCache.get","packageCache.set","p.all","versioning","HttpError","fs.createCacheWriteStream","fs.pipeline","fs.readCacheFile","fs.rmCache"],"sources":["../../../../lib/modules/datasource/nuget/v3.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport AdmZip from 'adm-zip';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { api as versioning } from '../../versioning/nuget/index.ts';\nimport type { Release, ReleaseResult } from '../types.ts';\nimport { massageUrl, removeBuildMeta, sortNugetVersions } from './common.ts';\nimport type {\n CatalogEntry,\n CatalogPage,\n PackageRegistration,\n ServicesIndexRaw,\n} from './types.ts';\n\nexport class NugetV3Api {\n static readonly cacheNamespace = 'datasource-nuget-v3';\n\n async getResourceUrl(\n http: Http,\n url: string,\n resourceType = 'RegistrationsBaseUrl',\n ): Promise<string | null> {\n // https://learn.microsoft.com/nuget/api/service-index\n const resultCacheKey = `${url}:${resourceType}`;\n const cachedResult = await packageCache.get<string>(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n );\n\n /* v8 ignore next 3 -- TODO: add test */\n if (cachedResult) {\n return cachedResult;\n }\n let servicesIndexRaw: ServicesIndexRaw | undefined;\n try {\n const responseCacheKey = url;\n servicesIndexRaw = await packageCache.get<ServicesIndexRaw>(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n );\n if (!servicesIndexRaw) {\n servicesIndexRaw = (\n await http.getJsonUnchecked<ServicesIndexRaw>(url, {\n cacheProvider: memCacheProvider,\n })\n ).body;\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n servicesIndexRaw,\n 3 * 24 * 60,\n );\n }\n\n const services = servicesIndexRaw.resources\n .map(({ '@id': serviceId, '@type': t }) => ({\n serviceId,\n type: t?.split('/')?.shift(),\n version: t?.split('/')?.pop(),\n }))\n .filter(\n ({ type, version }) => type === resourceType && semver.valid(version),\n )\n .sort((x, y) =>\n x.version && y.version\n ? semver.compare(x.version, y.version)\n : /* istanbul ignore next: hard to test */ 0,\n );\n\n if (services.length === 0) {\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n null,\n 60,\n );\n logger.debug(\n { url, servicesIndexRaw },\n `no ${resourceType} services found`,\n );\n return null;\n }\n\n const { serviceId, version } = services.pop()!;\n\n // istanbul ignore if\n if (\n resourceType === 'RegistrationsBaseUrl' &&\n version &&\n !version.startsWith('3.0.0-') &&\n !semver.satisfies(version, '^3.0.0')\n ) {\n logger.warn(\n { url, version },\n `Nuget: Unknown version returned. Only v3 is supported`,\n );\n }\n\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n serviceId,\n 60,\n );\n return serviceId;\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { err, url, servicesIndexRaw },\n `nuget registry failure: can't get ${resourceType}`,\n );\n return null;\n }\n }\n\n async getCatalogEntry(\n http: Http,\n catalogPage: CatalogPage,\n ): Promise<CatalogEntry[]> {\n let items = catalogPage.items;\n if (!items) {\n const url = catalogPage['@id'];\n const catalogPageFull = await http.getJsonUnchecked<CatalogPage>(url);\n items = catalogPageFull.body.items;\n }\n return items.map(({ catalogEntry }) => catalogEntry);\n }\n\n async getReleases(\n http: Http,\n registryUrl: string,\n feedUrl: string,\n pkgName: string,\n ): Promise<ReleaseResult | null> {\n const baseUrl = feedUrl.replace(regEx(/\\/*$/), '');\n const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`;\n const packageRegistration =\n await http.getJsonUnchecked<PackageRegistration>(url);\n const catalogPages = packageRegistration.body.items || [];\n const catalogPagesQueue = catalogPages.map(\n (page) => (): Promise<CatalogEntry[]> => this.getCatalogEntry(http, page),\n );\n const catalogEntries = (await p.all(catalogPagesQueue))\n .flat()\n .sort((a, b) => sortNugetVersions(a.version, b.version));\n\n let homepage: string | null = null;\n let latestStable: string | null = null;\n let nupkgUrl: string | null = null;\n const releases = catalogEntries.map(\n ({\n version,\n published,\n projectUrl,\n listed,\n packageContent,\n deprecation,\n }) => {\n const release: Release = { version: removeBuildMeta(version) };\n const releaseTimestamp = asTimestamp(published);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n if (\n versioning.isValid(version) &&\n versioning.isStable(version) &&\n listed\n ) {\n latestStable = removeBuildMeta(version);\n homepage = projectUrl ? massageUrl(projectUrl) : homepage;\n nupkgUrl = massageUrl(packageContent);\n }\n\n if (listed === false || deprecation) {\n release.isDeprecated = true;\n }\n return release;\n },\n );\n\n if (!releases.length) {\n return null;\n }\n\n // istanbul ignore next: only happens when no stable version exists\n if (latestStable === null && catalogPages.length) {\n const last = catalogEntries.pop()!;\n latestStable = removeBuildMeta(last.version);\n homepage ??= last.projectUrl ?? null;\n nupkgUrl ??= massageUrl(last.packageContent);\n }\n\n const dep: ReleaseResult = {\n releases,\n };\n\n if (releases.every((release) => release.isDeprecated === true)) {\n dep.deprecationMessage = this.getDeprecationMessage(pkgName);\n }\n\n try {\n const packageBaseAddress = await this.getResourceUrl(\n http,\n registryUrl,\n 'PackageBaseAddress',\n );\n if (isNonEmptyString(packageBaseAddress)) {\n const nuspecUrl = `${ensureTrailingSlash(\n packageBaseAddress,\n )}${pkgName.toLowerCase()}/${\n // TODO: types (#22198)\n latestStable\n }/${pkgName.toLowerCase()}.nuspec`;\n const metaresult = await http.getText(nuspecUrl, {\n cacheProvider: memCacheProvider,\n });\n const nuspec = new XmlDocument(metaresult.body);\n const releaseNotes = nuspec.valueWithPath('metadata.releaseNotes');\n if (releaseNotes) {\n dep.changelogContent = releaseNotes;\n }\n const sourceUrl = nuspec.valueWithPath('metadata.repository@url');\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n }\n } else if (nupkgUrl) {\n const sourceUrl = await this.getSourceUrlFromNupkg(\n http,\n registryUrl,\n pkgName,\n latestStable,\n nupkgUrl,\n );\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n logger.debug(`Determined sourceUrl ${sourceUrl} from ${nupkgUrl}`);\n }\n }\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n // ignore / silence 404. Seen on proget, if remote connector is used and package is not yet cached\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n logger.debug(\n { err, registryUrl, pkgName, pkgVersion: latestStable },\n `Cannot obtain sourceUrl`,\n );\n }\n }\n\n if (homepage) {\n // only assign if not assigned\n dep.sourceUrl ??= homepage;\n dep.homepage ??= homepage;\n }\n\n return dep;\n }\n\n private async _getSourceUrlFromNupkg(\n http: Http,\n _registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n /* v8 ignore next 4 */\n if (!getEnv().RENOVATE_X_NUGET_DOWNLOAD_NUPKGS) {\n logger.once.debug('RENOVATE_X_NUGET_DOWNLOAD_NUPKGS is not set');\n return null;\n }\n const cacheDir = await ensureCacheDir('nuget');\n const nupkgFile = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}.nupkg`,\n );\n const nupkgContentsDir = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}`,\n );\n const readStream = http.stream(nupkgUrl);\n try {\n const writeStream = fs.createCacheWriteStream(nupkgFile);\n await fs.pipeline(readStream, writeStream);\n const zip = new AdmZip(nupkgFile);\n zip.extractAllTo(nupkgContentsDir);\n const nuspecFile = upath.join(nupkgContentsDir, `${packageName}.nuspec`);\n const nuspec = new XmlDocument(\n await fs.readCacheFile(nuspecFile, 'utf8'),\n );\n return nuspec.valueWithPath('metadata.repository@url') ?? null;\n } finally {\n await fs.rmCache(nupkgFile);\n await fs.rmCache(nupkgContentsDir);\n }\n }\n\n getSourceUrlFromNupkg(\n http: Http,\n registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n return withCache(\n {\n namespace: NugetV3Api.cacheNamespace,\n key: `source-url:${registryUrl}:${packageName}`,\n ttlMinutes: 10080, // 1 week\n },\n () =>\n this._getSourceUrlFromNupkg(\n http,\n registryUrl,\n packageName,\n packageVersion,\n nupkgUrl,\n ),\n );\n }\n\n getDeprecationMessage(packageName: string): string {\n return `The package \\`${packageName}\\` is deprecated.`;\n }\n}\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { map } from "../../../../util/promises.js";
|
|
|
7
7
|
import { TerraformProviderDatasource } from "../../../datasource/terraform-provider/index.js";
|
|
8
8
|
import crypto from "node:crypto";
|
|
9
9
|
import upath from "upath";
|
|
10
|
-
import
|
|
10
|
+
import AdmZip from "adm-zip";
|
|
11
11
|
//#region lib/modules/manager/terraform/lockfile/hash.ts
|
|
12
12
|
var TerraformProviderHash = class TerraformProviderHash {
|
|
13
13
|
static http = new Http(TerraformProviderDatasource.id);
|
|
@@ -61,7 +61,7 @@ var TerraformProviderHash = class TerraformProviderHash {
|
|
|
61
61
|
* @param extractPath path to where to temporarily extract the data
|
|
62
62
|
*/
|
|
63
63
|
static async hashOfZipContent(zipFilePath, extractPath) {
|
|
64
|
-
|
|
64
|
+
new AdmZip(zipFilePath).extractAllTo(extractPath);
|
|
65
65
|
const hash = await this.hashOfDir(extractPath);
|
|
66
66
|
await rmCache(extractPath);
|
|
67
67
|
return hash;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","names":["fs.cachePathIsFile","fs.readCacheFile","fs.rmCache","fs.listCacheDir","fs.createCacheWriteStream","fs.pipeline","p.map"],"sources":["../../../../../lib/modules/manager/terraform/lockfile/hash.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport extract from 'extract-zip';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport {\n coerceArray,\n deduplicateArray,\n isNotNullOrUndefined,\n} from '../../../../util/array.ts';\nimport { withCache } from '../../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../../util/fs/index.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/types.ts';\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 private static async hashElementList(\n basePath: string,\n fileSystemEntries: string[],\n ): Promise<string> {\n const rootHash = crypto.createHash('sha256');\n\n for (const entryPath of fileSystemEntries) {\n const absolutePath = upath.resolve(basePath, entryPath);\n if (!(await fs.cachePathIsFile(absolutePath))) {\n continue;\n }\n\n // build for every file a line looking like \"aaaaaaaaaaaaaaa file.txt\\n\"\n\n // get hash of specific file\n const hash = crypto.createHash('sha256');\n const fileBuffer = await fs.readCacheFile(absolutePath);\n hash.update(fileBuffer);\n\n const line = `${hash.digest('hex')} ${upath.normalize(entryPath)}\\n`;\n rootHash.update(line);\n }\n\n return rootHash.digest('base64');\n }\n\n /**\n * This is a reimplementation of the Go H1 hash algorithm found at https://github.com/golang/mod/blob/master/sumdb/dirhash/hash.go\n * The package provides two function HashDir and HashZip where the first is for hashing the contents of a directory\n * and the second for doing the same but implicitly extracting the contents first.\n *\n * The problem starts with that there is a bug which leads to the fact that HashDir and HashZip do not return the same\n * hash if there are folders inside the content which should be hashed.\n *\n * In a folder structure such as\n * .\n * ├── Readme.md\n * └── readme-assets/\n * └── image.jpg\n *\n * HashDir will create a list of following entries which in turn will hash again\n * aaaaaaaaaaa Readme.md\\n\n * ccccccccccc readme-assets/image.jpg\\n\n *\n * HashZip in contrast will not filter out the directory itself but rather includes it in the hash list\n * aaaaaaaaaaa Readme.md\\n\n * bbbbbbbbbbb readme-assets/\\n\n * ccccccccccc readme-assets/image.jpg\\n\n *\n * As the resulting string is used to generate the final hash it will differ based on which function has been used.\n * The issue is tracked here: https://github.com/golang/go/issues/53448\n *\n * This implementation follows the intended implementation and filters out folder entries.\n * Terraform seems NOT to use HashZip for provider validation, but rather extracts it and then do the hash calculation\n * even as both are set up in their code base.\n * https://github.com/hashicorp/terraform/blob/3fdfbd69448b14a4982b3c62a5d36835956fcbaa/internal/getproviders/hash.go#L283-L305\n *\n * @param zipFilePath path to the zip file\n * @param extractPath path to where to temporarily extract the data\n */\n static async hashOfZipContent(\n zipFilePath: string,\n extractPath: string,\n ): Promise<string> {\n await extract(zipFilePath, {\n dir: extractPath,\n });\n const hash = await this.hashOfDir(extractPath);\n // delete extracted files\n await fs.rmCache(extractPath);\n\n return hash;\n }\n\n static async hashOfDir(dirPath: string): Promise<string> {\n const elements = await fs.listCacheDir(dirPath, { recursive: true });\n\n const sortedFileSystemObjects = elements.sort();\n return await TerraformProviderHash.hashElementList(\n dirPath,\n sortedFileSystemObjects,\n );\n }\n\n private static async _calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n const downloadFileName = upath.join(cacheDir, build.filename);\n const extractPath = upath.join(cacheDir, 'extract', build.filename);\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, extractPath);\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 // delete zip file\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: `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 ensureCacheDir('terraform');\n\n // for each build download ZIP, extract content and generate hash for all containing files\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 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 // sorting the hash alphabetically as terraform does this as well\n return hashes.sort();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hash.js","names":["fs.cachePathIsFile","fs.readCacheFile","fs.rmCache","fs.listCacheDir","fs.createCacheWriteStream","fs.pipeline","p.map"],"sources":["../../../../../lib/modules/manager/terraform/lockfile/hash.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport AdmZip from 'adm-zip';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport {\n coerceArray,\n deduplicateArray,\n isNotNullOrUndefined,\n} from '../../../../util/array.ts';\nimport { withCache } from '../../../../util/cache/package/with-cache.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../../util/fs/index.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/types.ts';\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 private static async hashElementList(\n basePath: string,\n fileSystemEntries: string[],\n ): Promise<string> {\n const rootHash = crypto.createHash('sha256');\n\n for (const entryPath of fileSystemEntries) {\n const absolutePath = upath.resolve(basePath, entryPath);\n if (!(await fs.cachePathIsFile(absolutePath))) {\n continue;\n }\n\n // build for every file a line looking like \"aaaaaaaaaaaaaaa file.txt\\n\"\n\n // get hash of specific file\n const hash = crypto.createHash('sha256');\n const fileBuffer = await fs.readCacheFile(absolutePath);\n hash.update(fileBuffer);\n\n const line = `${hash.digest('hex')} ${upath.normalize(entryPath)}\\n`;\n rootHash.update(line);\n }\n\n return rootHash.digest('base64');\n }\n\n /**\n * This is a reimplementation of the Go H1 hash algorithm found at https://github.com/golang/mod/blob/master/sumdb/dirhash/hash.go\n * The package provides two function HashDir and HashZip where the first is for hashing the contents of a directory\n * and the second for doing the same but implicitly extracting the contents first.\n *\n * The problem starts with that there is a bug which leads to the fact that HashDir and HashZip do not return the same\n * hash if there are folders inside the content which should be hashed.\n *\n * In a folder structure such as\n * .\n * ├── Readme.md\n * └── readme-assets/\n * └── image.jpg\n *\n * HashDir will create a list of following entries which in turn will hash again\n * aaaaaaaaaaa Readme.md\\n\n * ccccccccccc readme-assets/image.jpg\\n\n *\n * HashZip in contrast will not filter out the directory itself but rather includes it in the hash list\n * aaaaaaaaaaa Readme.md\\n\n * bbbbbbbbbbb readme-assets/\\n\n * ccccccccccc readme-assets/image.jpg\\n\n *\n * As the resulting string is used to generate the final hash it will differ based on which function has been used.\n * The issue is tracked here: https://github.com/golang/go/issues/53448\n *\n * This implementation follows the intended implementation and filters out folder entries.\n * Terraform seems NOT to use HashZip for provider validation, but rather extracts it and then do the hash calculation\n * even as both are set up in their code base.\n * https://github.com/hashicorp/terraform/blob/3fdfbd69448b14a4982b3c62a5d36835956fcbaa/internal/getproviders/hash.go#L283-L305\n *\n * @param zipFilePath path to the zip file\n * @param extractPath path to where to temporarily extract the data\n */\n static async hashOfZipContent(\n zipFilePath: string,\n extractPath: string,\n ): Promise<string> {\n const zip = new AdmZip(zipFilePath);\n zip.extractAllTo(extractPath);\n const hash = await this.hashOfDir(extractPath);\n // delete extracted files\n await fs.rmCache(extractPath);\n\n return hash;\n }\n\n static async hashOfDir(dirPath: string): Promise<string> {\n const elements = await fs.listCacheDir(dirPath, { recursive: true });\n\n const sortedFileSystemObjects = elements.sort();\n return await TerraformProviderHash.hashElementList(\n dirPath,\n sortedFileSystemObjects,\n );\n }\n\n private static async _calculateSingleHash(\n build: TerraformBuild,\n cacheDir: string,\n ): Promise<string> {\n const downloadFileName = upath.join(cacheDir, build.filename);\n const extractPath = upath.join(cacheDir, 'extract', build.filename);\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, extractPath);\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 // delete zip file\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: `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 ensureCacheDir('terraform');\n\n // for each build download ZIP, extract content and generate hash for all containing files\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 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 // sorting the hash alphabetically as terraform does this as well\n return hashes.sort();\n }\n}\n"],"mappings":"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"}
|
package/dist/util/fingerprint.js
CHANGED
|
@@ -1,9 +1,63 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { hash } from "./hash.js";
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
3
2
|
//#region lib/util/fingerprint.ts
|
|
3
|
+
function isEmittable(value, cache) {
|
|
4
|
+
if (value === void 0 || typeof value === "function" || typeof value === "symbol") return false;
|
|
5
|
+
if (value === null || typeof value !== "object") return true;
|
|
6
|
+
const cached = cache.get(value);
|
|
7
|
+
if (cached !== void 0) return cached;
|
|
8
|
+
const obj = value;
|
|
9
|
+
const result = typeof obj.toJSON === "function" ? isEmittable(obj.toJSON(), cache) : true;
|
|
10
|
+
cache.set(value, result);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
function fingerprintInto(h, value, seen, emittableCache) {
|
|
14
|
+
if (value === null || typeof value !== "object") {
|
|
15
|
+
h.update(JSON.stringify(value));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const obj = value;
|
|
19
|
+
if (typeof obj.toJSON === "function") {
|
|
20
|
+
fingerprintInto(h, obj.toJSON(), seen, emittableCache);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (seen.has(value)) {
|
|
24
|
+
h.update("\"[Circular]\"");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
seen.add(value);
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
h.update("[");
|
|
30
|
+
for (let i = 0; i < value.length; i++) {
|
|
31
|
+
if (i > 0) h.update(",");
|
|
32
|
+
const item = value[i];
|
|
33
|
+
if (isEmittable(item, emittableCache)) fingerprintInto(h, item, seen, emittableCache);
|
|
34
|
+
else h.update("null");
|
|
35
|
+
}
|
|
36
|
+
h.update("]");
|
|
37
|
+
} else {
|
|
38
|
+
const entries = value;
|
|
39
|
+
const keys = Object.keys(entries).sort();
|
|
40
|
+
h.update("{");
|
|
41
|
+
let first = true;
|
|
42
|
+
for (const k of keys) {
|
|
43
|
+
const v = entries[k];
|
|
44
|
+
if (!isEmittable(v, emittableCache)) continue;
|
|
45
|
+
if (!first) h.update(",");
|
|
46
|
+
first = false;
|
|
47
|
+
h.update(JSON.stringify(k));
|
|
48
|
+
h.update(":");
|
|
49
|
+
fingerprintInto(h, v, seen, emittableCache);
|
|
50
|
+
}
|
|
51
|
+
h.update("}");
|
|
52
|
+
}
|
|
53
|
+
seen.delete(value);
|
|
54
|
+
}
|
|
4
55
|
function fingerprint(input) {
|
|
5
|
-
const
|
|
6
|
-
|
|
56
|
+
const emittableCache = /* @__PURE__ */ new WeakMap();
|
|
57
|
+
if (!isEmittable(input, emittableCache)) return "";
|
|
58
|
+
const h = createHash("sha512");
|
|
59
|
+
fingerprintInto(h, input, /* @__PURE__ */ new WeakSet(), emittableCache);
|
|
60
|
+
return h.digest("hex");
|
|
7
61
|
}
|
|
8
62
|
//#endregion
|
|
9
63
|
export { fingerprint };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.js","names":[],"sources":["../../lib/util/fingerprint.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"fingerprint.js","names":[],"sources":["../../lib/util/fingerprint.ts"],"sourcesContent":["import { type Hash, createHash } from 'node:crypto';\n\n// Returns true when `value` would appear in the canonical JSON produced by\n// `safe-stable-stringify`. We pre-check before emitting because objects must\n// drop keys whose value resolves to nothing (incl. via toJSON → undefined),\n// and incremental hashing can't roll back already-emitted bytes.\n//\n// `cache` memoizes the result per object reference so callers that invoke\n// isEmittable just before recursing don't re-walk the toJSON chain twice.\nfunction isEmittable(value: unknown, cache: WeakMap<object, boolean>): boolean {\n if (\n value === undefined ||\n typeof value === 'function' ||\n typeof value === 'symbol'\n ) {\n return false;\n }\n if (value === null || typeof value !== 'object') {\n return true;\n }\n const cached = cache.get(value);\n if (cached !== undefined) {\n return cached;\n }\n const obj = value as { toJSON?: () => unknown };\n const result =\n typeof obj.toJSON === 'function' ? isEmittable(obj.toJSON(), cache) : true;\n cache.set(value, result);\n return result;\n}\n\n// Walks `value` and emits canonical JSON chunks directly into `h`,\n// matching `safe-stable-stringify` (deterministic mode) byte-for-byte\n// without materializing the full string. Required to avoid V8's max\n// string length when the input is large (e.g. a PR carrying upgrades\n// across hundreds of manifest files).\nfunction fingerprintInto(\n h: Hash,\n value: unknown,\n seen: WeakSet<object>,\n emittableCache: WeakMap<object, boolean>,\n): void {\n if (value === null || typeof value !== 'object') {\n h.update(JSON.stringify(value));\n return;\n }\n\n const obj = value as { toJSON?: () => unknown };\n if (typeof obj.toJSON === 'function') {\n fingerprintInto(h, obj.toJSON(), seen, emittableCache);\n return;\n }\n\n if (seen.has(value)) {\n h.update('\"[Circular]\"');\n return;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n h.update('[');\n for (let i = 0; i < value.length; i++) {\n if (i > 0) {\n h.update(',');\n }\n const item: unknown = value[i];\n if (isEmittable(item, emittableCache)) {\n fingerprintInto(h, item, seen, emittableCache);\n } else {\n h.update('null');\n }\n }\n h.update(']');\n } else {\n const entries = value as Record<string, unknown>;\n const keys = Object.keys(entries).sort();\n h.update('{');\n let first = true;\n for (const k of keys) {\n const v = entries[k];\n if (!isEmittable(v, emittableCache)) {\n continue;\n }\n if (!first) {\n h.update(',');\n }\n first = false;\n h.update(JSON.stringify(k));\n h.update(':');\n fingerprintInto(h, v, seen, emittableCache);\n }\n h.update('}');\n }\n seen.delete(value);\n}\n\nexport function fingerprint(input: unknown): string {\n const emittableCache = new WeakMap<object, boolean>();\n if (!isEmittable(input, emittableCache)) {\n return '';\n }\n const h = createHash('sha512');\n fingerprintInto(h, input, new WeakSet(), emittableCache);\n return h.digest('hex');\n}\n"],"mappings":";;AASA,SAAS,YAAY,OAAgB,OAA0C;CAC7E,IACE,UAAU,KAAA,KACV,OAAO,UAAU,cACjB,OAAO,UAAU,UAEjB,OAAO;CAET,IAAI,UAAU,QAAQ,OAAO,UAAU,UACrC,OAAO;CAET,MAAM,SAAS,MAAM,IAAI,KAAK;CAC9B,IAAI,WAAW,KAAA,GACb,OAAO;CAET,MAAM,MAAM;CACZ,MAAM,SACJ,OAAO,IAAI,WAAW,aAAa,YAAY,IAAI,OAAO,GAAG,KAAK,IAAI;CACxE,MAAM,IAAI,OAAO,MAAM;CACvB,OAAO;AACT;AAOA,SAAS,gBACP,GACA,OACA,MACA,gBACM;CACN,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;EAC/C,EAAE,OAAO,KAAK,UAAU,KAAK,CAAC;EAC9B;CACF;CAEA,MAAM,MAAM;CACZ,IAAI,OAAO,IAAI,WAAW,YAAY;EACpC,gBAAgB,GAAG,IAAI,OAAO,GAAG,MAAM,cAAc;EACrD;CACF;CAEA,IAAI,KAAK,IAAI,KAAK,GAAG;EACnB,EAAE,OAAO,gBAAc;EACvB;CACF;CACA,KAAK,IAAI,KAAK;CAEd,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,EAAE,OAAO,GAAG;EACZ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,IAAI,IAAI,GACN,EAAE,OAAO,GAAG;GAEd,MAAM,OAAgB,MAAM;GAC5B,IAAI,YAAY,MAAM,cAAc,GAClC,gBAAgB,GAAG,MAAM,MAAM,cAAc;QAE7C,EAAE,OAAO,MAAM;EAEnB;EACA,EAAE,OAAO,GAAG;CACd,OAAO;EACL,MAAM,UAAU;EAChB,MAAM,OAAO,OAAO,KAAK,OAAO,EAAE,KAAK;EACvC,EAAE,OAAO,GAAG;EACZ,IAAI,QAAQ;EACZ,KAAK,MAAM,KAAK,MAAM;GACpB,MAAM,IAAI,QAAQ;GAClB,IAAI,CAAC,YAAY,GAAG,cAAc,GAChC;GAEF,IAAI,CAAC,OACH,EAAE,OAAO,GAAG;GAEd,QAAQ;GACR,EAAE,OAAO,KAAK,UAAU,CAAC,CAAC;GAC1B,EAAE,OAAO,GAAG;GACZ,gBAAgB,GAAG,GAAG,MAAM,cAAc;EAC5C;EACA,EAAE,OAAO,GAAG;CACd;CACA,KAAK,OAAO,KAAK;AACnB;AAEA,SAAgB,YAAY,OAAwB;CAClD,MAAM,iCAAiB,IAAI,QAAyB;CACpD,IAAI,CAAC,YAAY,OAAO,cAAc,GACpC,OAAO;CAET,MAAM,IAAI,WAAW,QAAQ;CAC7B,gBAAgB,GAAG,uBAAO,IAAI,QAAQ,GAAG,cAAc;CACvD,OAAO,EAAE,OAAO,KAAK;AACvB"}
|
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": "43.206.
|
|
4
|
+
"version": "43.206.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"renovate": "dist/renovate.js",
|
|
@@ -124,6 +124,7 @@
|
|
|
124
124
|
"@sindresorhus/is": "8.1.0",
|
|
125
125
|
"@yarnpkg/core": "4.8.0",
|
|
126
126
|
"@yarnpkg/parsers": "3.0.3",
|
|
127
|
+
"adm-zip": "0.5.17",
|
|
127
128
|
"ae-cvss-calculator": "1.0.12",
|
|
128
129
|
"agentkeepalive": "4.6.0",
|
|
129
130
|
"async-mutex": "0.5.0",
|
|
@@ -146,7 +147,6 @@
|
|
|
146
147
|
"emojibase": "17.0.0",
|
|
147
148
|
"emojibase-regex": "17.0.0",
|
|
148
149
|
"execa": "8.0.1",
|
|
149
|
-
"extract-zip": "2.0.1",
|
|
150
150
|
"find-packages": "10.0.4",
|
|
151
151
|
"find-up": "8.0.0",
|
|
152
152
|
"fs-extra": "11.3.5",
|
|
@@ -219,6 +219,7 @@
|
|
|
219
219
|
"@openpgp/web-stream-tools": "0.3.1",
|
|
220
220
|
"@semantic-release/exec": "7.1.0",
|
|
221
221
|
"@smithy/util-stream": "4.6.4",
|
|
222
|
+
"@types/adm-zip": "0.5.8",
|
|
222
223
|
"@types/aws4": "1.11.6",
|
|
223
224
|
"@types/breejs__later": "4.1.5",
|
|
224
225
|
"@types/bunyan": "1.8.11",
|