Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(manager): add renovate config presets manager #32688

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/modules/manager/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import * as pub from './pub';
import * as puppet from './puppet';
import * as pyenv from './pyenv';
import * as renovateConfigPresets from './renovate-config-presets';

Check failure on line 85 in lib/modules/manager/api.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

Dependency cycle via ./extract:6=>../../../config/presets:3=>../massage:15=>./options:3=>../../modules/manager:1

Check warning on line 85 in lib/modules/manager/api.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/api.ts#L85

Added line #L85 was not covered by tests
import * as rubyVersion from './ruby-version';
import * as runtimeVersion from './runtime-version';
import * as sbt from './sbt';
Expand Down Expand Up @@ -188,6 +189,7 @@
api.set('pub', pub);
api.set('puppet', puppet);
api.set('pyenv', pyenv);
api.set('renovate-config-presets', renovateConfigPresets);

Check warning on line 192 in lib/modules/manager/api.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/api.ts#L192

Added line #L192 was not covered by tests
api.set('ruby-version', rubyVersion);
api.set('runtime-version', runtimeVersion);
api.set('sbt', sbt);
Expand Down
233 changes: 233 additions & 0 deletions lib/modules/manager/renovate-config-presets/extract.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import { codeBlock } from 'common-tags';
import { extractPackageFile } from '.';

const noPresets = codeBlock`
{
"draftPR": true
}
`;

const builtInPresets = codeBlock`
{
"extends": ["config:recommended", ":label(test)", "helpers:pinGitHubActionDigests"]
}
`;

const unsupportedPresets = codeBlock`
{
"extends": [
"fastcore",
"http://my.server/users/me/repos/renovate-presets/raw/default.json",
"local>renovate/presets",
"local>renovate/presets2#1.2.3"
]
}
`;

const presetsWithoutVersions = codeBlock`
{
"extends": [
"github>abc/foo",
"gitlab>abc/bar:xyz",
"gitea>cde/foo//path/xyz"
]
}
`;

const githubPresets = 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"
]
}
`;

const gitlabPresets = 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"
]
}
`;

const giteaPresets = 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"
]
}
`;

const json5Config = codeBlock`
{
// comments are permitted
"extends": [
"github>abc/foo#1.2.3",
],
}
`;

describe('modules/manager/renovate-config-presets/extract', () => {
describe('extractPackageFile()', () => {
it('returns null for empty file', () => {
expect(extractPackageFile('', '')).toBeNull();
});

it('returns null for invalid file', () => {
expect(extractPackageFile('this-is-not-json', '')).toBeNull();
});

it('returns null for a config file without presets', () => {
expect(extractPackageFile(noPresets, '')).toBeNull();
});

it('returns null for a config file only contains built-in presets', () => {
expect(extractPackageFile(builtInPresets, '')).toBeNull();
});

it('provides skipReason for unsupported preset sources', () => {
expect(extractPackageFile(unsupportedPresets, '')).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(presetsWithoutVersions, '')).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(githubPresets, '')).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(gitlabPresets, '')).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(giteaPresets, '')).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(json5Config, '')).toEqual({
deps: [
{
datasource: 'github-tags',
depName: 'abc/foo',
currentValue: '1.2.3',
},
],
});
});
});
});
82 changes: 82 additions & 0 deletions lib/modules/manager/renovate-config-presets/extract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import is from '@sindresorhus/is';
import JSON5 from 'json5';
import { parsePreset } from '../../../config/presets';

Check failure on line 3 in lib/modules/manager/renovate-config-presets/extract.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

Dependency cycle via ../massage:15=>./options:3=>../../modules/manager:1=>./api:2=>./renovate-config-presets:85

Check warning on line 3 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L1-L3

Added lines #L1 - L3 were not covered by tests
import type { RenovateConfig } from '../../../config/types';
import { logger } from '../../../logger';
import { GiteaTagsDatasource } from '../../datasource/gitea-tags';
import { GithubTagsDatasource } from '../../datasource/github-tags';
import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';

Check warning on line 8 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L5-L8

Added lines #L5 - L8 were not covered by tests
import type { PackageDependency, PackageFileContent } from '../types';

const supportedPresetSources: {
source: string;
datasource: string;
}[] = [

Check warning on line 14 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L14

Added line #L14 was not covered by tests
{
source: 'github',
datasource: GithubTagsDatasource.id,
},
{
source: 'gitlab',
datasource: GitlabTagsDatasource.id,
},
{
source: 'gitea',
datasource: GiteaTagsDatasource.id,
},
];

export function extractPackageFile(

Check warning on line 29 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L29

Added line #L29 was not covered by tests
content: string,
packageFile: string,
): PackageFileContent | null {
logger.trace(`renovate-config-presets.extractPackageFile(${packageFile})`);

Check warning on line 33 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L33

Added line #L33 was not covered by tests
let config: RenovateConfig;
try {
config = JSON5.parse<RenovateConfig>(content);

Check warning on line 36 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L35-L36

Added lines #L35 - L36 were not covered by tests
} catch {
logger.debug({ packageFile }, 'Invalid JSON5');
return null;

Check warning on line 39 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L38-L39

Added lines #L38 - L39 were not covered by tests
}

const deps: PackageDependency[] = [];

Check warning on line 42 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L42

Added line #L42 was not covered by tests

for (const preset of config.extends ?? []) {
const parsedPreset = parsePreset(preset);

Check warning on line 45 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L45

Added line #L45 was not covered by tests
if (
!supportedPresetSources.some(
(source) => source.source === parsedPreset.presetSource,

Check warning on line 48 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L48

Added line #L48 was not covered by tests
)
) {
if (parsedPreset.presetSource !== 'internal') {
deps.push({

Check warning on line 52 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L52

Added line #L52 was not covered by tests
depName: parsedPreset.repo,
skipReason: 'unsupported-datasource',
});
}
continue;

Check warning on line 57 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L57

Added line #L57 was not covered by tests
}

if (is.nullOrUndefined(parsedPreset.tag)) {
deps.push({

Check warning on line 61 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L61

Added line #L61 was not covered by tests
depName: parsedPreset.repo,
skipReason: 'unspecified-version',
});
continue;

Check warning on line 65 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L65

Added line #L65 was not covered by tests
}

const datasource = supportedPresetSources.find(
(source) => source.source === parsedPreset.presetSource,

Check warning on line 69 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L68-L69

Added lines #L68 - L69 were not covered by tests
)?.datasource;
if (!datasource) {
throw new Error(`Datasource not found for ${parsedPreset.presetSource}`);

Check warning on line 72 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L72

Added line #L72 was not covered by tests
}
deps.push({

Check warning on line 74 in lib/modules/manager/renovate-config-presets/extract.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/extract.ts#L74

Added line #L74 was not covered by tests
depName: parsedPreset.repo,
datasource,
currentValue: parsedPreset.tag,
});
}

return is.nonEmptyArray(deps) ? { deps } : null;
}
20 changes: 20 additions & 0 deletions lib/modules/manager/renovate-config-presets/index.ts
Original file line number Diff line number Diff line change
@@ -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';

Check warning on line 4 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L1-L4

Added lines #L1 - L4 were not covered by tests

export { extractPackageFile } from './extract';

Check failure on line 6 in lib/modules/manager/renovate-config-presets/index.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

Dependency cycle via ../../../config/presets:3=>../massage:15=>./options:3=>../../modules/manager:1=>./api:2

Check warning on line 6 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L6

Added line #L6 was not covered by tests

export const url = 'https://docs.renovatebot.com/config-presets/';

Check warning on line 8 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L8

Added line #L8 was not covered by tests

export const defaultConfig = {

Check warning on line 10 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L10

Added line #L10 was not covered by tests
fileMatch: configFileNames
.filter((name) => name !== 'package.json')
.map((name) => `^${name.replaceAll('.', '\\.')}$`),

Check warning on line 13 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L12-L13

Added lines #L12 - L13 were not covered by tests
};

export const supportedDatasources = [

Check warning on line 16 in lib/modules/manager/renovate-config-presets/index.ts

View check run for this annotation

Codecov / codecov/patch

lib/modules/manager/renovate-config-presets/index.ts#L16

Added line #L16 was not covered by tests
GithubTagsDatasource.id,
GitlabTagsDatasource.id,
GiteaTagsDatasource.id,
];
7 changes: 7 additions & 0 deletions lib/modules/manager/renovate-config-presets/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Unsupported Config

- [Local presets](https://docs.renovatebot.com/config-presets/#local-presets)
- [HTTP URLs presets](https://docs.renovatebot.com/config-presets/#fetching-presets-from-an-http-server)
- [`package.json` file config](https://docs.renovatebot.com/configuration-options/) (deprecated)
- [`npm` hosted presets](https://docs.renovatebot.com/config-presets/#npm-hosted-presets) (deprecated)
- `package.json` hosted presets (deprecated)
Loading