From 861321fbbe9b9d4a73d30265b9268864ed207777 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Thu, 12 Dec 2024 16:40:20 -0300 Subject: [PATCH 01/26] test: Use correct fields for `PackageRule` type (#33072) --- lib/config/index.spec.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/config/index.spec.ts b/lib/config/index.spec.ts index d8d81d4e262213..13fd4ac4fc995b 100644 --- a/lib/config/index.spec.ts +++ b/lib/config/index.spec.ts @@ -32,14 +32,23 @@ describe('config/index', () => { it('merges packageRules', () => { const parentConfig = { ...defaultConfig }; Object.assign(parentConfig, { - packageRules: [{ a: 1 }, { a: 2 }], + packageRules: [ + { matchPackageNames: ['pkg1'] }, + { matchPackageNames: ['pkg2'] }, + ], }); const childConfig = { - packageRules: [{ a: 3 }, { a: 4 }], + packageRules: [ + { matchPackageNames: ['pkg3'] }, + { matchPackageNames: ['pkg4'] }, + ], }; const config = mergeChildConfig(parentConfig, childConfig); - expect(config.packageRules.map((rule) => rule.a)).toMatchObject([ - 1, 2, 3, 4, + expect(config.packageRules).toMatchObject([ + { matchPackageNames: ['pkg1'] }, + { matchPackageNames: ['pkg2'] }, + { matchPackageNames: ['pkg3'] }, + { matchPackageNames: ['pkg4'] }, ]); }); @@ -95,9 +104,15 @@ describe('config/index', () => { it('handles null child packageRules', () => { const parentConfig = { ...defaultConfig }; - parentConfig.packageRules = [{ a: 3 }, { a: 4 }]; + parentConfig.packageRules = [ + { matchPackageNames: ['pkg1'] }, + { matchPackageNames: ['pkg2'] }, + ]; const config = mergeChildConfig(parentConfig, {}); - expect(config.packageRules).toHaveLength(2); + expect(config.packageRules).toMatchObject([ + { matchPackageNames: ['pkg1'] }, + { matchPackageNames: ['pkg2'] }, + ]); }); it('handles undefined childConfig', () => { From f78d77827a03bcb64673f3e4ddd0a74d629c1706 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Thu, 12 Dec 2024 16:40:46 -0300 Subject: [PATCH 02/26] test: Remove snapshots for `massage.spec.ts` (#33071) --- lib/config/__snapshots__/massage.spec.ts.snap | 53 ------------------- lib/config/massage.spec.ts | 32 ++++++++++- 2 files changed, 30 insertions(+), 55 deletions(-) delete mode 100644 lib/config/__snapshots__/massage.spec.ts.snap diff --git a/lib/config/__snapshots__/massage.spec.ts.snap b/lib/config/__snapshots__/massage.spec.ts.snap deleted file mode 100644 index e27c6b089d0cbb..00000000000000 --- a/lib/config/__snapshots__/massage.spec.ts.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`config/massage massageConfig does not massage lockFileMaintenance 1`] = ` -{ - "packageRules": [ - { - "lockFileMaintenance": { - "enabled": true, - }, - "matchBaseBranches": [ - "release/ft10/1.9.x", - ], - "matchManagers": [ - "helmv3", - ], - "schedule": [ - "at any time", - ], - }, - ], -} -`; - -exports[`config/massage massageConfig massages packageRules matchUpdateTypes 1`] = ` -{ - "packageRules": [ - { - "matchPackageNames": [ - "foo", - ], - "separateMajorMinor": false, - }, - { - "matchPackageNames": [ - "foo", - ], - "matchUpdateTypes": [ - "minor", - ], - "semanticCommitType": "feat", - }, - { - "matchPackageNames": [ - "foo", - ], - "matchUpdateTypes": [ - "patch", - ], - "semanticCommitType": "fix", - }, - ], -} -`; diff --git a/lib/config/massage.spec.ts b/lib/config/massage.spec.ts index e4bccdb76c8b05..0fb0d48fe137b1 100644 --- a/lib/config/massage.spec.ts +++ b/lib/config/massage.spec.ts @@ -33,7 +33,24 @@ describe('config/massage', () => { ], }; const res = massage.massageConfig(config); - expect(res).toMatchSnapshot(); + expect(res).toEqual({ + packageRules: [ + { + matchPackageNames: ['foo'], + separateMajorMinor: false, + }, + { + matchPackageNames: ['foo'], + matchUpdateTypes: ['minor'], + semanticCommitType: 'feat', + }, + { + matchPackageNames: ['foo'], + matchUpdateTypes: ['patch'], + semanticCommitType: 'fix', + }, + ], + }); expect(res.packageRules).toHaveLength(3); }); @@ -64,7 +81,18 @@ describe('config/massage', () => { ], }; const res = massage.massageConfig(config); - expect(res).toMatchSnapshot(); + expect(res).toEqual({ + packageRules: [ + { + lockFileMaintenance: { + enabled: true, + }, + matchBaseBranches: ['release/ft10/1.9.x'], + matchManagers: ['helmv3'], + schedule: ['at any time'], + }, + ], + }); expect(res.packageRules).toHaveLength(1); }); }); From d094afeb823b4bcd8817317c7e4e1edb47a71626 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 13 Dec 2024 01:42:59 +0530 Subject: [PATCH 03/26] refactor(manager/custom): reorganize and update utility functions (#33050) --- docs/usage/configuration-options.md | 1 + lib/modules/manager/custom/regex/index.ts | 2 +- .../manager/custom/regex/strategies.ts | 29 ++-------- lib/modules/manager/custom/regex/utils.ts | 32 +---------- lib/modules/manager/custom/utils.ts | 57 +++++++++++++++++++ lib/modules/manager/devcontainer/extract.ts | 2 +- .../extract/extract-fingerprint-config.ts | 2 +- .../update/branch/auto-replace.spec.ts | 7 ++- 8 files changed, 73 insertions(+), 59 deletions(-) create mode 100644 lib/modules/manager/custom/utils.ts diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 0ce57dc796c43f..c6205f400ec79d 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -769,6 +769,7 @@ Example: "customManagers": [ { "customType": "regex", + "fileMatch": ["values.yaml$"], "matchStrings": [ "ENV .*?_VERSION=(?.*) # (?.*?)/(?.*?)\\s" ] diff --git a/lib/modules/manager/custom/regex/index.ts b/lib/modules/manager/custom/regex/index.ts index 00d9d79b8afcc9..bbd4268369b9ff 100644 --- a/lib/modules/manager/custom/regex/index.ts +++ b/lib/modules/manager/custom/regex/index.ts @@ -6,9 +6,9 @@ import type { PackageDependency, PackageFileContent, } from '../../types'; +import { validMatchFields } from '../utils'; import { handleAny, handleCombination, handleRecursive } from './strategies'; import type { RegexManagerConfig, RegexManagerTemplates } from './types'; -import { validMatchFields } from './utils'; export const categories: Category[] = ['custom']; diff --git a/lib/modules/manager/custom/regex/strategies.ts b/lib/modules/manager/custom/regex/strategies.ts index 2e489e43bf0598..6ff7218bb99af2 100644 --- a/lib/modules/manager/custom/regex/strategies.ts +++ b/lib/modules/manager/custom/regex/strategies.ts @@ -1,11 +1,10 @@ import is from '@sindresorhus/is'; -import { logger } from '../../../../logger'; import { regEx } from '../../../../util/regex'; import type { PackageDependency } from '../../types'; +import { checkIsValidDependency } from '../utils'; import type { RecursionParameter, RegexManagerConfig } from './types'; import { createDependency, - isValidDependency, mergeExtractionTemplate, mergeGroups, regexMatchAll, @@ -32,7 +31,7 @@ export function handleAny( ) .filter(is.truthy) .filter((dep: PackageDependency) => - checkIsValidDependency(dep, packageFile), + checkIsValidDependency(dep, packageFile, 'regex'), ); } @@ -61,7 +60,7 @@ export function handleCombination( return [createDependency(extraction, config)] .filter(is.truthy) .filter((dep: PackageDependency) => - checkIsValidDependency(dep, packageFile), + checkIsValidDependency(dep, packageFile, 'regex'), ); } @@ -84,7 +83,7 @@ export function handleRecursive( }) .filter(is.truthy) .filter((dep: PackageDependency) => - checkIsValidDependency(dep, packageFile), + checkIsValidDependency(dep, packageFile, 'regex'), ); } @@ -116,23 +115,3 @@ function processRecursive(parameters: RecursionParameter): PackageDependency[] { }); }); } - -function checkIsValidDependency( - dep: PackageDependency, - packageFile: string, -): boolean { - const isValid = isValidDependency(dep); - if (!isValid) { - const meta = { - packageDependency: dep, - packageFile, - }; - logger.trace( - meta, - 'Discovered a package dependency by matching regex, but it did not pass validation. Discarding', - ); - return isValid; - } - - return isValid; -} diff --git a/lib/modules/manager/custom/regex/utils.ts b/lib/modules/manager/custom/regex/utils.ts index 350f639d9da434..3714b1f42deafd 100644 --- a/lib/modules/manager/custom/regex/utils.ts +++ b/lib/modules/manager/custom/regex/utils.ts @@ -4,27 +4,14 @@ import { migrateDatasource } from '../../../../config/migrations/custom/datasour import { logger } from '../../../../logger'; import * as template from '../../../../util/template'; import type { PackageDependency } from '../../types'; +import type { ValidMatchFields } from '../utils'; +import { validMatchFields } from '../utils'; import type { ExtractionTemplate, RegexManagerConfig, RegexManagerTemplates, } from './types'; -export const validMatchFields = [ - 'depName', - 'packageName', - 'currentValue', - 'currentDigest', - 'datasource', - 'versioning', - 'extractVersion', - 'registryUrl', - 'depType', - 'indentation', -] as const; - -type ValidMatchFields = (typeof validMatchFields)[number]; - function updateDependency( dependency: PackageDependency, field: ValidMatchFields, @@ -119,18 +106,3 @@ export function mergeExtractionTemplate( replaceString: addition.replaceString ?? base.replaceString, }; } - -export function isValidDependency({ - depName, - currentValue, - currentDigest, - packageName, -}: PackageDependency): boolean { - // check if all the fields are set - return ( - (is.nonEmptyStringAndNotWhitespace(depName) || - is.nonEmptyStringAndNotWhitespace(packageName)) && - (is.nonEmptyStringAndNotWhitespace(currentDigest) || - is.nonEmptyStringAndNotWhitespace(currentValue)) - ); -} diff --git a/lib/modules/manager/custom/utils.ts b/lib/modules/manager/custom/utils.ts new file mode 100644 index 00000000000000..024ac0d078d4b3 --- /dev/null +++ b/lib/modules/manager/custom/utils.ts @@ -0,0 +1,57 @@ +import is from '@sindresorhus/is'; +import { logger } from '../../../logger'; +import type { PackageDependency } from '../types'; + +export const validMatchFields = [ + 'depName', + 'packageName', + 'currentValue', + 'currentDigest', + 'datasource', + 'versioning', + 'extractVersion', + 'registryUrl', + 'depType', + 'indentation', +] as const; + +export type ValidMatchFields = (typeof validMatchFields)[number]; + +export function isValidDependency({ + depName, + currentValue, + currentDigest, + packageName, + datasource, +}: PackageDependency): boolean { + // check if all the fields are set + return ( + (is.nonEmptyStringAndNotWhitespace(depName) || + is.nonEmptyStringAndNotWhitespace(packageName)) && + (is.nonEmptyStringAndNotWhitespace(currentDigest) || + is.nonEmptyStringAndNotWhitespace(currentValue)) && + is.nonEmptyStringAndNotWhitespace(datasource) + ); +} + +export function checkIsValidDependency( + dep: PackageDependency, + packageFile: string, + manager: string, +): boolean { + const isValid = isValidDependency(dep); + if (!isValid) { + const meta = { + packageDependency: dep, + packageFile, + manager, + }; + logger.trace( + meta, + 'Discovered a package dependency, but it did not pass validation. Discarding', + ); + return isValid; + } + + return isValid; +} diff --git a/lib/modules/manager/devcontainer/extract.ts b/lib/modules/manager/devcontainer/extract.ts index 489563507a8214..8e96f1eeca47d0 100644 --- a/lib/modules/manager/devcontainer/extract.ts +++ b/lib/modules/manager/devcontainer/extract.ts @@ -1,5 +1,5 @@ import { logger } from '../../../logger'; -import { isValidDependency } from '../custom/regex/utils'; +import { isValidDependency } from '../custom/utils'; import { getDep as getDockerDep } from '../dockerfile/extract'; import type { ExtractConfig, diff --git a/lib/workers/repository/extract/extract-fingerprint-config.ts b/lib/workers/repository/extract/extract-fingerprint-config.ts index 8d1ad76c1431e9..efeb296b0de532 100644 --- a/lib/workers/repository/extract/extract-fingerprint-config.ts +++ b/lib/workers/repository/extract/extract-fingerprint-config.ts @@ -3,8 +3,8 @@ import type { RenovateConfig } from '../../../config/types'; import { getEnabledManagersList } from '../../../modules/manager'; import { isCustomManager } from '../../../modules/manager/custom'; import type { RegexManagerTemplates } from '../../../modules/manager/custom/regex/types'; -import { validMatchFields } from '../../../modules/manager/custom/regex/utils'; import type { CustomExtractConfig } from '../../../modules/manager/custom/types'; +import { validMatchFields } from '../../../modules/manager/custom/utils'; import type { WorkerExtractConfig } from '../../types'; export interface FingerprintExtractConfig { diff --git a/lib/workers/repository/update/branch/auto-replace.spec.ts b/lib/workers/repository/update/branch/auto-replace.spec.ts index ee0b2c8e8abfb6..fb06f7bc23bc89 100644 --- a/lib/workers/repository/update/branch/auto-replace.spec.ts +++ b/lib/workers/repository/update/branch/auto-replace.spec.ts @@ -218,6 +218,7 @@ describe('workers/repository/update/branch/auto-replace', () => { upgrade.packageFile = '.gitlab-ci.yml'; upgrade.autoReplaceStringTemplate = "'{{{depName}}}'\nref: {{{newValue}}}"; + upgrade.datasourceTemplate = 'docker'; upgrade.matchStringsStrategy = 'combination'; // If the new "name" is not added to the matchStrings, the regex matcher fails to extract from `newContent` as @@ -237,7 +238,7 @@ describe('workers/repository/update/branch/auto-replace', () => { ); }); - it('fails with oldversion in depname', async () => { + it('fails with oldversion in depName', async () => { const yml = 'image: "1111111111.dkr.ecr.us-east-1.amazonaws.com/my-repository:1"\n\n'; upgrade.manager = 'regex'; @@ -252,6 +253,7 @@ describe('workers/repository/update/branch/auto-replace', () => { upgrade.matchStrings = [ 'image:\\s*\\\'?\\"?(?[^:]+):(?[^\\s\\\'\\"]+)\\\'?\\"?\\s*', ]; + upgrade.datasourceTemplate = 'docker'; const res = doAutoReplace(upgrade, yml, reuseExistingBranch); await expect(res).rejects.toThrow(WORKER_FILE_UPDATE_FAILED); }); @@ -316,6 +318,7 @@ describe('workers/repository/update/branch/auto-replace', () => { upgrade.matchStrings = [ 'image:\\s*\\\'?\\"?(?[^:]+):(?[^\\s\\\'\\"]+)\\\'?\\"?\\s*', ]; + upgrade.datasourceTemplate = 'docker'; const res = await doAutoReplace(upgrade, yml, reuseExistingBranch); expect(res).toBe(yml); }); @@ -1190,6 +1193,7 @@ describe('workers/repository/update/branch/auto-replace', () => { upgrade.matchStrings = [ 'image:\\s*?\\\'?\\"?(?[^:\\\'\\"]+):(?[^@\\\'\\"]+)@?(?[^\\s\\\'\\"]+)?\\"?\\\'?\\s*', ]; + upgrade.datasourceTemplate = 'docker'; const res = await doAutoReplace(upgrade, yml, reuseExistingBranch); expect(res).toBe('image: "some.other.url.com/some-new-repo:3.16"'); }); @@ -1213,6 +1217,7 @@ describe('workers/repository/update/branch/auto-replace', () => { upgrade.matchStrings = [ 'image:\\s*[\\\'\\"]?(?[^:]+):(?[^@]+)?@?(?[^\\s\\\'\\"]+)?[\\\'\\"]?\\s*', ]; + upgrade.datasourceTemplate = 'docker'; const res = await doAutoReplace(upgrade, yml, reuseExistingBranch); expect(res).toBe( 'image: "some.other.url.com/some-new-repo:3.16@sha256:p0o9i8u7z6t5r4e3w2q1"', From eb074924655488bbd62dba7f55e75bfb925e0f94 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 13 Dec 2024 01:53:03 +0530 Subject: [PATCH 04/26] fix(config/inherit): resolve presets (#31642) Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> Co-authored-by: Rhys Arkins --- docs/usage/config-overview.md | 13 ++ lib/workers/repository/init/inherited.spec.ts | 136 +++++++++++++++++- lib/workers/repository/init/inherited.ts | 40 +++++- 3 files changed, 187 insertions(+), 2 deletions(-) diff --git a/docs/usage/config-overview.md b/docs/usage/config-overview.md index 99d6b40c96a26f..669e15ea87607b 100644 --- a/docs/usage/config-overview.md +++ b/docs/usage/config-overview.md @@ -159,6 +159,19 @@ Inherited config may use all Repository config settings, and any Global config o For information on how the Mend Renovate App supports Inherited config, see the dedicated "Mend Renovate App Config" section toward the end of this page. +#### Presets handling + +If the inherited config contains `extends` presets, then Renovate will: + +1. Resolve the presets +1. Add the resolved preset config to the beginning of the inherited config +1. Merge the presets on top of the global config + +##### You can not ignore presets from inherited config + +You can _not_ use `ignorePresets` in your repository config to ignore presets _within_ inherited config. +This is because inherited config is resolved _before_ the repository config. + ### Repository config Repository config is the config loaded from a config file in the repository. diff --git a/lib/workers/repository/init/inherited.spec.ts b/lib/workers/repository/init/inherited.spec.ts index f89c18201649c8..e31f5ba2fc32bf 100644 --- a/lib/workers/repository/init/inherited.spec.ts +++ b/lib/workers/repository/init/inherited.spec.ts @@ -1,5 +1,7 @@ -import { platform } from '../../../../test/util'; +import { mocked, platform } from '../../../../test/util'; +import * as presets_ from '../../../config/presets'; import type { RenovateConfig } from '../../../config/types'; +import * as validation from '../../../config/validation'; import { CONFIG_INHERIT_NOT_FOUND, CONFIG_INHERIT_PARSE_ERROR, @@ -8,6 +10,10 @@ import { import { logger } from '../../../logger'; import { mergeInheritedConfig } from './inherited'; +jest.mock('../../../config/presets'); + +const presets = mocked(presets_); + describe('workers/repository/init/inherited', () => { let config: RenovateConfig; @@ -84,4 +90,132 @@ describe('workers/repository/init/inherited', () => { expect(res.onboarding).toBeFalse(); expect(logger.warn).not.toHaveBeenCalled(); }); + + it('should resolve presets found in inherited config', async () => { + platform.getRawFile.mockResolvedValue( + '{"onboarding":false,"labels":["test"],"extends":[":automergeAll"]}', + ); + presets.resolveConfigPresets.mockResolvedValue({ + onboarding: false, + labels: ['test'], + automerge: true, + }); + const res = await mergeInheritedConfig(config); + expect(res.labels).toEqual(['test']); + expect(res.onboarding).toBeFalse(); + expect(logger.warn).not.toHaveBeenCalled(); + expect(logger.debug).toHaveBeenCalledWith( + 'Resolving presets found in inherited config', + ); + }); + + it('should warn if presets fails validation with warnings', async () => { + platform.getRawFile.mockResolvedValue( + '{"onboarding":false,"labels":["test"],"extends":[":automergeAll"]}', + ); + jest + .spyOn(validation, 'validateConfig') + .mockResolvedValueOnce({ + warnings: [], + errors: [], + }) + .mockResolvedValueOnce({ + warnings: [ + { + message: 'some warning', + topic: 'Configuration Error', + }, + ], + errors: [], + }); + presets.resolveConfigPresets.mockResolvedValue({ + onboarding: false, + labels: ['test'], + automerge: true, + }); + const res = await mergeInheritedConfig(config); + expect(res.binarySource).toBeUndefined(); + expect(logger.warn).toHaveBeenCalledWith( + { + warnings: [ + { + message: 'some warning', + topic: 'Configuration Error', + }, + ], + }, + 'Found warnings in presets inside the inherited configuration.', + ); + }); + + it('should throw error if presets fails validation with errors', async () => { + platform.getRawFile.mockResolvedValue( + '{"labels":["test"],"extends":[":automergeAll"]}', + ); + jest + .spyOn(validation, 'validateConfig') + .mockResolvedValueOnce({ + warnings: [], + errors: [], + }) + .mockResolvedValueOnce({ + warnings: [], + errors: [ + { + message: 'some error', + topic: 'Configuration Error', + }, + ], + }); + presets.resolveConfigPresets.mockResolvedValue({ + labels: ['test'], + automerge: true, + }); + await expect(mergeInheritedConfig(config)).rejects.toThrow( + CONFIG_VALIDATION, + ); + expect(logger.warn).toHaveBeenCalledWith( + { + errors: [ + { + message: 'some error', + topic: 'Configuration Error', + }, + ], + }, + 'Found errors in presets inside the inherited configuration.', + ); + }); + + it('should remove global config from presets found in inherited config', async () => { + platform.getRawFile.mockResolvedValue( + '{"labels":["test"],"extends":[":automergeAll"]}', + ); + jest.spyOn(validation, 'validateConfig').mockResolvedValue({ + warnings: [], + errors: [], + }); + presets.resolveConfigPresets.mockResolvedValue({ + labels: ['test'], + automerge: true, + binarySource: 'docker', // global config option: should not be here + }); + const res = await mergeInheritedConfig(config); + expect(res.labels).toEqual(['test']); + expect(logger.warn).not.toHaveBeenCalled(); + expect(logger.debug).toHaveBeenCalledWith( + { + inheritedConfig: { + labels: ['test'], + automerge: true, + binarySource: 'docker', + }, + filteredConfig: { + labels: ['test'], + automerge: true, + }, + }, + 'Removed global config from inherited config presets.', + ); + }); }); diff --git a/lib/workers/repository/init/inherited.ts b/lib/workers/repository/init/inherited.ts index f25be4f3f3169e..d924ff825bd37d 100644 --- a/lib/workers/repository/init/inherited.ts +++ b/lib/workers/repository/init/inherited.ts @@ -2,6 +2,7 @@ import is from '@sindresorhus/is'; import { dequal } from 'dequal'; import { mergeChildConfig, removeGlobalConfig } from '../../../config'; import { parseFileConfig } from '../../../config/parse'; +import { resolveConfigPresets } from '../../../config/presets'; import type { RenovateConfig } from '../../../config/types'; import { validateConfig } from '../../../config/validation'; import { @@ -92,12 +93,49 @@ export async function mergeInheritedConfig( 'Found warnings in inherited configuration.', ); } - const filteredConfig = removeGlobalConfig(inheritedConfig, true); + let filteredConfig = removeGlobalConfig(inheritedConfig, true); if (!dequal(inheritedConfig, filteredConfig)) { logger.debug( { inheritedConfig, filteredConfig }, 'Removed global config from inherited config.', ); } + + if (is.nullOrUndefined(filteredConfig.extends)) { + return mergeChildConfig(config, filteredConfig); + } + + logger.debug('Resolving presets found in inherited config'); + const resolvedConfig = await resolveConfigPresets( + filteredConfig, + config, + config.ignorePresets, + ); + logger.trace({ config: resolvedConfig }, 'Resolved inherited config'); + + const validationRes = await validateConfig('inherit', resolvedConfig); + if (validationRes.errors.length) { + logger.warn( + { errors: validationRes.errors }, + 'Found errors in presets inside the inherited configuration.', + ); + throw new Error(CONFIG_VALIDATION); + } + if (validationRes.warnings.length) { + logger.warn( + { warnings: validationRes.warnings }, + 'Found warnings in presets inside the inherited configuration.', + ); + } + + // remove global config options once again, as resolved presets could have added some + filteredConfig = removeGlobalConfig(resolvedConfig, true); + if (!dequal(resolvedConfig, filteredConfig)) { + logger.debug( + { inheritedConfig: resolvedConfig, filteredConfig }, + 'Removed global config from inherited config presets.', + ); + } + return mergeChildConfig(config, filteredConfig); } From 955229edfeb3dc61ba704d699f89b26899ea2b66 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:46:57 +0000 Subject: [PATCH 05/26] chore(deps): update github/codeql-action action to v3.27.8 (#33074) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- .github/workflows/trivy.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 21a87761e58cdf..f8f998b227bba2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/init@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 with: languages: javascript @@ -51,7 +51,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/autobuild@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -65,4 +65,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/analyze@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a1ff96abf20226..92e36ed039660e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -51,6 +51,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + uses: github/codeql-action/upload-sarif@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 with: sarif_file: results.sarif diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 827760089e89e8..384d273da8cb6f 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -31,7 +31,7 @@ jobs: format: 'sarif' output: 'trivy-results.sarif' - - uses: github/codeql-action/upload-sarif@babb554ede22fd5605947329c4d04d8e7a0b8155 # v3.27.7 + - uses: github/codeql-action/upload-sarif@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 with: sarif_file: trivy-results.sarif category: 'docker-image-${{ matrix.tag }}' From 2a51500ed72f0fcf10f3ffd1ae95d2429d6c9a60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:09:53 +0000 Subject: [PATCH 06/26] chore(deps): update github/codeql-action action to v3.27.9 (#33077) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- .github/workflows/trivy.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f8f998b227bba2..75e0567225d421 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 + uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: languages: javascript @@ -51,7 +51,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 + uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -65,4 +65,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 + uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 92e36ed039660e..de03e2e09ecfd4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -51,6 +51,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: sarif_file: results.sarif diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 384d273da8cb6f..36bfabaa8bd3fd 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -31,7 +31,7 @@ jobs: format: 'sarif' output: 'trivy-results.sarif' - - uses: github/codeql-action/upload-sarif@8a93837afdf1873301a68d777844b43e98cd4313 # v3.27.8 + - uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: sarif_file: trivy-results.sarif category: 'docker-image-${{ matrix.tag }}' From d63ff715cd72891c30faf4c61e9645bff5422e10 Mon Sep 17 00:00:00 2001 From: Janus Troelsen Date: Fri, 13 Dec 2024 01:17:26 -0600 Subject: [PATCH 07/26] feat(datasource): add Hackage datasource (#32944) Co-authored-by: Sebastian Poxhofer --- lib/modules/datasource/api.ts | 2 + lib/modules/datasource/hackage/index.spec.ts | 57 ++++++++++++++++++++ lib/modules/datasource/hackage/index.ts | 54 +++++++++++++++++++ lib/modules/datasource/hackage/readme.md | 7 +++ lib/modules/datasource/hackage/schema.ts | 3 ++ 5 files changed, 123 insertions(+) create mode 100644 lib/modules/datasource/hackage/index.spec.ts create mode 100644 lib/modules/datasource/hackage/index.ts create mode 100644 lib/modules/datasource/hackage/readme.md create mode 100644 lib/modules/datasource/hackage/schema.ts diff --git a/lib/modules/datasource/api.ts b/lib/modules/datasource/api.ts index a9839f4f7a11de..e7284442c0a36b 100644 --- a/lib/modules/datasource/api.ts +++ b/lib/modules/datasource/api.ts @@ -38,6 +38,7 @@ import { GlasskubePackagesDatasource } from './glasskube-packages'; import { GoDatasource } from './go'; import { GolangVersionDatasource } from './golang-version'; import { GradleVersionDatasource } from './gradle-version'; +import { HackageDatasource } from './hackage'; import { HelmDatasource } from './helm'; import { HermitDatasource } from './hermit'; import { HexDatasource } from './hex'; @@ -111,6 +112,7 @@ api.set(GlasskubePackagesDatasource.id, new GlasskubePackagesDatasource()); api.set(GoDatasource.id, new GoDatasource()); api.set(GolangVersionDatasource.id, new GolangVersionDatasource()); api.set(GradleVersionDatasource.id, new GradleVersionDatasource()); +api.set(HackageDatasource.id, new HackageDatasource()); api.set(HelmDatasource.id, new HelmDatasource()); api.set(HermitDatasource.id, new HermitDatasource()); api.set(HexDatasource.id, new HexDatasource()); diff --git a/lib/modules/datasource/hackage/index.spec.ts b/lib/modules/datasource/hackage/index.spec.ts new file mode 100644 index 00000000000000..676e082583da48 --- /dev/null +++ b/lib/modules/datasource/hackage/index.spec.ts @@ -0,0 +1,57 @@ +import { getPkgReleases } from '..'; +import * as httpMock from '../../../../test/http-mock'; +import { HackageDatasource, versionToRelease } from './index'; + +const baseUrl = 'https://hackage.haskell.org/'; + +describe('modules/datasource/hackage/index', () => { + describe('versionToRelease', () => { + it('should make release with given version', () => { + expect( + versionToRelease('3.1.0', 'base', 'http://localhost').version, + ).toBe('3.1.0'); + }); + }); + + describe('getReleases', () => { + it('return null with empty registryUrl', async () => { + expect( + await new HackageDatasource().getReleases({ + packageName: 'base', + registryUrl: undefined, + }), + ).toBeNull(); + }); + + it('returns null for 404', async () => { + httpMock.scope(baseUrl).get('/package/base.json').reply(404); + expect( + await getPkgReleases({ + datasource: HackageDatasource.id, + packageName: 'base', + }), + ).toBeNull(); + }); + + it('returns release for 200', async () => { + httpMock + .scope(baseUrl) + .get('/package/base.json') + .reply(200, { '4.20.0.1': 'normal' }); + expect( + await getPkgReleases({ + datasource: HackageDatasource.id, + packageName: 'base', + }), + ).toEqual({ + registryUrl: baseUrl, + releases: [ + { + changelogUrl: baseUrl + 'package/base-4.20.0.1/changelog', + version: '4.20.0.1', + }, + ], + }); + }); + }); +}); diff --git a/lib/modules/datasource/hackage/index.ts b/lib/modules/datasource/hackage/index.ts new file mode 100644 index 00000000000000..4a75568d485468 --- /dev/null +++ b/lib/modules/datasource/hackage/index.ts @@ -0,0 +1,54 @@ +import is from '@sindresorhus/is'; +import { joinUrlParts } from '../../../util/url'; +import * as pvpVersioning from '../../versioning/pvp'; +import { Datasource } from '../datasource'; +import type { GetReleasesConfig, Release, ReleaseResult } from '../types'; +import { HackagePackageMetadata } from './schema'; + +export class HackageDatasource extends Datasource { + static readonly id = 'hackage'; + + constructor() { + super(HackageDatasource.id); + } + + override readonly defaultVersioning = pvpVersioning.id; + override readonly customRegistrySupport = false; + override readonly defaultRegistryUrls = ['https://hackage.haskell.org/']; + + async getReleases(config: GetReleasesConfig): Promise { + const { registryUrl, packageName } = config; + if (!is.nonEmptyString(registryUrl)) { + return null; + } + const massagedPackageName = encodeURIComponent(packageName); + const url = joinUrlParts( + registryUrl, + 'package', + `${massagedPackageName}.json`, + ); + const res = await this.http.getJson(url, HackagePackageMetadata); + const keys = Object.keys(res.body); + return { + releases: keys.map((version) => + versionToRelease(version, packageName, registryUrl), + ), + }; + } +} + +export function versionToRelease( + version: string, + packageName: string, + registryUrl: string, +): Release { + return { + version, + changelogUrl: joinUrlParts( + registryUrl, + 'package', + `${packageName}-${version}`, + 'changelog', + ), + }; +} diff --git a/lib/modules/datasource/hackage/readme.md b/lib/modules/datasource/hackage/readme.md new file mode 100644 index 00000000000000..d7e56e14b844c1 --- /dev/null +++ b/lib/modules/datasource/hackage/readme.md @@ -0,0 +1,7 @@ +This datasource uses +[the Hackage JSON API](https://hackage.haskell.org/api#package-info-json) +to fetch versions for published Haskell packages. + +While not all versions use [PVP](https://pvp.haskell.org), the majority does. +This manager assumes a default versioning set to PVP. +Versioning can be overwritten using `packageRules`, e.g. with `matchDatasources`. diff --git a/lib/modules/datasource/hackage/schema.ts b/lib/modules/datasource/hackage/schema.ts new file mode 100644 index 00000000000000..dcee186743c602 --- /dev/null +++ b/lib/modules/datasource/hackage/schema.ts @@ -0,0 +1,3 @@ +import { z } from 'zod'; + +export const HackagePackageMetadata = z.record(z.string()); From 44c83b0901a4a835c1c667d3b33220da1d835766 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Fri, 13 Dec 2024 12:31:15 +0100 Subject: [PATCH 08/26] feat: raise error when encrypted + no privateKey (#33085) --- docs/usage/self-hosted-experimental.md | 4 ++++ lib/config/decrypt.spec.ts | 10 ++++++++++ lib/config/decrypt.ts | 11 ++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md index 61629fab747cda..f80219fd96fde9 100644 --- a/docs/usage/self-hosted-experimental.md +++ b/docs/usage/self-hosted-experimental.md @@ -39,6 +39,10 @@ This includes the following: If set to any value, Renovate will stop using the Docker Hub API (`https://hub.docker.com`) to fetch tags and instead use the normal Docker API for images pulled from `https://index.docker.io`. +## `RENOVATE_X_ENCRYPTED_STRICT` + +If set to `"true"`, a config error Issue will be raised in case repository config contains `encrypted` objects without any `privateKey` defined. + ## `RENOVATE_X_EXEC_GPID_HANDLE` If set, Renovate will terminate the whole process group of a terminated child process spawned by Renovate. diff --git a/lib/config/decrypt.spec.ts b/lib/config/decrypt.spec.ts index 66d73753ebb267..3a056690dba2eb 100644 --- a/lib/config/decrypt.spec.ts +++ b/lib/config/decrypt.spec.ts @@ -12,6 +12,7 @@ describe('config/decrypt', () => { beforeEach(() => { config = {}; GlobalConfig.reset(); + delete process.env.RENOVATE_X_ENCRYPTED_STRICT; }); it('returns empty with no privateKey', async () => { @@ -30,5 +31,14 @@ describe('config/decrypt', () => { expect(res.encrypted).toBeUndefined(); expect(res.a).toBeUndefined(); }); + + it('throws exception if encrypted found but no privateKey', async () => { + config.encrypted = { a: '1' }; + process.env.RENOVATE_X_ENCRYPTED_STRICT = 'true'; + + await expect(decryptConfig(config, repository)).rejects.toThrow( + 'config-validation', + ); + }); }); }); diff --git a/lib/config/decrypt.ts b/lib/config/decrypt.ts index ac560c4d456a45..80cddcd490830a 100644 --- a/lib/config/decrypt.ts +++ b/lib/config/decrypt.ts @@ -1,4 +1,5 @@ import is from '@sindresorhus/is'; +import { CONFIG_VALIDATION } from '../constants/error-messages'; import { logger } from '../logger'; import { regEx } from '../util/regex'; import { addSecretForSanitizing } from '../util/sanitize'; @@ -173,7 +174,15 @@ export async function decryptConfig( } } } else { - logger.error('Found encrypted data but no privateKey'); + if (process.env.RENOVATE_X_ENCRYPTED_STRICT === 'true') { + const error = new Error(CONFIG_VALIDATION); + error.validationSource = 'config'; + error.validationError = 'Encrypted config unsupported'; + error.validationMessage = `This config contains an encrypted object at location \`$.${key}\` but no privateKey is configured. To support encrypted config, the Renovate administrator must configure a \`privateKey\` in Global Configuration.`; + throw error; + } else { + logger.error('Found encrypted data but no privateKey'); + } } delete decryptedConfig.encrypted; } else if (is.array(val)) { From f8b436d0cf187f64d3d6a922a1863cc89b60fb9d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:01:21 +0000 Subject: [PATCH 09/26] chore(deps): update ghcr.io/containerbase/devcontainer docker tag to v13.4.1 (#33091) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3c2f85da2579fa..5aa64074f63664 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1 +1 @@ -FROM ghcr.io/containerbase/devcontainer:13.4.0 +FROM ghcr.io/containerbase/devcontainer:13.4.1 From 0092db9d543d2377b94e9cd9e1545977048276c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:01:22 +0000 Subject: [PATCH 10/26] fix(deps): update ghcr.io/containerbase/sidecar docker tag to v13.4.1 (#33092) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- lib/config/options/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index b74c49d23e9c87..664e97152841d6 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -515,7 +515,7 @@ const options: RenovateOptions[] = [ description: 'Change this value to override the default Renovate sidecar image.', type: 'string', - default: 'ghcr.io/containerbase/sidecar:13.4.0', + default: 'ghcr.io/containerbase/sidecar:13.4.1', globalOnly: true, }, { From 60f1caa56f8e64d116d3ac4f9d6d0d3865afb494 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:33:39 +0000 Subject: [PATCH 11/26] chore(deps): update pnpm to v9.15.0 (#33094) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 271cb44e5c4b45..3310152fbb0f0e 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ }, "volta": { "node": "22.11.0", - "pnpm": "9.14.4" + "pnpm": "9.15.0" }, "dependencies": { "@aws-sdk/client-codecommit": "3.699.0", @@ -351,7 +351,7 @@ "typescript": "5.7.2", "unified": "9.2.2" }, - "packageManager": "pnpm@9.14.4", + "packageManager": "pnpm@9.15.0", "files": [ "dist", "renovate-schema.json" From ba5e4daf03dd559b1139b9d60b17c72b2a0c1569 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:58:34 +0000 Subject: [PATCH 12/26] chore(deps): update ghcr.io/containerbase/devcontainer docker tag to v13.4.2 (#33100) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5aa64074f63664..3f088d2e94b969 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1 +1 @@ -FROM ghcr.io/containerbase/devcontainer:13.4.1 +FROM ghcr.io/containerbase/devcontainer:13.4.2 From 0633b79d188956f69207066fd4c7545daa819e4d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:02:26 +0000 Subject: [PATCH 13/26] fix(deps): update ghcr.io/containerbase/sidecar docker tag to v13.4.2 (#33101) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- lib/config/options/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 664e97152841d6..a87d3d8a916df7 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -515,7 +515,7 @@ const options: RenovateOptions[] = [ description: 'Change this value to override the default Renovate sidecar image.', type: 'string', - default: 'ghcr.io/containerbase/sidecar:13.4.1', + default: 'ghcr.io/containerbase/sidecar:13.4.2', globalOnly: true, }, { From 3d86982ccb1ce44826521b9370d2c9bb7a8b5be9 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Fri, 13 Dec 2024 17:43:41 -0300 Subject: [PATCH 14/26] fix(go): Better condition for quitting major versions fetch loop (#33102) --- lib/modules/datasource/go/releases-goproxy.spec.ts | 6 +----- lib/modules/datasource/go/releases-goproxy.ts | 8 +++++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/modules/datasource/go/releases-goproxy.spec.ts b/lib/modules/datasource/go/releases-goproxy.spec.ts index 1c3abe6cf1a42a..de9313b8c575c4 100644 --- a/lib/modules/datasource/go/releases-goproxy.spec.ts +++ b/lib/modules/datasource/go/releases-goproxy.spec.ts @@ -602,8 +602,6 @@ describe('modules/datasource/go/releases-goproxy', () => { .get('/@v/list') .reply(200) .get('/@latest') - .reply(404) - .get('/v2/@v/list') .reply(404); const res = await datasource.getReleases({ @@ -621,9 +619,7 @@ describe('modules/datasource/go/releases-goproxy', () => { .get('/@v/list') .reply(200) .get('/@latest') - .reply(200, { Version: 'v0.0.0-20230905200255-921286631fa9' }) - .get('/v2/@v/list') - .reply(404); + .reply(200, { Version: 'v0.0.0-20230905200255-921286631fa9' }); const res = await datasource.getReleases({ packageName: 'github.com/google/btree', diff --git a/lib/modules/datasource/go/releases-goproxy.ts b/lib/modules/datasource/go/releases-goproxy.ts index a196a4311ec767..951a857afab056 100644 --- a/lib/modules/datasource/go/releases-goproxy.ts +++ b/lib/modules/datasource/go/releases-goproxy.ts @@ -213,9 +213,11 @@ export class GoProxyDatasource extends Datasource { major += 1; // v0 and v1 are the same module } + let releases: Release[] = []; + try { const res = await this.listVersions(baseUrl, pkg); - const releases = await p.map(res, async (versionInfo) => { + releases = await p.map(res, async (versionInfo) => { const { version, newDigest, releaseTimestamp } = versionInfo; if (releaseTimestamp) { @@ -258,6 +260,10 @@ export class GoProxyDatasource extends Datasource { } } } + + if (!releases.length) { + break; + } } return result; From ebfc4db9a0c02d9915188d2ca63559761e630bd5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 20:57:20 +0000 Subject: [PATCH 15/26] feat(deps): update ghcr.io/renovatebot/base-image docker tag to v9.22.1 (#33103) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- tools/docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index a27f7c00bbc346..cb627854eec5fb 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -5,19 +5,19 @@ ARG BASE_IMAGE_TYPE=slim # -------------------------------------- # slim image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.21.1@sha256:37080986a759161b3a22f153e4d0aeb7e3a859caba376eff894f27e185e32372 AS slim-base +FROM ghcr.io/renovatebot/base-image:9.22.1@sha256:890df0216c9e2bcf668f78cb10408bcc995982b3a5187fe4c2e5e3b3373a542e AS slim-base # -------------------------------------- # full image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.21.1-full@sha256:442c8d1c0ed51bf7b6d1cb18d0779736158c2fb789b91ab9be11ed0d3669e3a1 AS full-base +FROM ghcr.io/renovatebot/base-image:9.22.1-full@sha256:d2873fcf84adcfb12d3d7fd3e678919eb09ae9ba108e739328c37df047778081 AS full-base ENV RENOVATE_BINARY_SOURCE=global # -------------------------------------- # build image # -------------------------------------- -FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.21.1@sha256:37080986a759161b3a22f153e4d0aeb7e3a859caba376eff894f27e185e32372 AS build +FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.22.1@sha256:890df0216c9e2bcf668f78cb10408bcc995982b3a5187fe4c2e5e3b3373a542e AS build # We want a specific node version here # renovate: datasource=node-version From 0552d987b6d1abdabad36d2b36034ec6e06b1873 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 01:13:43 +0000 Subject: [PATCH 16/26] fix(deps): update ghcr.io/renovatebot/base-image docker tag to v9.22.2 (#33106) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- tools/docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index cb627854eec5fb..497c7632bdcbec 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -5,19 +5,19 @@ ARG BASE_IMAGE_TYPE=slim # -------------------------------------- # slim image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.22.1@sha256:890df0216c9e2bcf668f78cb10408bcc995982b3a5187fe4c2e5e3b3373a542e AS slim-base +FROM ghcr.io/renovatebot/base-image:9.22.2@sha256:ef4c8e2eebad1ff876e1d1ad7292070c20df96d08e8a62cb0eb3cfd60a3943e6 AS slim-base # -------------------------------------- # full image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.22.1-full@sha256:d2873fcf84adcfb12d3d7fd3e678919eb09ae9ba108e739328c37df047778081 AS full-base +FROM ghcr.io/renovatebot/base-image:9.22.2-full@sha256:40914939b7dda15dd472c34da99906c6d8a006958eaae749e3ff57a8eba72649 AS full-base ENV RENOVATE_BINARY_SOURCE=global # -------------------------------------- # build image # -------------------------------------- -FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.22.1@sha256:890df0216c9e2bcf668f78cb10408bcc995982b3a5187fe4c2e5e3b3373a542e AS build +FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.22.2@sha256:ef4c8e2eebad1ff876e1d1ad7292070c20df96d08e8a62cb0eb3cfd60a3943e6 AS build # We want a specific node version here # renovate: datasource=node-version From 3c37e662206db201258a8f7ba96f87bd7a3611b7 Mon Sep 17 00:00:00 2001 From: Julien Tanay Date: Sat, 14 Dec 2024 07:42:34 +0100 Subject: [PATCH 17/26] feat(preset): add LinkifyJS monorepo (#33097) --- lib/data/monorepo.json | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/data/monorepo.json b/lib/data/monorepo.json index 0d038bbafa237f..a1dead298aa1f4 100644 --- a/lib/data/monorepo.json +++ b/lib/data/monorepo.json @@ -360,6 +360,7 @@ "lerna-lite": "https://github.com/lerna-lite/lerna-lite", "lexical": "https://github.com/facebook/lexical", "linguijs": "https://github.com/lingui/js-lingui", + "linkifyjs": "https://github.com/nfrasser/linkifyjs", "log4j2": "https://github.com/apache/logging-log4j2", "logback": "https://github.com/qos-ch/logback", "loopback": [ From 8d00693d5638a6a94002bf241e40005c5d496e01 Mon Sep 17 00:00:00 2001 From: Julien Tanay Date: Sat, 14 Dec 2024 07:42:48 +0100 Subject: [PATCH 18/26] feat(preset): add happy-dom monorepo (#33098) --- lib/data/monorepo.json | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/data/monorepo.json b/lib/data/monorepo.json index a1dead298aa1f4..352ce8df6d83a2 100644 --- a/lib/data/monorepo.json +++ b/lib/data/monorepo.json @@ -321,6 +321,7 @@ "grpc-java": "https://github.com/grpc/grpc-java", "gstreamer-rust": "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", "guava": "https://github.com/google/guava", + "happy-dom": "https://github.com/capricorn86/happy-dom", "Hangfire": "https://github.com/HangfireIO/Hangfire", "hickory-dns": "https://github.com/hickory-dns/hickory-dns", "infrastructure-ui": "https://github.com/instructure/instructure-ui", From 9d3f7e63b37d5ca723aa74a841b29a88307e670a Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 14 Dec 2024 08:59:29 +0100 Subject: [PATCH 19/26] feat(config): global:safeEnv (#33096) --- lib/config/options/index.ts | 1 + lib/config/presets/internal/global.ts | 11 +++++++++++ lib/config/presets/internal/index.spec.ts | 3 ++- lib/config/presets/internal/index.ts | 2 ++ lib/config/presets/parse.ts | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 lib/config/presets/internal/global.ts diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index a87d3d8a916df7..8310f685b96481 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -52,6 +52,7 @@ const options: RenovateOptions[] = [ subType: 'string', globalOnly: true, patternMatch: true, + mergeable: true, }, { name: 'detectGlobalManagerConfig', diff --git a/lib/config/presets/internal/global.ts b/lib/config/presets/internal/global.ts new file mode 100644 index 00000000000000..aaf331d81e69c5 --- /dev/null +++ b/lib/config/presets/internal/global.ts @@ -0,0 +1,11 @@ +import type { Preset } from '../types'; + +/* eslint sort-keys: ["error", "asc", {caseSensitive: false, natural: true}] */ + +export const presets: Record = { + safeEnv: { + allowedEnv: ['GO*'], + description: + 'Hopefully safe environment variables to allow users to configure.', + }, +}; diff --git a/lib/config/presets/internal/index.spec.ts b/lib/config/presets/internal/index.spec.ts index 1b978f01d0d2b4..76f4d3572550e8 100644 --- a/lib/config/presets/internal/index.spec.ts +++ b/lib/config/presets/internal/index.spec.ts @@ -30,7 +30,8 @@ describe('config/presets/internal/index', () => { const config = await resolveConfigPresets( massageConfig(presetConfig), ); - const res = await validateConfig('repo', config, true); + const configType = groupName === 'global' ? 'global' : 'repo'; + const res = await validateConfig(configType, config, true); expect(res.errors).toHaveLength(0); expect(res.warnings).toHaveLength(0); } catch (err) { diff --git a/lib/config/presets/internal/index.ts b/lib/config/presets/internal/index.ts index e61f0d5a0a017b..d9ec8c4bdff8ba 100644 --- a/lib/config/presets/internal/index.ts +++ b/lib/config/presets/internal/index.ts @@ -3,6 +3,7 @@ import * as configPreset from './config'; import * as customManagersPreset from './custom-managers'; import * as defaultPreset from './default'; import * as dockerPreset from './docker'; +import * as globalPreset from './global'; import * as groupPreset from './group'; import * as helpersPreset from './helpers'; import * as mergeConfidence from './merge-confidence'; @@ -22,6 +23,7 @@ export const groups: Record> = { customManagers: customManagersPreset.presets, default: defaultPreset.presets, docker: dockerPreset.presets, + global: globalPreset.presets, group: groupPreset.presets, helpers: helpersPreset.presets, mergeConfidence: mergeConfidence.presets, diff --git a/lib/config/presets/parse.ts b/lib/config/presets/parse.ts index 09ac031b26ce9e..d81a7d9ac65f97 100644 --- a/lib/config/presets/parse.ts +++ b/lib/config/presets/parse.ts @@ -57,6 +57,7 @@ export function parsePreset(input: string): ParsedPreset { 'customManagers', 'default', 'docker', + 'global', 'group', 'helpers', 'mergeConfidence', From 9c244a2b84d3f63f8645bf644ccaaa7c28830cbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 08:14:54 +0000 Subject: [PATCH 20/26] fix(deps): update ghcr.io/containerbase/sidecar docker tag to v13.4.3 (#33110) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- lib/config/options/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 8310f685b96481..db79053add6c99 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -516,7 +516,7 @@ const options: RenovateOptions[] = [ description: 'Change this value to override the default Renovate sidecar image.', type: 'string', - default: 'ghcr.io/containerbase/sidecar:13.4.2', + default: 'ghcr.io/containerbase/sidecar:13.4.3', globalOnly: true, }, { From 4c40e99f1a7d0d02bf3b1bc44e7923ec8f80c437 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 08:15:11 +0000 Subject: [PATCH 21/26] chore(deps): update ghcr.io/containerbase/devcontainer docker tag to v13.4.3 (#33109) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3f088d2e94b969..035b15af331d8b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1 +1 @@ -FROM ghcr.io/containerbase/devcontainer:13.4.2 +FROM ghcr.io/containerbase/devcontainer:13.4.3 From d898d7fc40e1e6ef6357cc260950ad7be156ba73 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 14 Dec 2024 09:53:48 +0100 Subject: [PATCH 22/26] fix(config/presets): ensure groups have packageRules (#33088) --- lib/config/presets/internal/group.spec.ts | 13 +++++++++++++ lib/config/presets/internal/group.ts | 21 +++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 lib/config/presets/internal/group.spec.ts diff --git a/lib/config/presets/internal/group.spec.ts b/lib/config/presets/internal/group.spec.ts new file mode 100644 index 00000000000000..226ddcb37cb5f3 --- /dev/null +++ b/lib/config/presets/internal/group.spec.ts @@ -0,0 +1,13 @@ +import { presets } from './group'; + +const exceptions = new Set(['monorepos', 'recommended']); + +describe('config/presets/internal/group', () => { + const presetNames = Object.keys(presets).filter( + (name) => !exceptions.has(name), + ); + + it.each(presetNames)('group:%s contains packageRules', (name: string) => { + expect(presets[name]).toHaveProperty('packageRules'); + }); +}); diff --git a/lib/config/presets/internal/group.ts b/lib/config/presets/internal/group.ts index 2957b595ef3a81..d0735ef136ada9 100644 --- a/lib/config/presets/internal/group.ts +++ b/lib/config/presets/internal/group.ts @@ -111,14 +111,19 @@ const staticGroups = { }, fusionjs: { description: 'Group Fusion.js packages together.', - matchPackageNames: [ - 'fusion-cli', - 'fusion-core', - 'fusion-test-utils', - 'fusion-tokens', - 'fusion-plugin-**', - 'fusion-react**', - 'fusion-apollo**', + packageRules: [ + { + groupName: 'Fusion.js packages', + matchPackageNames: [ + 'fusion-cli', + 'fusion-core', + 'fusion-test-utils', + 'fusion-tokens', + 'fusion-plugin-**', + 'fusion-react**', + 'fusion-apollo**', + ], + }, ], }, githubArtifactActions: { From 07c005869cc738fc7e3f7786011d97511c386014 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sat, 14 Dec 2024 11:32:51 +0100 Subject: [PATCH 23/26] feat: extend skipStage to extract, lookup (#33108) --- lib/modules/manager/types.ts | 8 +++++++- lib/types/index.ts | 2 +- lib/types/skip-reason.ts | 2 ++ lib/workers/repository/process/extract-update.ts | 4 ++++ lib/workers/repository/process/fetch.spec.ts | 3 +++ lib/workers/repository/process/fetch.ts | 3 +++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/types.ts b/lib/modules/manager/types.ts index a1e8ba2824d9df..2ce51aa306a0d9 100644 --- a/lib/modules/manager/types.ts +++ b/lib/modules/manager/types.ts @@ -6,7 +6,12 @@ import type { ValidationMessage, } from '../../config/types'; import type { Category } from '../../constants'; -import type { ModuleApi, RangeStrategy, SkipReason } from '../../types'; +import type { + ModuleApi, + RangeStrategy, + SkipReason, + StageName, +} from '../../types'; import type { FileChange } from '../../util/git/types'; import type { MergeConfidence } from '../../util/merge-confidence/types'; import type { CustomExtractConfig } from './custom/types'; @@ -144,6 +149,7 @@ export interface PackageDependency> registryUrls?: string[] | null; rangeStrategy?: RangeStrategy; skipReason?: SkipReason; + skipStage?: StageName; sourceLine?: number; newVersion?: string; updates?: LookupUpdate[]; diff --git a/lib/types/index.ts b/lib/types/index.ts index a111c9ade7ea7d..4b6a9036088268 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -1,6 +1,6 @@ export type { CommitMessageJSON } from './commit-message-json'; export type { HostRule, CombinedHostRule } from './host-rules'; -export type { SkipReason } from './skip-reason'; +export type { SkipReason, StageName } from './skip-reason'; export type { RangeStrategy } from './versioning'; export type { BranchStatus } from './branch-status'; export type { diff --git a/lib/types/skip-reason.ts b/lib/types/skip-reason.ts index 534d37b445b934..8ebf4568e4363f 100644 --- a/lib/types/skip-reason.ts +++ b/lib/types/skip-reason.ts @@ -50,8 +50,10 @@ export type SkipReason = export type StageName = | 'current-timestamp' | 'datasource-merge' + | 'extract' | 'lock-file-maintenance-merge' | 'lock-file-maintenance-merge-2' + | 'lookup' | 'pre-lookup' | 'source-url' | 'update-type' diff --git a/lib/workers/repository/process/extract-update.ts b/lib/workers/repository/process/extract-update.ts index e31b055a9e78e0..75aecabd65a131 100644 --- a/lib/workers/repository/process/extract-update.ts +++ b/lib/workers/repository/process/extract-update.ts @@ -128,6 +128,10 @@ export async function extract( for (const file of files) { for (const dep of file.deps) { delete dep.updates; + if (dep.skipStage && dep.skipStage !== 'extract') { + delete dep.skipReason; + delete dep.skipStage; + } } } } diff --git a/lib/workers/repository/process/fetch.spec.ts b/lib/workers/repository/process/fetch.spec.ts index f891c6e81e6fd8..e68a4ce76f1647 100644 --- a/lib/workers/repository/process/fetch.spec.ts +++ b/lib/workers/repository/process/fetch.spec.ts @@ -59,18 +59,21 @@ describe('workers/repository/process/fetch', () => { depName: 'abcd', packageName: 'abcd', skipReason: 'ignored', + skipStage: 'lookup', updates: [], }, { depName: 'foo', packageName: 'foo', skipReason: 'disabled', + skipStage: 'lookup', updates: [], }, { depName: 'skipped', packageName: 'skipped', skipReason: 'some-reason', + skipStage: 'lookup', updates: [], }, ], diff --git a/lib/workers/repository/process/fetch.ts b/lib/workers/repository/process/fetch.ts index e9b17a4470f6bc..36fd712277c32d 100644 --- a/lib/workers/repository/process/fetch.ts +++ b/lib/workers/repository/process/fetch.ts @@ -172,6 +172,9 @@ export async function fetchUpdates( deps = []; packageDeps.set(packageFile, deps); } + if (dep.skipReason && !dep.skipStage) { + dep.skipStage = 'lookup'; + } deps.push(dep); } else { errors.push(err); From 5b8942f8f872ea53ecb745d1ed90afa8b52f900c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 10:46:04 +0000 Subject: [PATCH 24/26] fix(deps): update ghcr.io/renovatebot/base-image docker tag to v9.22.3 (#33112) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- tools/docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 497c7632bdcbec..73d5c377b48590 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -5,19 +5,19 @@ ARG BASE_IMAGE_TYPE=slim # -------------------------------------- # slim image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.22.2@sha256:ef4c8e2eebad1ff876e1d1ad7292070c20df96d08e8a62cb0eb3cfd60a3943e6 AS slim-base +FROM ghcr.io/renovatebot/base-image:9.22.3@sha256:c3c461778316552c91752e6866ccc9373a33131e92425d76d3f9b1e874295052 AS slim-base # -------------------------------------- # full image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.22.2-full@sha256:40914939b7dda15dd472c34da99906c6d8a006958eaae749e3ff57a8eba72649 AS full-base +FROM ghcr.io/renovatebot/base-image:9.22.3-full@sha256:9bacbb95d80cf8f44ce75c54a0a5cf5528a0938e0b6ea406c658dddb590139e8 AS full-base ENV RENOVATE_BINARY_SOURCE=global # -------------------------------------- # build image # -------------------------------------- -FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.22.2@sha256:ef4c8e2eebad1ff876e1d1ad7292070c20df96d08e8a62cb0eb3cfd60a3943e6 AS build +FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.22.3@sha256:c3c461778316552c91752e6866ccc9373a33131e92425d76d3f9b1e874295052 AS build # We want a specific node version here # renovate: datasource=node-version From ffa4333a385f3289e2d5a35584e849a11ec2418c Mon Sep 17 00:00:00 2001 From: Steven Davidovitz <13248+steved@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:55:06 -0800 Subject: [PATCH 25/26] fix(circleci): parsing of inline orb definitions (#31843) --- lib/modules/manager/circleci/extract.spec.ts | 60 ++++++++++++++++++++ lib/modules/manager/circleci/extract.ts | 59 ++++++++++++------- lib/modules/manager/circleci/schema.ts | 21 ++++++- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/lib/modules/manager/circleci/extract.spec.ts b/lib/modules/manager/circleci/extract.spec.ts index 7feeb83add7213..25915c53639f84 100644 --- a/lib/modules/manager/circleci/extract.spec.ts +++ b/lib/modules/manager/circleci/extract.spec.ts @@ -249,5 +249,65 @@ describe('modules/manager/circleci/extract', () => { }, ]); }); + + it('extracts orb definitions', () => { + const res = extractPackageFile(codeBlock` + version: 2.1 + + orbs: + myorb: + orbs: + python: circleci/python@2.1.1 + + executors: + python: + docker: + - image: cimg/python:3.9 + + jobs: + test_image: + docker: + - image: cimg/python:3.7 + steps: + - checkout + + workflows: + Test: + jobs: + - myorb/test_image`); + + expect(res).toEqual({ + deps: [ + { + currentValue: '2.1.1', + datasource: 'orb', + depName: 'python', + depType: 'orb', + packageName: 'circleci/python', + versioning: 'npm', + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '3.9', + datasource: 'docker', + depName: 'cimg/python', + depType: 'docker', + replaceString: 'cimg/python:3.9', + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '3.7', + datasource: 'docker', + depName: 'cimg/python', + depType: 'docker', + replaceString: 'cimg/python:3.7', + }, + ], + }); + }); }); }); diff --git a/lib/modules/manager/circleci/extract.ts b/lib/modules/manager/circleci/extract.ts index 660fb4eb35e620..8748635cf59595 100644 --- a/lib/modules/manager/circleci/extract.ts +++ b/lib/modules/manager/circleci/extract.ts @@ -9,20 +9,16 @@ import type { PackageDependency, PackageFileContent, } from '../types'; -import { CircleCiFile, type CircleCiJob } from './schema'; +import { CircleCiFile, type CircleCiJob, type CircleCiOrb } from './schema'; -export function extractPackageFile( - content: string, - packageFile?: string, +function extractDefinition( + definition: CircleCiOrb | CircleCiFile, config?: ExtractConfig, -): PackageFileContent | null { +): PackageDependency[] { const deps: PackageDependency[] = []; - try { - const parsed = parseSingleYaml(content, { - customSchema: CircleCiFile, - }); - for (const [key, orb] of Object.entries(parsed.orbs ?? {})) { + for (const [key, orb] of Object.entries(definition.orbs ?? {})) { + if (typeof orb === 'string') { const [packageName, currentValue] = orb.split('@'); deps.push({ @@ -33,21 +29,40 @@ export function extractPackageFile( versioning: npmVersioning.id, datasource: OrbDatasource.id, }); + } else { + deps.push(...extractDefinition(orb, config)); } + } - // extract environments - const environments: CircleCiJob[] = [ - Object.values(parsed.executors ?? {}), - Object.values(parsed.jobs ?? {}), - ].flat(); - for (const job of environments) { - for (const dockerElement of coerceArray(job.docker)) { - deps.push({ - ...getDep(dockerElement.image, true, config?.registryAliases), - depType: 'docker', - }); - } + // extract environments + const environments: CircleCiJob[] = [ + Object.values(definition.executors ?? {}), + Object.values(definition.jobs ?? {}), + ].flat(); + for (const job of environments) { + for (const dockerElement of coerceArray(job.docker)) { + deps.push({ + ...getDep(dockerElement.image, true, config?.registryAliases), + depType: 'docker', + }); } + } + + return deps; +} + +export function extractPackageFile( + content: string, + packageFile?: string, + config?: ExtractConfig, +): PackageFileContent | null { + const deps: PackageDependency[] = []; + try { + const parsed = parseSingleYaml(content, { + customSchema: CircleCiFile, + }); + + deps.push(...extractDefinition(parsed, config)); for (const alias of coerceArray(parsed.aliases)) { deps.push({ diff --git a/lib/modules/manager/circleci/schema.ts b/lib/modules/manager/circleci/schema.ts index 2aa96811019fc3..f4288727a2845f 100644 --- a/lib/modules/manager/circleci/schema.ts +++ b/lib/modules/manager/circleci/schema.ts @@ -4,14 +4,31 @@ export const CircleCiDocker = z.object({ image: z.string(), }); -export type CircleCiJob = z.infer; export const CircleCiJob = z.object({ docker: z.array(CircleCiDocker).optional(), }); +export type CircleCiJob = z.infer; + +const baseOrb = z.object({ + executors: z.record(z.string(), CircleCiJob).optional(), + jobs: z.record(z.string(), CircleCiJob).optional(), +}); + +type Orb = z.infer & { + orbs?: Record; +}; + +export const CircleCiOrb: z.ZodType = baseOrb.extend({ + orbs: z.lazy(() => + z.record(z.string(), z.union([z.string(), CircleCiOrb])).optional(), + ), +}); +export type CircleCiOrb = z.infer; export const CircleCiFile = z.object({ aliases: z.array(CircleCiDocker).optional(), executors: z.record(z.string(), CircleCiJob).optional(), jobs: z.record(z.string(), CircleCiJob).optional(), - orbs: z.record(z.string()).optional(), + orbs: z.record(z.string(), z.union([z.string(), CircleCiOrb])).optional(), }); +export type CircleCiFile = z.infer; From d0c0aa7333b0c00582dfc8cc2dbebe7e4f80d0e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 03:55:46 +0000 Subject: [PATCH 26/26] build(deps): update dependency better-sqlite3 to v11.7.0 (#33114) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3310152fbb0f0e..8bd07e61988f1d 100644 --- a/package.json +++ b/package.json @@ -254,7 +254,7 @@ "zod": "3.23.8" }, "optionalDependencies": { - "better-sqlite3": "11.6.0", + "better-sqlite3": "11.7.0", "openpgp": "6.0.1", "re2": "1.21.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc630c3a4524a9..a6c408ba86a356 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -340,8 +340,8 @@ importers: version: 3.23.8 optionalDependencies: better-sqlite3: - specifier: 11.6.0 - version: 11.6.0 + specifier: 11.7.0 + version: 11.7.0 openpgp: specifier: 6.0.1 version: 6.0.1 @@ -2553,8 +2553,8 @@ packages: before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} - better-sqlite3@11.6.0: - resolution: {integrity: sha512-2J6k/eVxcFYY2SsTxsXrj6XylzHWPxveCn4fKPKZFv/Vqn/Cd7lOuX4d7rGQXT5zL+97MkNL3nSbCrIoe3LkgA==} + better-sqlite3@11.7.0: + resolution: {integrity: sha512-mXpa5jnIKKHeoGzBrUJrc65cXFKcILGZpU3FXR0pradUEm9MA7UZz02qfEejaMcm9iXrSOCenwwYMJ/tZ1y5Ig==} bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} @@ -9286,7 +9286,7 @@ snapshots: before-after-hook@3.0.2: {} - better-sqlite3@11.6.0: + better-sqlite3@11.7.0: dependencies: bindings: 1.5.0 prebuild-install: 7.1.2