This commit is contained in:
Risu 2025-01-08 16:28:34 +01:00 committed by GitHub
commit 09868b3952
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 367 additions and 0 deletions

View file

@ -82,6 +82,7 @@ import * as preCommit from './pre-commit';
import * as pub from './pub';
import * as puppet from './puppet';
import * as pyenv from './pyenv';
import * as renovateConfigPresets from './renovate-config-presets';
import * as rubyVersion from './ruby-version';
import * as runtimeVersion from './runtime-version';
import * as sbt from './sbt';
@ -188,6 +189,7 @@ api.set('pre-commit', preCommit);
api.set('pub', pub);
api.set('puppet', puppet);
api.set('pyenv', pyenv);
api.set('renovate-config-presets', renovateConfigPresets);
api.set('ruby-version', rubyVersion);
api.set('runtime-version', runtimeVersion);
api.set('sbt', sbt);

View file

@ -0,0 +1,259 @@
import { codeBlock } from 'common-tags';
import { extractPackageFile } from '.';
describe('modules/manager/renovate-config-presets/extract', () => {
describe('extractPackageFile()', () => {
it('returns null for empty file', () => {
expect(extractPackageFile('', 'renovate.json')).toBeNull();
});
it('returns null for invalid file', () => {
expect(
extractPackageFile('this-is-not-json', 'renovate.json'),
).toBeNull();
});
it('returns null for a config file without presets', () => {
expect(
extractPackageFile(
codeBlock`
{
"draftPR": true
}
`,
'renovate.json',
),
).toBeNull();
});
it('returns null for a config file only contains built-in presets', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": ["config:recommended", ":label(test)", "helpers:pinGitHubActionDigests"]
}
`,
'renovate.json',
),
).toBeNull();
});
it('provides skipReason for unsupported preset sources', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": [
"fastcore",
"http://my.server/users/me/repos/renovate-presets/raw/default.json",
"local>renovate/presets",
"local>renovate/presets2#1.2.3"
]
}
`,
'renovate.json',
),
).toEqual({
deps: [
{
depName: 'renovate-config-fastcore',
skipReason: 'unsupported-datasource',
},
{
depName:
'http://my.server/users/me/repos/renovate-presets/raw/default.json',
skipReason: 'unsupported-datasource',
},
{
depName: 'renovate/presets',
skipReason: 'unsupported-datasource',
},
{
depName: 'renovate/presets2',
skipReason: 'unsupported-datasource',
},
],
});
});
it('provides skipReason for presets without versions', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": [
"github>abc/foo",
"gitlab>abc/bar:xyz",
"gitea>cde/foo//path/xyz"
]
}
`,
'renovate.json',
),
).toEqual({
deps: [
{
depName: 'abc/foo',
skipReason: 'unspecified-version',
},
{
depName: 'abc/bar',
skipReason: 'unspecified-version',
},
{
depName: 'cde/foo',
skipReason: 'unspecified-version',
},
],
});
});
it('extracts from a config file with GitHub hosted presets', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": [
"github>abc/foo#1.2.3",
"github>abc/bar:xyz#1.2.3",
"github>cde/foo//path/xyz#1.2.3",
"github>cde/bar:xyz/sub#1.2.3"
]
}
`,
'renovate.json',
),
).toEqual({
deps: [
{
datasource: 'github-tags',
depName: 'abc/foo',
currentValue: '1.2.3',
},
{
datasource: 'github-tags',
depName: 'abc/bar',
currentValue: '1.2.3',
},
{
datasource: 'github-tags',
depName: 'cde/foo',
currentValue: '1.2.3',
},
{
datasource: 'github-tags',
depName: 'cde/bar',
currentValue: '1.2.3',
},
],
});
});
it('extracts from a config file with GitLab hosted presets', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": [
"gitlab>abc/foo#1.2.3",
"gitlab>abc/bar:xyz#1.2.3",
"gitlab>cde/foo//path/xyz#1.2.3",
"gitlab>cde/bar:xyz/sub#1.2.3"
]
}
`,
'renovate.json',
),
).toEqual({
deps: [
{
datasource: 'gitlab-tags',
depName: 'abc/foo',
currentValue: '1.2.3',
},
{
datasource: 'gitlab-tags',
depName: 'abc/bar',
currentValue: '1.2.3',
},
{
datasource: 'gitlab-tags',
depName: 'cde/foo',
currentValue: '1.2.3',
},
{
datasource: 'gitlab-tags',
depName: 'cde/bar',
currentValue: '1.2.3',
},
],
});
});
it('extracts from a config file with Gitea hosted presets', () => {
expect(
extractPackageFile(
codeBlock`
{
"extends": [
"gitea>abc/foo#1.2.3",
"gitea>abc/bar:xyz#1.2.3",
"gitea>cde/foo//path/xyz#1.2.3",
"gitea>cde/bar:xyz/sub#1.2.3"
]
}
`,
'renovate.json',
),
).toEqual({
deps: [
{
datasource: 'gitea-tags',
depName: 'abc/foo',
currentValue: '1.2.3',
},
{
datasource: 'gitea-tags',
depName: 'abc/bar',
currentValue: '1.2.3',
},
{
datasource: 'gitea-tags',
depName: 'cde/foo',
currentValue: '1.2.3',
},
{
datasource: 'gitea-tags',
depName: 'cde/bar',
currentValue: '1.2.3',
},
],
});
});
it('supports JSON5', () => {
expect(
extractPackageFile(
codeBlock`
{
// comments are permitted
"extends": [
"github>abc/foo#1.2.3",
],
}
`,
'renovate.json5',
),
).toEqual({
deps: [
{
datasource: 'github-tags',
depName: 'abc/foo',
currentValue: '1.2.3',
},
],
});
});
});
});

View file

@ -0,0 +1,80 @@
import is from '@sindresorhus/is';
import { parsePreset } from '../../../config/presets/parse';
import type { RenovateConfig } from '../../../config/types';
import { logger } from '../../../logger';
import { parseJson } from '../../../util/common';
import { GiteaTagsDatasource } from '../../datasource/gitea-tags';
import { GithubTagsDatasource } from '../../datasource/github-tags';
import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
import type { PackageDependency, PackageFileContent } from '../types';
const supportedPresetSources: {
source: string;
datasource: string;
}[] = [
{
source: 'github',
datasource: GithubTagsDatasource.id,
},
{
source: 'gitlab',
datasource: GitlabTagsDatasource.id,
},
{
source: 'gitea',
datasource: GiteaTagsDatasource.id,
},
];
export function extractPackageFile(
content: string,
packageFile: string,
): PackageFileContent | null {
logger.trace(`renovate-config-presets.extractPackageFile(${packageFile})`);
let config: RenovateConfig | null;
try {
config = parseJson(content, packageFile) as RenovateConfig | null;
} catch {
logger.debug({ packageFile }, 'Invalid JSON5');
return null;
}
if (is.nullOrUndefined(config)) {
return null;
}
const deps: PackageDependency[] = [];
for (const preset of config.extends ?? []) {
const parsedPreset = parsePreset(preset);
const datasource = supportedPresetSources.find(
(source) => source.source === parsedPreset.presetSource,
)?.datasource;
if (is.nullOrUndefined(datasource)) {
if (parsedPreset.presetSource !== 'internal') {
deps.push({
depName: parsedPreset.repo,
skipReason: 'unsupported-datasource',
});
}
continue;
}
if (is.nullOrUndefined(parsedPreset.tag)) {
deps.push({
depName: parsedPreset.repo,
skipReason: 'unspecified-version',
});
continue;
}
deps.push({
depName: parsedPreset.repo,
datasource,
currentValue: parsedPreset.tag,
});
}
return is.nonEmptyArray(deps) ? { deps } : null;
}

View file

@ -0,0 +1,20 @@
import { configFileNames } from '../../../config/app-strings';
import { GiteaTagsDatasource } from '../../datasource/gitea-tags';
import { GithubTagsDatasource } from '../../datasource/github-tags';
import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
export { extractPackageFile } from './extract';
export const url = '../../../config-presets.md';
export const defaultConfig = {
fileMatch: configFileNames
.filter((name) => name !== 'package.json')
.map((name) => `^${name.replaceAll('.', '\\.')}$`),
};
export const supportedDatasources = [
GithubTagsDatasource.id,
GitlabTagsDatasource.id,
GiteaTagsDatasource.id,
];

View file

@ -0,0 +1,6 @@
### Unsupported Config
- [Local presets](../../../config-presets.md#local-presets)
- [HTTP URLs presets](../../../config-presets.md#fetching-presets-from-an-http-server)
- [`package.json` file config](../../../configuration-options.md) (deprecated)
- [`npm` hosted presets](../../../config-presets.md#npm-hosted-presets) (deprecated)