2023-06-16 23:42:34 +05:45
|
|
|
import { getConfig } from '../../../config/defaults';
|
2022-03-03 10:35:26 +01:00
|
|
|
import { MavenDatasource } from '../../../modules/datasource/maven';
|
2023-02-20 15:58:49 +01:00
|
|
|
import type { PackageFile } from '../../../modules/manager/types';
|
2022-06-22 12:56:55 +03:00
|
|
|
import { ExternalHostError } from '../../../types/errors/external-host-error';
|
2020-05-01 18:03:48 +02:00
|
|
|
import { fetchUpdates } from './fetch';
|
2020-03-05 21:57:24 +01:00
|
|
|
import * as lookup from './lookup';
|
2025-03-13 18:52:09 +01:00
|
|
|
import type { RenovateConfig } from '~test/util';
|
2018-05-09 08:03:59 +02:00
|
|
|
|
2025-03-13 18:52:09 +01:00
|
|
|
const lookupUpdates = vi.mocked(lookup).lookupUpdates;
|
2018-06-01 09:02:51 +02:00
|
|
|
|
2025-02-26 10:35:54 +01:00
|
|
|
vi.mock('./lookup');
|
2018-05-09 08:03:59 +02:00
|
|
|
|
2021-08-18 08:46:56 +03:00
|
|
|
describe('workers/repository/process/fetch', () => {
|
2018-05-09 08:03:59 +02:00
|
|
|
describe('fetchUpdates()', () => {
|
2020-01-30 07:07:56 +01:00
|
|
|
let config: RenovateConfig;
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2018-05-09 08:03:59 +02:00
|
|
|
beforeEach(() => {
|
2020-01-30 07:07:56 +01:00
|
|
|
config = getConfig();
|
2018-05-09 08:03:59 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2018-05-09 08:03:59 +02:00
|
|
|
it('handles empty deps', async () => {
|
2023-02-20 15:58:49 +01:00
|
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
2018-05-09 08:03:59 +02:00
|
|
|
npm: [{ packageFile: 'package.json', deps: [] }],
|
|
|
|
};
|
|
|
|
await fetchUpdates(config, packageFiles);
|
2022-01-02 18:25:53 +03:00
|
|
|
expect(packageFiles).toEqual({
|
|
|
|
npm: [{ deps: [], packageFile: 'package.json' }],
|
|
|
|
});
|
2018-05-09 08:03:59 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2018-05-31 20:56:31 +02:00
|
|
|
it('handles ignored, skipped and disabled', async () => {
|
2018-05-09 08:03:59 +02:00
|
|
|
config.ignoreDeps = ['abcd'];
|
|
|
|
config.packageRules = [
|
|
|
|
{
|
2021-01-29 14:43:42 +04:00
|
|
|
matchPackageNames: ['foo'],
|
2018-05-09 08:03:59 +02:00
|
|
|
enabled: false,
|
|
|
|
},
|
|
|
|
];
|
2023-02-20 15:58:49 +01:00
|
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
2018-05-09 08:03:59 +02:00
|
|
|
npm: [
|
|
|
|
{
|
|
|
|
packageFile: 'package.json',
|
|
|
|
deps: [
|
|
|
|
{ depName: 'abcd' },
|
|
|
|
{ depName: 'foo' },
|
2020-05-07 10:23:45 +02:00
|
|
|
{ depName: 'skipped', skipReason: 'some-reason' as never },
|
2018-05-09 08:03:59 +02:00
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await fetchUpdates(config, packageFiles);
|
2024-12-08 04:33:31 -03:00
|
|
|
expect(packageFiles).toEqual({
|
|
|
|
npm: [
|
|
|
|
{
|
|
|
|
deps: [
|
|
|
|
{
|
|
|
|
depName: 'abcd',
|
|
|
|
packageName: 'abcd',
|
|
|
|
skipReason: 'ignored',
|
|
|
|
updates: [],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
depName: 'foo',
|
|
|
|
packageName: 'foo',
|
|
|
|
skipReason: 'disabled',
|
|
|
|
updates: [],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
depName: 'skipped',
|
|
|
|
packageName: 'skipped',
|
|
|
|
skipReason: 'some-reason',
|
|
|
|
updates: [],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
packageFile: 'package.json',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
2021-11-08 13:16:58 +01:00
|
|
|
expect(packageFiles.npm[0].deps[0].skipReason).toBe('ignored');
|
2018-05-09 08:03:59 +02:00
|
|
|
expect(packageFiles.npm[0].deps[0].updates).toHaveLength(0);
|
2021-11-08 13:16:58 +01:00
|
|
|
expect(packageFiles.npm[0].deps[1].skipReason).toBe('disabled');
|
2018-05-09 08:03:59 +02:00
|
|
|
expect(packageFiles.npm[0].deps[1].updates).toHaveLength(0);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2018-05-09 08:03:59 +02:00
|
|
|
it('fetches updates', async () => {
|
feat: rangeStrategy (#1954)
This PR replaces the existing `pinVersions`, `upgradeInRange` and `versionStrategy` settings with a single one: `rangeStrategy`.
Previously:
- `pinVersions` could be `true` or `false`, but defaulted to `null`, which meant that Renovate would decide. `true` meant that Renovate would replace existing ranges like `^1.0.0` with an exact/pinned version such as `1.2.0`.
- `upgradeInRange` could be true or false, default to false. If `true`, it would mean Renovate would replace an existing range like `^1.0.0` with something like `^1.2.0`
- `versionStrategy` could be `replace` or `widen` and was mainly used for `peerDependencies` to widen existing ranges, e.g. from `^1.0.0` to `^1.0.0 || ^2.0.0`
It was possible to set conflicting settings, e.g. configuring `pinVersions=true` and `upgradeInRange=true`.
Now, we combine them into a single setting: `rangeStrategy`:
- `auto` = Renovate decides (this will be done on a manager-by-manager basis)
- `pin` = convert ranges to exact versions
- `bump` = same as `upgradeInRange` previously, e.g. bump the range even if the new version satisifies the existing range
- `replace` = Same as pinVersions === false && upgradeInRange === false, i.e. only replace the range if the new version falls outside it
- `widen` = Same as previous versionStrategy==='widen'
2018-05-17 07:16:13 +02:00
|
|
|
config.rangeStrategy = 'auto';
|
2023-03-29 07:08:15 +02:00
|
|
|
config.constraints = { some: 'different' };
|
2020-01-06 09:16:15 +01:00
|
|
|
const packageFiles: any = {
|
2020-03-12 07:41:49 +01:00
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
packageFile: 'pom.xml',
|
2023-03-29 07:08:15 +02:00
|
|
|
extractedConstraints: { some: 'constraint', other: 'constraint' },
|
2022-02-15 08:12:30 +03:00
|
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
2020-03-12 07:41:49 +01:00
|
|
|
},
|
|
|
|
],
|
2018-05-09 08:03:59 +02:00
|
|
|
};
|
2020-04-13 13:44:49 +02:00
|
|
|
lookupUpdates.mockResolvedValue({ updates: ['a', 'b'] } as never);
|
2018-05-09 08:03:59 +02:00
|
|
|
await fetchUpdates(config, packageFiles);
|
2024-12-08 04:33:31 -03:00
|
|
|
expect(packageFiles).toEqual({
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
deps: [
|
|
|
|
{
|
|
|
|
datasource: 'maven',
|
|
|
|
depName: 'bbb',
|
|
|
|
packageName: 'bbb',
|
|
|
|
updates: ['a', 'b'],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
extractedConstraints: { other: 'constraint', some: 'constraint' },
|
|
|
|
packageFile: 'pom.xml',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
2018-05-09 08:03:59 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2022-02-13 10:59:03 +02:00
|
|
|
it('skips deps with empty names', async () => {
|
2023-02-20 15:58:49 +01:00
|
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
2022-02-13 10:59:03 +02:00
|
|
|
docker: [
|
|
|
|
{
|
|
|
|
packageFile: 'values.yaml',
|
|
|
|
deps: [
|
|
|
|
{ depName: '', currentValue: '2.8.11', datasource: 'docker' },
|
|
|
|
{ depName: 'abcd' },
|
|
|
|
{ currentValue: '2.8.11', datasource: 'docker' },
|
|
|
|
{ depName: ' ' },
|
2022-06-21 15:09:30 +05:30
|
|
|
{},
|
2022-02-13 10:59:03 +02:00
|
|
|
{ depName: undefined },
|
2022-02-21 15:38:24 +01:00
|
|
|
{ depName: { oh: 'no' } as unknown as string },
|
2022-02-13 10:59:03 +02:00
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await fetchUpdates(config, packageFiles);
|
2022-02-21 15:38:24 +01:00
|
|
|
expect(packageFiles.docker[0].deps[0].skipReason).toBe('invalid-name');
|
2022-02-13 10:59:03 +02:00
|
|
|
expect(packageFiles.docker[0].deps[1].skipReason).toBeUndefined();
|
2022-02-21 15:38:24 +01:00
|
|
|
expect(packageFiles.docker[0].deps[2].skipReason).toBe('invalid-name');
|
|
|
|
expect(packageFiles.docker[0].deps[3].skipReason).toBe('invalid-name');
|
|
|
|
expect(packageFiles.docker[0].deps[4].skipReason).toBe('invalid-name');
|
|
|
|
expect(packageFiles.docker[0].deps[5].skipReason).toBe('invalid-name');
|
|
|
|
expect(packageFiles.docker[0].deps[6].skipReason).toBe('invalid-name');
|
2022-02-13 10:59:03 +02:00
|
|
|
});
|
2022-06-15 09:51:37 +05:30
|
|
|
|
|
|
|
it('skips internal deps by default', async () => {
|
2023-02-20 15:58:49 +01:00
|
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
2022-06-15 09:51:37 +05:30
|
|
|
docker: [
|
|
|
|
{
|
|
|
|
packageFile: 'values.yaml',
|
|
|
|
deps: [
|
|
|
|
{
|
|
|
|
depName: 'dep-name',
|
|
|
|
currentValue: '2.8.11',
|
|
|
|
datasource: 'docker',
|
|
|
|
isInternal: true,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(packageFiles.docker[0].deps[0].skipReason).toBe(
|
2023-11-07 12:50:29 -03:00
|
|
|
'internal-package',
|
2022-06-15 09:51:37 +05:30
|
|
|
);
|
|
|
|
expect(packageFiles.docker[0].deps[0].updates).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetch updates for internal deps if updateInternalDeps is true', async () => {
|
|
|
|
config.updateInternalDeps = true;
|
|
|
|
config.rangeStrategy = 'auto';
|
|
|
|
const packageFiles: any = {
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
packageFile: 'pom.xml',
|
|
|
|
deps: [
|
|
|
|
{
|
|
|
|
datasource: MavenDatasource.id,
|
|
|
|
depName: 'bbb',
|
|
|
|
isInternal: true,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
lookupUpdates.mockResolvedValue({ updates: ['a', 'b'] } as never);
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(packageFiles.maven[0].deps[0].updates).toHaveLength(2);
|
|
|
|
});
|
2022-06-22 12:56:55 +03:00
|
|
|
|
|
|
|
it('throws lookup errors for onboarded repos', async () => {
|
|
|
|
config.rangeStrategy = 'auto';
|
|
|
|
const packageFiles: any = {
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
packageFile: 'pom.xml',
|
|
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
2024-12-18 10:42:39 +01:00
|
|
|
lookupUpdates.mockRejectedValueOnce(new Error('some error'));
|
2022-06-22 12:56:55 +03:00
|
|
|
|
|
|
|
await expect(
|
2023-11-07 12:50:29 -03:00
|
|
|
fetchUpdates({ ...config, repoIsOnboarded: true }, packageFiles),
|
2022-06-22 12:56:55 +03:00
|
|
|
).rejects.toThrow();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('throws lookup errors for not onboarded repos', async () => {
|
|
|
|
config.rangeStrategy = 'auto';
|
|
|
|
const packageFiles: any = {
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
packageFile: 'pom.xml',
|
|
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
2024-12-18 10:42:39 +01:00
|
|
|
lookupUpdates.mockRejectedValueOnce(new Error('some error'));
|
2022-06-22 12:56:55 +03:00
|
|
|
|
|
|
|
await expect(
|
2023-11-07 12:50:29 -03:00
|
|
|
fetchUpdates({ ...config, repoIsOnboarded: true }, packageFiles),
|
2022-06-22 12:56:55 +03:00
|
|
|
).rejects.toThrow();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('produces external host warnings for not onboarded repos', async () => {
|
|
|
|
config.rangeStrategy = 'auto';
|
|
|
|
const packageFiles: any = {
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
packageFile: 'pom.xml',
|
|
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const err = new ExternalHostError(new Error('some error'));
|
|
|
|
lookupUpdates.mockRejectedValueOnce(err);
|
|
|
|
|
|
|
|
await fetchUpdates({ ...config, repoIsOnboarded: false }, packageFiles);
|
|
|
|
|
|
|
|
expect(packageFiles).toMatchObject({
|
|
|
|
maven: [
|
|
|
|
{
|
|
|
|
deps: [
|
|
|
|
{
|
|
|
|
depName: 'bbb',
|
|
|
|
warnings: [
|
|
|
|
{ topic: 'Lookup Error', message: 'bbb: some error' },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
|
|
|
});
|
2018-05-09 08:03:59 +02:00
|
|
|
});
|
|
|
|
});
|