mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-31 09:41:46 +00:00
e01b50c6ab
* refactor: flag all typed object literal casts in prefer-partial-in-specs * refactor: type maven spec httpError helper against got response shape
404 lines
12 KiB
TypeScript
404 lines
12 KiB
TypeScript
import type { RenovateConfig } from '~test/util.ts';
|
|
import { partial } from '~test/util.ts';
|
|
import { getConfig } from '../../../config/defaults.ts';
|
|
import { MavenDatasource } from '../../../modules/datasource/maven/index.ts';
|
|
import type { PackageFile } from '../../../modules/manager/types.ts';
|
|
import { ExternalHostError } from '../../../types/errors/external-host-error.ts';
|
|
import { Result } from '../../../util/result.ts';
|
|
import { fetchUpdates } from './fetch.ts';
|
|
import * as lookup from './lookup/index.ts';
|
|
import type { UpdateResult } from './lookup/types.ts';
|
|
|
|
const lookupUpdates = vi.mocked(lookup).lookupUpdates;
|
|
|
|
vi.mock('./lookup/index.ts');
|
|
|
|
describe('workers/repository/process/fetch', () => {
|
|
describe('fetchUpdates()', () => {
|
|
let config: RenovateConfig;
|
|
|
|
beforeEach(() => {
|
|
config = getConfig();
|
|
});
|
|
|
|
it('handles empty deps', async () => {
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
|
npm: [{ packageFile: 'package.json', deps: [] }],
|
|
};
|
|
await fetchUpdates(config, packageFiles);
|
|
expect(packageFiles).toEqual({
|
|
npm: [{ deps: [], packageFile: 'package.json' }],
|
|
});
|
|
});
|
|
|
|
it('handles ignored, skipped and disabled', async () => {
|
|
config.ignoreDeps = ['abcd'];
|
|
config.packageRules = [
|
|
{
|
|
matchPackageNames: ['foo'],
|
|
enabled: false,
|
|
},
|
|
];
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
|
npm: [
|
|
{
|
|
packageFile: 'package.json',
|
|
deps: [
|
|
{ depName: 'abcd' },
|
|
{ depName: 'foo' },
|
|
{ depName: 'skipped', skipReason: 'some-reason' as never },
|
|
],
|
|
},
|
|
],
|
|
};
|
|
await fetchUpdates(config, packageFiles);
|
|
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',
|
|
},
|
|
],
|
|
});
|
|
expect(packageFiles.npm[0].deps[0].skipReason).toBe('ignored');
|
|
expect(packageFiles.npm[0].deps[0].updates).toHaveLength(0);
|
|
expect(packageFiles.npm[0].deps[1].skipReason).toBe('disabled');
|
|
expect(packageFiles.npm[0].deps[1].updates).toHaveLength(0);
|
|
});
|
|
|
|
it('fetches updates', async () => {
|
|
config.rangeStrategy = 'auto';
|
|
// @ts-expect-error -- intentionally using invalid constraint names
|
|
config.constraints = { some: 'different' };
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
extractedConstraints: { some: 'constraint', other: 'constraint' },
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: ['a', 'b'] as never })),
|
|
);
|
|
await fetchUpdates(config, packageFiles);
|
|
expect(packageFiles).toEqual({
|
|
maven: [
|
|
{
|
|
deps: [
|
|
{
|
|
datasource: 'maven',
|
|
depName: 'bbb',
|
|
packageName: 'bbb',
|
|
updates: ['a', 'b'],
|
|
},
|
|
],
|
|
extractedConstraints: { other: 'constraint', some: 'constraint' },
|
|
packageFile: 'pom.xml',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
describe('constraintsVersioning', () => {
|
|
it('is merged from packageFile with config', async () => {
|
|
config.constraintsVersioning = { gomodMod: 'config-version' };
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
constraintsVersioning: {
|
|
gomodMod: 'pfile-version',
|
|
go: 'go-version',
|
|
},
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: [] })),
|
|
);
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(lookupUpdates).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
constraintsVersioning: {
|
|
gomodMod: 'config-version',
|
|
go: 'go-version',
|
|
},
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('is set from packageFile if only set on packageFile', async () => {
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
constraintsVersioning: { go: 'go-version' },
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: [] })),
|
|
);
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(lookupUpdates).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
constraintsVersioning: { go: 'go-version' },
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('is not set if neither config nor packageFile are set', async () => {
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
// no constraintsVersioning on pFile
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: [] })),
|
|
);
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(lookupUpdates).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
constraintsVersioning: {},
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('is set if config is set', async () => {
|
|
config.rangeStrategy = 'auto';
|
|
config.constraintsVersioning = { gomodMod: 'config-version' };
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
// no constraintsVersioning on pFile
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: [] })),
|
|
);
|
|
await fetchUpdates(config, packageFiles);
|
|
expect(lookupUpdates).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
constraintsVersioning: { gomodMod: 'config-version' },
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
it('prefers configured constraints over extracted constraints', async () => {
|
|
config.rangeStrategy = 'auto';
|
|
config.constraints = { python: '>=3.9' };
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
extractedConstraints: { python: '>=3.8' },
|
|
deps: [
|
|
{
|
|
datasource: MavenDatasource.id,
|
|
depName: 'bbb',
|
|
extractedConstraints: { python: '<3.12' },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockResolvedValue(
|
|
Result.ok(partial<UpdateResult>({ updates: ['a', 'b'] as never })),
|
|
);
|
|
|
|
await fetchUpdates(config, packageFiles);
|
|
|
|
expect(lookupUpdates).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
constraints: { python: '>=3.9' },
|
|
datasource: 'maven',
|
|
depName: 'bbb',
|
|
}),
|
|
);
|
|
expect(packageFiles.maven[0].deps[0]).toEqual(
|
|
expect.objectContaining({
|
|
extractedConstraints: { python: '<3.12' },
|
|
updates: ['a', 'b'],
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('skips deps with empty names', async () => {
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
|
docker: [
|
|
{
|
|
packageFile: 'values.yaml',
|
|
deps: [
|
|
{ depName: '', currentValue: '2.8.11', datasource: 'docker' },
|
|
{ depName: 'abcd' },
|
|
{ currentValue: '2.8.11', datasource: 'docker' },
|
|
{ depName: ' ' },
|
|
{},
|
|
{ depName: undefined },
|
|
// oxlint-disable-next-line renovate/prefer-partial-in-specs -- intentionally invalid depName type to test invalid-name skip handling
|
|
{ depName: { oh: 'no' } as unknown as string },
|
|
],
|
|
},
|
|
],
|
|
};
|
|
await fetchUpdates(config, packageFiles);
|
|
expect(packageFiles.docker[0].deps[0].skipReason).toBe('invalid-name');
|
|
expect(packageFiles.docker[0].deps[1].skipReason).toBeUndefined();
|
|
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');
|
|
});
|
|
|
|
it('skips internal deps by default', async () => {
|
|
const packageFiles: Record<string, PackageFile[]> = {
|
|
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(
|
|
'internal-package',
|
|
);
|
|
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(
|
|
Result.ok(partial<UpdateResult>({ updates: ['a', 'b'] as never })),
|
|
);
|
|
await fetchUpdates(config, packageFiles);
|
|
expect(packageFiles.maven[0].deps[0].updates).toHaveLength(2);
|
|
});
|
|
|
|
it('throws lookup errors for onboarded repos', async () => {
|
|
config.rangeStrategy = 'auto';
|
|
const packageFiles: any = {
|
|
maven: [
|
|
{
|
|
packageFile: 'pom.xml',
|
|
deps: [{ datasource: MavenDatasource.id, depName: 'bbb' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockRejectedValueOnce(new Error('some error'));
|
|
|
|
await expect(
|
|
fetchUpdates({ ...config, repoIsOnboarded: true }, packageFiles),
|
|
).rejects.toThrow('some error');
|
|
});
|
|
|
|
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' }],
|
|
},
|
|
],
|
|
};
|
|
lookupUpdates.mockRejectedValueOnce(new Error('some error'));
|
|
|
|
await expect(
|
|
fetchUpdates({ ...config, repoIsOnboarded: true }, packageFiles),
|
|
).rejects.toThrow('some error');
|
|
});
|
|
|
|
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' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
});
|