diff --git a/lib/datasource/maven/__fixtures__/child-all-info/meta.xml b/lib/datasource/maven/__fixtures__/child-all-info/meta.xml new file mode 100644 index 00000000000000..8927f14aa205f0 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-all-info/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-all-info + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-all-info/pom.xml b/lib/datasource/maven/__fixtures__/child-all-info/pom.xml new file mode 100644 index 00000000000000..38a060ce1769f1 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-all-info/pom.xml @@ -0,0 +1,12 @@ + + + org.example + parent + 1.0.0 + + + + scm:git:http://www.github.com/child-scm/child + + https://child-home.example.com + diff --git a/lib/datasource/maven/__fixtures__/child-empty/meta.xml b/lib/datasource/maven/__fixtures__/child-empty/meta.xml new file mode 100644 index 00000000000000..efcaf6091919d5 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-empty/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-no-info + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-empty/pom.xml b/lib/datasource/maven/__fixtures__/child-empty/pom.xml new file mode 100644 index 00000000000000..b3f546cac09a4e --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-empty/pom.xml @@ -0,0 +1,4 @@ + + + + diff --git a/lib/datasource/maven/__fixtures__/child-no-info/meta.xml b/lib/datasource/maven/__fixtures__/child-no-info/meta.xml new file mode 100644 index 00000000000000..efcaf6091919d5 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-no-info/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-no-info + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-no-info/pom.xml b/lib/datasource/maven/__fixtures__/child-no-info/pom.xml new file mode 100644 index 00000000000000..1ec845afb44865 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-no-info/pom.xml @@ -0,0 +1,7 @@ + + + org.example + parent + 1.0.0 + + diff --git a/lib/datasource/maven/__fixtures__/child-parent-cycle/child.meta.xml b/lib/datasource/maven/__fixtures__/child-parent-cycle/child.meta.xml new file mode 100644 index 00000000000000..07848472aec2ec --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-parent-cycle/child.meta.xml @@ -0,0 +1,11 @@ + + org.example + package + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-parent-cycle/child.pom.xml b/lib/datasource/maven/__fixtures__/child-parent-cycle/child.pom.xml new file mode 100644 index 00000000000000..6e3c7456bae805 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-parent-cycle/child.pom.xml @@ -0,0 +1,17 @@ + + + + + org.example + parent + 2.0.0 + + org.example + child + Generic Package + Generic Maven Package + diff --git a/lib/datasource/maven/__fixtures__/child-parent-cycle/parent.pom.xml b/lib/datasource/maven/__fixtures__/child-parent-cycle/parent.pom.xml new file mode 100644 index 00000000000000..2760a1dd818d77 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-parent-cycle/parent.pom.xml @@ -0,0 +1,8 @@ + + + org.example + child + 2.0.0 + + https://parent-home.example.com + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/meta.xml b/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/meta.xml new file mode 100644 index 00000000000000..f42fe8589746f0 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-scm-gitatcolon + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/pom.xml b/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/pom.xml new file mode 100644 index 00000000000000..7c3157b5c445bb --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitatcolon/pom.xml @@ -0,0 +1,6 @@ + + + + git@github.com:child-scm/child + + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitatslash/meta.xml b/lib/datasource/maven/__fixtures__/child-scm-gitatslash/meta.xml new file mode 100644 index 00000000000000..07a2b3af129a9e --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitatslash/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-scm-gitatslash + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitatslash/pom.xml b/lib/datasource/maven/__fixtures__/child-scm-gitatslash/pom.xml new file mode 100644 index 00000000000000..2ad57eaa1ffde2 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitatslash/pom.xml @@ -0,0 +1,6 @@ + + + + git@github.com/child-scm/child + + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/meta.xml b/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/meta.xml new file mode 100644 index 00000000000000..1741d3965409af --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-scm-gitprotocol + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/pom.xml b/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/pom.xml new file mode 100644 index 00000000000000..da09dda8a96e76 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm-gitprotocol/pom.xml @@ -0,0 +1,6 @@ + + + + git://github.com/child-scm/child + + diff --git a/lib/datasource/maven/__fixtures__/child-scm/meta.xml b/lib/datasource/maven/__fixtures__/child-scm/meta.xml new file mode 100644 index 00000000000000..c0f390f2aee0f1 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-scm + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-scm/pom.xml b/lib/datasource/maven/__fixtures__/child-scm/pom.xml new file mode 100644 index 00000000000000..a6cf6fea3a0ff7 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-scm/pom.xml @@ -0,0 +1,11 @@ + + + org.example + parent + 1.0.0 + + + + scm:git:https://www.github.com/child-scm/child + + diff --git a/lib/datasource/maven/__fixtures__/child-url/meta.xml b/lib/datasource/maven/__fixtures__/child-url/meta.xml new file mode 100644 index 00000000000000..3fd1398f527e5f --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-url/meta.xml @@ -0,0 +1,11 @@ + + org.example + child-url + 2.0.0 + + + 2.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/child-url/pom.xml b/lib/datasource/maven/__fixtures__/child-url/pom.xml new file mode 100644 index 00000000000000..f153707958a38a --- /dev/null +++ b/lib/datasource/maven/__fixtures__/child-url/pom.xml @@ -0,0 +1,8 @@ + + + org.example + parent + 1.0.0 + + https://child-home.example.com + diff --git a/lib/datasource/maven/__fixtures__/parent-scm-homepage/meta.xml b/lib/datasource/maven/__fixtures__/parent-scm-homepage/meta.xml new file mode 100644 index 00000000000000..2a44ff77578734 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/parent-scm-homepage/meta.xml @@ -0,0 +1,11 @@ + + org.example + parent + 1.0.0 + + + 1.0.0 + + 20130301200000 + + diff --git a/lib/datasource/maven/__fixtures__/parent-scm-homepage/pom.xml b/lib/datasource/maven/__fixtures__/parent-scm-homepage/pom.xml new file mode 100644 index 00000000000000..18357e50fb1351 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/parent-scm-homepage/pom.xml @@ -0,0 +1,7 @@ + + + + scm:git:git://www.github.com/parent-scm/parent + + https://parent-home.example.com + diff --git a/lib/datasource/maven/__snapshots__/index.spec.ts.snap b/lib/datasource/maven/__snapshots__/index.spec.ts.snap index aba4930ded3c49..f401e28a77d53d 100644 --- a/lib/datasource/maven/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/maven/__snapshots__/index.spec.ts.snap @@ -204,6 +204,366 @@ Array [ ] `; +exports[`datasource/maven/index fetching parent info should be able to detect git://@github.com/child-scm as valid sourceUrl 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should be able to detect git@github.com/child-scm as valid sourceUrl 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should be able to detect git@github.com:child-scm as valid sourceUrl 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should deal with circular hierarchy 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/child/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/child/2.0.0/child-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/child/2.0.0/child-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/2.0.0/parent-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/child/2.0.0/child-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/2.0.0/parent-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/child/2.0.0/child-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/2.0.0/parent-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should deal with missing parent fields 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should get homepage and source from own pom 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should get homepage from own pom and source from parent 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/1.0.0/parent-1.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should get source and homepage from parent 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/1.0.0/parent-1.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index fetching parent info should get source from own pom and homepage from parent 1`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://repo.maven.apache.org/maven2/org/example/parent/1.0.0/parent-1.0.0.pom", + }, +] +`; + exports[`datasource/maven/index handles optional slash at the end of registry url 1`] = ` Array [ Object { diff --git a/lib/datasource/maven/index.spec.ts b/lib/datasource/maven/index.spec.ts index 4c9c719fcbcee4..e610a5cc68d35d 100644 --- a/lib/datasource/maven/index.spec.ts +++ b/lib/datasource/maven/index.spec.ts @@ -305,4 +305,191 @@ describe(getName(), () => { expect(res).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot(); }); + + describe('fetching parent info', () => { + const parentPackage = { + dep: 'org.example:parent', + meta: null, + pom: loadFixture('parent-scm-homepage/pom.xml'), + latest: '1.0.0', + jars: null, + }; + + it('should get source and homepage from parent', async () => { + mockGenericPackage({ + meta: loadFixture('child-no-info/meta.xml'), + pom: loadFixture('child-no-info/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + mockGenericPackage(parentPackage); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/parent-scm/parent', + homepage: 'https://parent-home.example.com', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should deal with missing parent fields', async () => { + mockGenericPackage({ + meta: loadFixture('child-empty/meta.xml'), + pom: loadFixture('child-empty/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + + const res = await get(); + + expect(res).toMatchObject({ + display: 'org.example:package', + group: 'org.example', + name: 'package', + }); + expect(res).not.toHaveProperty('homepage'); + expect(res).not.toHaveProperty('sourceUrl'); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should deal with circular hierarchy', async () => { + const parentPom = loadFixture('child-parent-cycle/parent.pom.xml'); + const parentPomMock = { + dep: 'org.example:parent', + meta: null, + pom: parentPom, + latest: '2.0.0', + jars: null, + }; + + const childMeta = loadFixture('child-parent-cycle/child.meta.xml'); + const childPom = loadFixture('child-parent-cycle/child.pom.xml'); + const childPomMock = { + dep: 'org.example:child', + meta: null, + pom: childPom, + latest: '2.0.0', + jars: null, + }; + + mockGenericPackage({ + ...childPomMock, + meta: childMeta, + jars: { '2.0.0': 200 }, + }); + mockGenericPackage(parentPomMock); + mockGenericPackage(childPomMock); + mockGenericPackage(parentPomMock); + mockGenericPackage(childPomMock); + mockGenericPackage(parentPomMock); + + const res = await get('org.example:child'); + + expect(res).toMatchObject({ + homepage: 'https://parent-home.example.com', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should get source from own pom and homepage from parent', async () => { + mockGenericPackage({ + meta: loadFixture('child-scm/meta.xml'), + pom: loadFixture('child-scm/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + mockGenericPackage(parentPackage); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/child-scm/child', + homepage: 'https://parent-home.example.com', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should get homepage from own pom and source from parent', async () => { + mockGenericPackage({ + meta: loadFixture('child-url/meta.xml'), + pom: loadFixture('child-url/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + mockGenericPackage(parentPackage); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/parent-scm/parent', + homepage: 'https://child-home.example.com', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should get homepage and source from own pom', async () => { + mockGenericPackage({ + meta: loadFixture('child-all-info/meta.xml'), + pom: loadFixture('child-all-info/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/child-scm/child', + homepage: 'https://child-home.example.com', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should be able to detect git@github.com:child-scm as valid sourceUrl', async () => { + mockGenericPackage({ + meta: loadFixture('child-scm-gitatcolon/meta.xml'), + pom: loadFixture('child-scm-gitatcolon/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/child-scm/child', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('should be able to detect git@github.com/child-scm as valid sourceUrl', async () => { + mockGenericPackage({ + meta: loadFixture('child-scm-gitatslash/meta.xml'), + pom: loadFixture('child-scm-gitatslash/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/child-scm/child', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + it('should be able to detect git://@github.com/child-scm as valid sourceUrl', async () => { + mockGenericPackage({ + meta: loadFixture('child-scm-gitprotocol/meta.xml'), + pom: loadFixture('child-scm-gitprotocol/pom.xml'), + latest: '2.0.0', + jars: { '2.0.0': 200 }, + }); + + const res = await get(); + + expect(res).toMatchObject({ + sourceUrl: 'https://github.com/child-scm/child', + }); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + }); }); diff --git a/lib/datasource/maven/util.ts b/lib/datasource/maven/util.ts index ed7f7355ce4678..18316d73df55b2 100644 --- a/lib/datasource/maven/util.ts +++ b/lib/datasource/maven/util.ts @@ -163,10 +163,22 @@ export async function downloadMavenXml( return { authorization, xml: new XmlDocument(rawContent) }; } +export function getDependencyParts(lookupName: string): MavenDependency { + const [group, name] = lookupName.split(':'); + const dependencyUrl = `${group.replace(/\./g, '/')}/${name}`; + return { + display: lookupName, + group, + name, + dependencyUrl, + }; +} + export async function getDependencyInfo( dependency: MavenDependency, repoUrl: string, - version: string + version: string, + recursionLimit = 5 ): Promise> { const result: Partial = {}; const path = `${version}/${dependency.name}-${version}.pom`; @@ -185,19 +197,46 @@ export async function getDependencyInfo( const sourceUrl = pomContent.valueWithPath('scm.url'); if (sourceUrl && !containsPlaceholder(sourceUrl)) { - result.sourceUrl = sourceUrl.replace(/^scm:/, ''); + result.sourceUrl = sourceUrl + .replace(/^scm:/, '') + .replace(/^git:/, '') + .replace(/^git@github.com:/, 'https://github.com/') + .replace(/^git@github.com\//, 'https://github.com/') + .replace(/\.git$/, ''); + + if (result.sourceUrl.startsWith('//')) { + // most likely the result of us stripping scm:, git: etc + // going with prepending https: here which should result in potential information retrival + result.sourceUrl = `https:${result.sourceUrl}`; + } } - return result; -} + const parent = pomContent.childNamed('parent'); + if (recursionLimit > 0 && parent && (!result.sourceUrl || !result.homepage)) { + // if we found a parent and are missing some information + // trying to get the scm/homepage information from it + const [parentGroupId, parentArtifactId, parentVersion] = [ + 'groupId', + 'artifactId', + 'version', + ].map((k) => parent.valueWithPath(k)?.replace(/\s+/g, '')); + if (parentGroupId && parentArtifactId && parentVersion) { + const parentDisplayId = `${parentGroupId}:${parentArtifactId}`; + const parentDependency = getDependencyParts(parentDisplayId); + const parentInformation = await getDependencyInfo( + parentDependency, + repoUrl, + parentVersion, + recursionLimit - 1 + ); + if (!result.sourceUrl && parentInformation.sourceUrl) { + result.sourceUrl = parentInformation.sourceUrl; + } + if (!result.homepage && parentInformation.homepage) { + result.homepage = parentInformation.homepage; + } + } + } -export function getDependencyParts(lookupName: string): MavenDependency { - const [group, name] = lookupName.split(':'); - const dependencyUrl = `${group.replace(/\./g, '/')}/${name}`; - return { - display: lookupName, - group, - name, - dependencyUrl, - }; + return result; }