mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-31 09:41:46 +00:00
97327c3d28
* refactor(linters): add prefer-coerce-array rule Refs #45217 `x ?? []` and `coerceArray(x)` say the same thing, but only the second one is searchable and consistent. The rule flags a `??` whose default is a bare `[]` literal; a non-empty default or an asserted `([] as Foo[])` still passes. Applying it across `lib/` surfaced three spots the helper cannot cover, which keep `?? []` with a disable comment or a narrower fix: - `package-files.ts` destructures a tuple, which `coerceArray()` widens - `generate.spec.ts` defaults `matchAll()`, an iterator rather than an array - `mise/upgradeable-tooling.ts` declares a `Record` return, so its `?? []` fallback was wrong to begin with and becomes `coerceObject()` * refactor(platform/github): hoist the GHE version header lookup `Object.entries(...).find()` returns a tuple, and defaulting it with `?? []` only to destructure the second element reads as an array default when it is not one. Name the found entry instead, which drops the `?? []` rather than routing a tuple through `coerceArray()`.
413 lines
12 KiB
TypeScript
413 lines
12 KiB
TypeScript
import { codeBlock } from 'common-tags';
|
|
import { Fixtures } from '~test/fixtures.ts';
|
|
import { coerceArray } from '../../../util/array.ts';
|
|
import { extractPackageFile } from './extract.ts';
|
|
|
|
describe('modules/manager/swift/extract', () => {
|
|
describe('extractPackageFile()', () => {
|
|
it('returns null for empty content', () => {
|
|
expect(extractPackageFile('')).toBeNull();
|
|
});
|
|
|
|
it('returns null for content without dependencies', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
products: [
|
|
.library(
|
|
name: "MyLibrary",
|
|
targets: ["MyLibrary"]
|
|
)
|
|
],
|
|
targets: [
|
|
.target(
|
|
name: "MyLibrary"
|
|
)
|
|
]
|
|
)
|
|
`;
|
|
expect(extractPackageFile(content)).toBeNull();
|
|
});
|
|
|
|
it('extracts GitHub dependencies with github-tags datasource', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: 'from: "1.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts GitLab dependencies with gitlab-tags datasource', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://gitlab.com/example/repo", from: "2.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'gitlab-tags',
|
|
depName: 'example/repo',
|
|
currentValue: 'from: "2.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts self-hosted GitHub dependencies with registryUrls', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.example.com/org/repo", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'org/repo',
|
|
currentValue: 'from: "1.0.0"',
|
|
registryUrls: ['https://github.example.com'],
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts self-hosted GitLab dependencies with registryUrls', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://gitlab.mycompany.com/group/project.git", from: "2.5.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'gitlab-tags',
|
|
depName: 'group/project',
|
|
currentValue: 'from: "2.5.0"',
|
|
registryUrls: ['https://gitlab.mycompany.com'],
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts GitHub dependencies from SCP-style SSH URL', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "git@github.com:example/repo.git", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: 'from: "1.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts GitLab dependencies from SCP-style SSH URL', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "git@gitlab.com:group/project.git", from: "2.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'gitlab-tags',
|
|
depName: 'group/project',
|
|
currentValue: 'from: "2.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts dependencies from ssh:// URL', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "ssh://git@github.com/example/repo.git", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: 'from: "1.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('returns null for unparseable SSH URL', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "ssh://", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
expect(extractPackageFile(content)).toBeNull();
|
|
});
|
|
|
|
it('extracts other dependencies with git-tags datasource', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://example.com/repo.git", from: "3.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'git-tags',
|
|
depName: 'https://example.com/repo.git',
|
|
currentValue: 'from: "3.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts exact version dependencies', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo", .exact("1.2.3"))
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: '1.2.3',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts exact version with label syntax', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo", exact: "1.2.1")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: '1.2.1',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts range version dependencies', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo", "1.0.0"..."2.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toMatchObject({
|
|
deps: [
|
|
{
|
|
datasource: 'github-tags',
|
|
depName: 'example/repo',
|
|
currentValue: '"1.0.0"..."2.0.0"',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts dependencies from sample package file', () => {
|
|
const result = extractPackageFile(Fixtures.get('SamplePackage.swift'));
|
|
|
|
expect(result?.deps).toHaveLength(10);
|
|
|
|
const githubDeps = coerceArray(
|
|
result?.deps.filter((dep) => dep.datasource === 'github-tags'),
|
|
);
|
|
expect(githubDeps).toHaveLength(10);
|
|
|
|
expect(result?.deps).toContainEqual({
|
|
datasource: 'github-tags',
|
|
depName: '0x7fs/CountedSet',
|
|
currentValue: '"master"\n ',
|
|
});
|
|
|
|
expect(result?.deps).toContainEqual({
|
|
datasource: 'github-tags',
|
|
depName: 'avito-tech/GraphiteClient',
|
|
currentValue: '0.1.0',
|
|
});
|
|
|
|
expect(result?.deps).toContainEqual({
|
|
datasource: 'github-tags',
|
|
depName: 'apple/swift-argument-parser',
|
|
currentValue: '1.2.1',
|
|
});
|
|
|
|
// Check that ZIPFoundation was extracted from the multi-line declaration
|
|
expect(result?.deps).toContainEqual({
|
|
datasource: 'github-tags',
|
|
depName: 'weichsel/ZIPFoundation',
|
|
currentValue: 'from : "0.9.6"',
|
|
});
|
|
});
|
|
|
|
it('handles malformed URLs gracefully', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "not-a-valid-url", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('handles dependencies without version', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('handles dependencies with local package', () => {
|
|
const content = codeBlock`
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(path: "../LocalPackage")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('handles dependencies with name (deprecated args)', () => {
|
|
const content = codeBlock`
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(name: "repo", url: "https://github.com/example/repo", from: "1.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result?.deps).toMatchObject([
|
|
{ depName: 'example/repo', currentValue: 'from: "1.0.0"' },
|
|
]);
|
|
});
|
|
|
|
it('extracts multiple dependencies with different datasources', () => {
|
|
const content = `
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/github-repo", from: "1.0.0"),
|
|
.package(url: "https://gitlab.com/example/gitlab-repo", from: "2.0.0"),
|
|
.package(url: "https://example.com/other-repo.git", from: "3.0.0")
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result?.deps).toHaveLength(3);
|
|
expect(result?.deps[0].datasource).toBe('github-tags');
|
|
expect(result?.deps[1].datasource).toBe('gitlab-tags');
|
|
expect(result?.deps[2].datasource).toBe('git-tags');
|
|
});
|
|
|
|
it('extracts multiple dependencies with traits arguments', () => {
|
|
const content = codeBlock`
|
|
let package = Package(
|
|
name: "MyPackage",
|
|
dependencies: [
|
|
.package(url: "https://github.com/example/repo1", from: "1.0.0", traits: []),
|
|
.package(url: "https://github.com/example/repo2", "2.0.0"..<"3.0.0", traits: [.defaults]),
|
|
.package(
|
|
url: "https://github.com/example/repo3",
|
|
.exact("4.0.0"),
|
|
traits: [
|
|
.trait(name: "CUSTOM_TRAIT"),
|
|
.trait(name: "ANOTHER_TRAIT")
|
|
]
|
|
)
|
|
]
|
|
)
|
|
`;
|
|
const result = extractPackageFile(content);
|
|
expect(result?.deps).toHaveLength(3);
|
|
expect(result?.deps).toMatchObject([
|
|
{ depName: 'example/repo1', currentValue: 'from: "1.0.0"' },
|
|
{ depName: 'example/repo2', currentValue: '"2.0.0"..<"3.0.0"' },
|
|
{ depName: 'example/repo3', currentValue: '4.0.0' },
|
|
]);
|
|
});
|
|
});
|
|
});
|