From 1d7a98446ade1591e32e80337167cb1d946922ad Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Wed, 28 Apr 2021 01:09:21 +0400 Subject: [PATCH] refactor(maven): Refactor datasource tests (#9745) --- .../mysql-connector-java/maven-metadata.xml | 12 - .../5.13.0/realm-gradle-plugin-5.13.0.pom | 40 - .../realm-gradle-plugin/maven-metadata.xml | 100 --- .../maven/__fixtures__/metadata-extra.xml | 13 + .../maven/__fixtures__/metadata-invalid.xml | 9 + .../maven/__fixtures__/metadata.xml | 16 + .../maven/__fixtures__/pom.scm-prefix.xml | 18 + lib/datasource/maven/__fixtures__/pom.xml | 14 + .../8.0.12/mysql-connector-java-8.0.12.pom | 38 - .../mysql-connector-java/maven-metadata.xml | 17 - .../hamcrest/hamcrest-core/maven-metadata.xml | 19 - .../maven/__snapshots__/index.spec.ts.snap | 848 ++++++++++++++++-- lib/datasource/maven/index.spec.ts | 549 ++++++------ lib/datasource/maven/util.ts | 1 + 14 files changed, 1110 insertions(+), 584 deletions(-) delete mode 100644 lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/mysql/mysql-connector-java/maven-metadata.xml delete mode 100644 lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/5.13.0/realm-gradle-plugin-5.13.0.pom delete mode 100644 lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/maven-metadata.xml create mode 100644 lib/datasource/maven/__fixtures__/metadata-extra.xml create mode 100644 lib/datasource/maven/__fixtures__/metadata-invalid.xml create mode 100644 lib/datasource/maven/__fixtures__/metadata.xml create mode 100644 lib/datasource/maven/__fixtures__/pom.scm-prefix.xml create mode 100644 lib/datasource/maven/__fixtures__/pom.xml delete mode 100644 lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom delete mode 100644 lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml delete mode 100644 lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/maven-metadata.xml diff --git a/lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/mysql/mysql-connector-java/maven-metadata.xml b/lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/mysql/mysql-connector-java/maven-metadata.xml deleted file mode 100644 index 38781a726fe7f8..00000000000000 --- a/lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/mysql/mysql-connector-java/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - mysql - mysql-connector-java - 6.0.5 - - - 6.0.5 - 6.0.4 - - 20130301200000 - - diff --git a/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/5.13.0/realm-gradle-plugin-5.13.0.pom b/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/5.13.0/realm-gradle-plugin-5.13.0.pom deleted file mode 100644 index 7cb22951e8a32e..00000000000000 --- a/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/5.13.0/realm-gradle-plugin-5.13.0.pom +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - io.realm - realm-gradle-plugin - 5.13.0 - - - io.realm - realm-transformer - 5.13.0 - compile - - - com.neenbedankt.gradle.plugins - android-apt - 1.8 - compile - - - realm-gradle-plugin - Gradle plugin for Realm. Realm is a mobile database: a replacement for SQLite & ORMs. - http://realm.io - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - github - https://github.com/realm/realm-java/issues - - - scm:https://github.com/realm/realm-java - scm:git@github.com:realm/realm-java.git - scm:git@github.com:realm/realm-java.git - - diff --git a/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/maven-metadata.xml b/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/maven-metadata.xml deleted file mode 100644 index 514e83f8329c01..00000000000000 --- a/lib/datasource/maven/__fixtures__/jcenter/io/realm/realm-gradle-plugin/maven-metadata.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - io.realm - realm-gradle-plugin - 5.13.0 - - 5.13.0 - 5.13.0 - - 0.85.0 - 0.85.1 - 0.86.0 - 0.86.1 - 0.87.0 - 0.87.1 - 0.87.2 - 0.87.3 - 0.87.4 - 0.87.5 - 0.88.0 - 0.88.1 - 0.88.2 - 0.88.3 - 0.89.0 - 0.89.1 - 0.90.0 - 0.90.1 - 0.91.0 - 0.91.1 - 1.0.0 - 1.0.1 - 1.1.0 - 1.1.1 - 1.2.0 - 2.0.0 - 2.0.1 - 2.0.2 - 2.1.0 - 2.1.1 - 2.2.0 - 2.2.1 - 2.2.2 - 2.3.0 - 2.3.1 - 2.3.2 - 3.0.0 - 3.1.0 - 3.1.1 - 3.1.2 - 3.1.3 - 3.1.4 - 3.2.0 - 3.2.1 - 3.3.0 - 3.3.1 - 3.3.2 - 3.4.0 - 3.5.0 - 3.6.0 - 3.7.0 - 3.7.1 - 3.7.2 - 4.0.0-RC1 - 4.0.0 - 4.1.0 - 4.1.1 - 4.2.0 - 4.3.0 - 4.3.1 - 4.3.2 - 4.3.3 - 4.3.4 - 4.4.0 - 5.0.0-BETA1 - 5.0.0 - 5.0.1 - 5.1.0 - 5.2.0 - 5.3.0 - 5.3.1 - 5.4.0 - 5.4.1 - 5.4.2 - 5.5.0 - 5.6.0 - 5.7.0 - 5.7.1 - 5.8.0-BETA1 - 5.8.0-BETA2 - 5.8.0 - 5.9.0 - 5.9.1 - 5.10.0 - 5.11.0 - 5.12.0 - 5.13.0 - - 20190723221805 - - diff --git a/lib/datasource/maven/__fixtures__/metadata-extra.xml b/lib/datasource/maven/__fixtures__/metadata-extra.xml new file mode 100644 index 00000000000000..d9607d4fda0847 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/metadata-extra.xml @@ -0,0 +1,13 @@ + + + org.example + package + + 3.0.0 + 3.0.0 + + 3.0.0 + + 20210101000000 + + diff --git a/lib/datasource/maven/__fixtures__/metadata-invalid.xml b/lib/datasource/maven/__fixtures__/metadata-invalid.xml new file mode 100644 index 00000000000000..eb92a3c0ed6cfa --- /dev/null +++ b/lib/datasource/maven/__fixtures__/metadata-invalid.xml @@ -0,0 +1,9 @@ + + + org.example + package + 3.0.0-SNAPSHOT + + 20210101010000 + + diff --git a/lib/datasource/maven/__fixtures__/metadata.xml b/lib/datasource/maven/__fixtures__/metadata.xml new file mode 100644 index 00000000000000..a355205eb254e2 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/metadata.xml @@ -0,0 +1,16 @@ + + + org.example + package + + 2.0.0 + 2.0.0 + + 1.0.0 + 1.0.1 + 1.0.2 + 2.0.0 + + 20210101000000 + + diff --git a/lib/datasource/maven/__fixtures__/pom.scm-prefix.xml b/lib/datasource/maven/__fixtures__/pom.scm-prefix.xml new file mode 100644 index 00000000000000..d939ede245f393 --- /dev/null +++ b/lib/datasource/maven/__fixtures__/pom.scm-prefix.xml @@ -0,0 +1,18 @@ + + + + 4.0.0 + org.example + package + Generic Package + Generic Maven Package + + scm:https://github.com/example/test + scm:git@github.com:example/test.git + scm:git@github.com:example/test.git + + diff --git a/lib/datasource/maven/__fixtures__/pom.xml b/lib/datasource/maven/__fixtures__/pom.xml new file mode 100644 index 00000000000000..2183fc473fea9a --- /dev/null +++ b/lib/datasource/maven/__fixtures__/pom.xml @@ -0,0 +1,14 @@ + + + + 4.0.0 + org.example + package + Generic Package + Generic Maven Package + https://package.example.org/about + diff --git a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom b/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom deleted file mode 100644 index 09e1cb25900e19..00000000000000 --- a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom +++ /dev/null @@ -1,38 +0,0 @@ - - 4.0.0 - mysql - mysql-connector-java - 8.0.12 - jar - - MySQL Connector/J - JDBC Type 4 driver for MySQL - - - - The GNU General Public License, v2 with FOSS exception - repo - For detailed license information see the LICENSE file in this distribution. - - - - http://dev.mysql.com/doc/connector-j/en/ - - - scm:git:git@github.com:mysql/mysql-connector-j.git - https://github.com/mysql/mysql-connector-j - - - - Oracle Corporation - http://www.oracle.com - - - - - com.google.protobuf - protobuf-java - 2.6.0 - - - diff --git a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml b/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml deleted file mode 100644 index 4c3bd0fea3e1b6..00000000000000 --- a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml +++ /dev/null @@ -1,17 +0,0 @@ - - mysql - mysql-connector-java - 8.0.12 - - - 8.0.12 - 8.0.11 - 8.0.9 - 8.0.8 - 8.0.7 - 6.0.6 - 6.0.5 - - 20130301200000 - - diff --git a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/maven-metadata.xml b/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/maven-metadata.xml deleted file mode 100644 index 027fecd11a88f3..00000000000000 --- a/lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/org/hamcrest/hamcrest-core/maven-metadata.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - org.hamcrest - hamcrest-core - - 2.1-rc3 - 2.1-rc3 - - 1.1 - 1.2 - 1.2.1 - 1.3.RC2 - 1.3 - 2.1-rc2 - 2.1-rc3 - - 20181129182853 - - diff --git a/lib/datasource/maven/__snapshots__/index.spec.ts.snap b/lib/datasource/maven/__snapshots__/index.spec.ts.snap index ddedb1b554257c..8906027ab35a76 100644 --- a/lib/datasource/maven/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/maven/__snapshots__/index.spec.ts.snap @@ -1,186 +1,860 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`datasource/maven/index getReleases should return all versions from a custom repository 1`] = ` +exports[`datasource/maven/index collects releases from all registry urls 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/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://custom.registry.renovatebot.com/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://custom.registry.renovatebot.com/org/example/package/3.0.0/package-3.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://custom.registry.renovatebot.com/org/example/package/3.0.0/package-3.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index falls back to next registry url 1`] = ` Object { - "display": "mysql:mysql-connector-java", - "group": "mysql", - "homepage": "http://dev.mysql.com/doc/connector-j/en/", - "name": "mysql-connector-java", - "registryUrl": "https://custom.registry.renovatebot.com", + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://repo.maven.apache.org/maven2", "releases": Array [ Object { - "version": "6.0.5", + "releaseTimestamp": "2020-01-01T01:00:00.000Z", + "version": "1.0.0", }, Object { - "version": "6.0.6", + "releaseTimestamp": "2020-01-01T02:00:00.000Z", + "version": "2.0.0", }, - Object { - "version": "8.0.7", + ], +} +`; + +exports[`datasource/maven/index falls back to next registry url 2`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "failed_repo", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://failed_repo/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "unauthorized_repo", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://unauthorized_repo/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "empty_repo", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://empty_repo/org/example/package/maven-metadata.xml", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "unknown_error", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://unknown_error/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": "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/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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 handles optional slash at the end of registry url 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/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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/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/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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 ignores unsupported protocols 1`] = ` +Array [ + Object { + "releaseTimestamp": "2020-01-01T01:00:00.000Z", + "version": "1.0.0", + }, + Object { + "releaseTimestamp": "2020-01-01T02:00:00.000Z", + "version": "2.0.0", + }, +] +`; + +exports[`datasource/maven/index ignores unsupported protocols 2`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "http://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": "http://repo.maven.apache.org/maven2/org/example/package/1.0.0/package-1.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", }, + "method": "HEAD", + "url": "http://repo.maven.apache.org/maven2/org/example/package/1.0.1/package-1.0.1.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "http://repo.maven.apache.org/maven2/org/example/package/1.0.2/package-1.0.2.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "repo.maven.apache.org", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "http://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": "http://repo.maven.apache.org/maven2/org/example/package/2.0.0/package-2.0.0.pom", + }, +] +`; + +exports[`datasource/maven/index removes authentication header after redirect 1`] = ` +Object { + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://frontend_for_private_s3_repository/maven2", + "releases": Array [ Object { - "version": "8.0.8", + "version": "1.0.0", }, Object { - "version": "8.0.9", + "version": "1.0.1", }, Object { - "version": "8.0.11", + "version": "1.0.2", }, Object { - "version": "8.0.12", + "version": "2.0.0", }, ], - "sourceUrl": "https://github.com/mysql/mysql-connector-j", } `; -exports[`datasource/maven/index getReleases should return all versions of a specific library if a repository fails 1`] = ` +exports[`datasource/maven/index removes authentication header after redirect 2`] = ` Array [ Object { - "releaseTimestamp": "2020-01-01T00:00:00.650Z", - "version": "6.0.5", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=", + "host": "frontend_for_private_s3_repository", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://frontend_for_private_s3_repository/maven2/org/example/package/maven-metadata.xml", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.660Z", - "version": "6.0.6", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "private_s3_repository", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://private_s3_repository/maven2/org/example/package/maven-metadata.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.870Z", - "version": "8.0.7", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=", + "host": "frontend_for_private_s3_repository", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://frontend_for_private_s3_repository/maven2/org/example/package/2.0.0/package-2.0.0.pom", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.880Z", - "version": "8.0.8", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "private_s3_repository", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://private_s3_repository/maven2/org/example/package/2.0.0/package-2.0.0.pom?X-Amz-Algorithm=AWS4-HMAC-SHA256", }, +] +`; + +exports[`datasource/maven/index returns null when metadata is not found 1`] = ` +Array [ Object { - "releaseTimestamp": "2020-01-01T00:00:00.890Z", - "version": "8.0.9", + "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", }, ] `; -exports[`datasource/maven/index getReleases should return all versions of a specific library if a repository fails because invalid metadata file is found in another repository 1`] = ` +exports[`datasource/maven/index returns releases 1`] = ` Object { - "display": "mysql:mysql-connector-java", - "group": "mysql", - "name": "mysql-connector-java", - "registryUrl": "https://repo.maven.apache.org/maven2/", + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://repo.maven.apache.org/maven2", "releases": Array [ Object { - "releaseTimestamp": "2020-01-01T00:00:00.650Z", - "version": "6.0.5", + "releaseTimestamp": "2020-01-01T01:00:00.000Z", + "version": "1.0.0", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.660Z", - "version": "6.0.6", + "releaseTimestamp": "2020-01-01T02:00:00.000Z", + "version": "2.0.0", }, - Object { - "releaseTimestamp": "2020-01-01T00:00:00.870Z", - "version": "8.0.7", + ], +} +`; + +exports[`datasource/maven/index returns releases 2`] = ` +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/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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 returns releases from custom repository 1`] = ` +Object { + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://custom.registry.renovatebot.com", + "releases": Array [ Object { - "releaseTimestamp": "2020-01-01T00:00:00.880Z", - "version": "8.0.8", + "version": "1.0.0", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.890Z", - "version": "8.0.9", + "version": "2.0.0", }, ], } `; -exports[`datasource/maven/index getReleases should return all versions of a specific library if a repository fails because invalid protocol 1`] = ` +exports[`datasource/maven/index returns releases from custom repository 2`] = ` Array [ Object { - "releaseTimestamp": "2020-01-01T00:00:00.650Z", - "version": "6.0.5", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://custom.registry.renovatebot.com/org/example/package/maven-metadata.xml", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.660Z", - "version": "6.0.6", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://custom.registry.renovatebot.com/org/example/package/1.0.0/package-1.0.0.pom", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.870Z", - "version": "8.0.7", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://custom.registry.renovatebot.com/org/example/package/1.0.1/package-1.0.1.pom", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.880Z", - "version": "8.0.8", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://custom.registry.renovatebot.com/org/example/package/1.0.2/package-1.0.2.pom", }, Object { - "releaseTimestamp": "2020-01-01T00:00:00.890Z", - "version": "8.0.9", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "HEAD", + "url": "https://custom.registry.renovatebot.com/org/example/package/2.0.0/package-2.0.0.pom", + }, + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "custom.registry.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://custom.registry.renovatebot.com/org/example/package/2.0.0/package-2.0.0.pom", }, ] `; -exports[`datasource/maven/index getReleases should return versions in all repositories for a specific library 1`] = ` +exports[`datasource/maven/index skips registry with invalid XML 1`] = ` Object { - "display": "mysql:mysql-connector-java", - "group": "mysql", - "homepage": "http://dev.mysql.com/doc/connector-j/en/", - "name": "mysql-connector-java", + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://repo.maven.apache.org/maven2", "releases": Array [ Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/", - "version": "6.0.4", + "releaseTimestamp": "2020-01-01T01:00:00.000Z", + "version": "1.0.0", }, Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "6.0.5", + "releaseTimestamp": "2020-01-01T02:00:00.000Z", + "version": "2.0.0", }, - Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "6.0.6", + ], +} +`; + +exports[`datasource/maven/index skips registry with invalid XML 2`] = ` +Array [ + Object { + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "invalid_metadata_repo", + "user-agent": "https://github.com/renovatebot/renovate", }, - Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "8.0.7", + "method": "GET", + "url": "https://invalid_metadata_repo/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", }, - Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "8.0.8", + "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", }, - Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "8.0.9", + "method": "HEAD", + "url": "https://repo.maven.apache.org/maven2/org/example/package/1.0.0/package-1.0.0.pom", + }, + 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/1.0.1/package-1.0.1.pom", + }, + 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/1.0.2/package-1.0.2.pom", + }, + 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 skips registry with invalid metadata structure 1`] = ` +Object { + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "https://repo.maven.apache.org/maven2", + "releases": Array [ Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "8.0.11", + "releaseTimestamp": "2020-01-01T01:00:00.000Z", + "version": "1.0.0", }, Object { - "registryUrl": "file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/", - "version": "8.0.12", + "releaseTimestamp": "2020-01-01T02:00:00.000Z", + "version": "2.0.0", }, ], - "sourceUrl": "https://github.com/mysql/mysql-connector-j", } `; -exports[`datasource/maven/index getReleases should simply return all versions of a specific library 1`] = ` +exports[`datasource/maven/index skips registry with invalid metadata structure 2`] = ` Array [ Object { - "version": "1.1", + "headers": Object { + "accept-encoding": "gzip, deflate, br", + "host": "invalid_metadata_repo", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://invalid_metadata_repo/org/example/package/maven-metadata.xml", }, Object { - "version": "1.2", + "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 { - "version": "1.2.1", + "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/1.0.0/package-1.0.0.pom", }, Object { - "version": "1.3.RC2", + "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/1.0.1/package-1.0.1.pom", }, Object { - "version": "1.3", + "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/1.0.2/package-1.0.2.pom", }, Object { - "version": "2.1-rc2", + "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 { - "version": "2.1-rc3", + "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 supports file protocol 1`] = ` +Object { + "display": "org.example:package", + "group": "org.example", + "homepage": "https://package.example.org/about", + "name": "package", + "registryUrl": "file:///bar", + "releases": Array [ + Object { + "version": "1.0.0", + }, + Object { + "version": "1.0.1", + }, + Object { + "version": "1.0.2", + }, + Object { + "version": "2.0.0", + }, + ], +} +`; + +exports[`datasource/maven/index supports file protocol 2`] = ` +Array [ + Array [ + "/bar/org/example/package/maven-metadata.xml", + "utf8", + ], + Array [ + "/bar/org/example/package/2.0.0/package-2.0.0.pom", + "utf8", + ], +] +`; + +exports[`datasource/maven/index throws EXTERNAL_HOST_ERROR for 50x 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", }, ] `; diff --git a/lib/datasource/maven/index.spec.ts b/lib/datasource/maven/index.spec.ts index 33f60510fadc7f..43bdf411619c3f 100644 --- a/lib/datasource/maven/index.spec.ts +++ b/lib/datasource/maven/index.spec.ts @@ -1,314 +1,321 @@ -import nock from 'nock'; -import { Release, getPkgReleases } from '..'; -import { getName, loadFixture } from '../../../test/util'; +import _fs from 'fs-extra'; +import { ReleaseResult, getPkgReleases } from '..'; +import * as httpMock from '../../../test/http-mock'; +import { getName, loadFixture, mocked } from '../../../test/util'; import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages'; import * as hostRules from '../../util/host-rules'; -import * as mavenVersioning from '../../versioning/maven'; +import { id as versioning } from '../../versioning/maven'; import { id as datasource } from '.'; -const MYSQL_VERSIONS = ['6.0.5', '6.0.6', '8.0.7', '8.0.8', '8.0.9']; +jest.mock('fs-extra'); +const fs = mocked(_fs); -const MYSQL_MAVEN_METADATA = loadFixture( - 'repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml' -); +const baseUrl = 'https://repo.maven.apache.org/maven2'; +const baseUrlCustom = 'https://custom.registry.renovatebot.com'; -const MYSQL_MAVEN_MYSQL_POM = loadFixture( - 'repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' -); +interface MockOpts { + base?: string; + meta?: string; + pom?: string; + heads?: Record; +} + +function mockGenericPackage(opts: MockOpts = {}) { + const { + base = baseUrl, + meta = loadFixture('metadata.xml'), + pom = loadFixture('pom.xml'), + heads = { + '1.0.0': 200, + '1.0.1': 404, + '1.0.2': 500, + '2.0.0': 200, + }, + } = opts; -const config = { - versioning: mavenVersioning.id, - datasource, -}; + const scope = httpMock.scope(base); -function timestamp(version: string): string { - const millis = (version.replace(/[^1-9]/g, '') + '000').slice(0, 3); - return `2020-01-01T00:00:00.${millis}Z`; + scope.get('/org/example/package/maven-metadata.xml').reply(200, meta); + + if (heads) { + const pairs = Object.entries(heads); + const latest = pairs + .filter(([, s]) => s >= 200 && s < 300) + .map(([v]) => v) + .sort() + .pop(); + scope + .get(`/org/example/package/${latest}/package-${latest}.pom`) + .reply(200, pom); + pairs.forEach(([version, status]) => { + const [major, minor, patch] = version + .split('.') + .map((x) => parseInt(x, 10)) + .map((x) => (x < 10 ? `0${x}` : `${x}`)); + const timestamp = `2020-01-01T${major}:${minor}:${patch}.000Z`; + scope + .head(`/org/example/package/${version}/package-${version}.pom`) + .reply(status, '', { 'Last-Modified': timestamp }); + }); + } } -function generateReleases(versions: string[], ts = false): Release[] { - return versions.map((version) => { - if (ts) { - const releaseTimestamp = timestamp(version); - return { version, releaseTimestamp }; - } - return { version }; - }); +function get( + depName: string, + ...registryUrls: string[] +): Promise { + const conf = { versioning, datasource, depName }; + return getPkgReleases(registryUrls ? { ...conf, registryUrls } : conf); } describe(getName(), () => { beforeEach(() => { - hostRules.add({ - hostType: datasource, - hostName: 'frontend_for_private_s3_repository', - username: 'username', - password: 'password', - timeout: 20000, - }); hostRules.add({ hostType: datasource, hostName: 'custom.registry.renovatebot.com', token: 'abc123', }); jest.resetAllMocks(); - nock.cleanAll(); - nock.disableNetConnect(); - nock('https://repo.maven.apache.org') - .get('/maven2/mysql/mysql-connector-java/maven-metadata.xml') - .reply(200, MYSQL_MAVEN_METADATA); - nock('https://repo.maven.apache.org') - .get( - '/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' - ) - .reply(200, MYSQL_MAVEN_MYSQL_POM); - nock('https://custom.registry.renovatebot.com') - .get('/mysql/mysql-connector-java/maven-metadata.xml') - .reply(200, MYSQL_MAVEN_METADATA); - nock('https://custom.registry.renovatebot.com') - .get('/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom') - .reply(200, MYSQL_MAVEN_MYSQL_POM); - nock('http://failed_repo') - .get('/mysql/mysql-connector-java/maven-metadata.xml') - .reply(404, null); - nock('http://unauthorized_repo') - .get('/mysql/mysql-connector-java/maven-metadata.xml') - .reply(403, null); - nock('http://empty_repo') - .get('/mysql/mysql-connector-java/maven-metadata.xml') - .reply(200, 'non-sense'); - nock('http://frontend_for_private_s3_repository') - .get('/maven2/mysql/mysql-connector-java/maven-metadata.xml') - .basicAuth({ user: 'username', pass: 'password' }) - .reply(302, '', { - Location: - 'http://private_s3_repository/maven2/mysql/mysql-connector-java/maven-metadata.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256', - }) - .get( - '/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' - ) - .basicAuth({ user: 'username', pass: 'password' }) - .reply(302, '', { - Location: - 'http://private_s3_repository/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom?X-Amz-Algorithm=AWS4-HMAC-SHA256', - }); - nock('http://private_s3_repository', { badheaders: ['authorization'] }) - .get( - '/maven2/mysql/mysql-connector-java/maven-metadata.xml?X-Amz-Algorithm=AWS4-HMAC-SHA256' - ) - .reply(200, MYSQL_MAVEN_METADATA) - .get( - '/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom?X-Amz-Algorithm=AWS4-HMAC-SHA256' - ) - .reply(200, MYSQL_MAVEN_MYSQL_POM); - Object.entries({ - '6.0.5': 200, - '6.0.6': 200, - '8.0.7': 200, - '8.0.8': 200, - '8.0.9': 200, - '8.0.11': 404, - '8.0.12': 500, - }).forEach(([v, status]) => { - const path = `/maven2/mysql/mysql-connector-java/${v}/mysql-connector-java-${v}.pom`; - nock('https://repo.maven.apache.org') - .head(path) - .reply(status, '', { 'Last-Modified': timestamp(v) }); - nock('http://frontend_for_private_s3_repository') - .head(path) - .reply(status, '', { 'Last-Modified': timestamp(v) }); - }); + httpMock.setup(); }); afterEach(() => { - nock.enableNetConnect(); + hostRules.clear(); + httpMock.reset(); delete process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK; }); - describe('getReleases', () => { - it('should return empty if library is not found', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'unknown:unknown', - registryUrls: [ - 's3://somewhere.s3.aws.amazon.com', - 'file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/', - ], - }); - expect(releases).toBeNull(); - }); + it('returns null when metadata is not found', async () => { + httpMock + .scope(baseUrl) + .get('/org/example/package/maven-metadata.xml') + .reply(404); - it('should simply return all versions of a specific library', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'org.hamcrest:hamcrest-core', - registryUrls: [ - 'file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/', - 'file://lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/', - 's3://somewhere.s3.aws.amazon.com', - ], - }); - expect(releases.releases).toMatchSnapshot(); - }); + const res = await get('org.example:package'); - it('should return versions in all repositories for a specific library', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: [ - 'file://lib/datasource/maven/__fixtures__/repo1.maven.org/maven2/', - 'file://lib/datasource/maven/__fixtures__/custom_maven_repo/maven2/', - ], - }); - expect(releases).toMatchSnapshot(); - }); + expect(res).toBeNull(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); - it('should return all versions of a specific library for http repositories', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: ['https://repo.maven.apache.org/maven2/'], - }); - expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS, true)); - }); + it('returns releases', async () => { + mockGenericPackage(); - it('should return all versions from a custom repository', async () => { - process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK = 'true'; - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: ['https://custom.registry.renovatebot.com'], - }); - expect(releases).toMatchSnapshot(); - }); + const res = await get('org.example:package'); - it('should return all versions of a specific library if a repository fails', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: [ - 'https://repo.maven.apache.org/maven2/', - 'http://failed_repo/', - 'http://unauthorized_repo/', - 'http://dns_error_repo', - 'http://empty_repo', - ], - }); - expect(releases.releases).toMatchSnapshot(); - }); + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); - it('should throw external-host-error if default maven repo fails', async () => { - nock('https://repo.maven.apache.org') - .get('/maven2/org/artifact/maven-metadata.xml') - .times(4) - .reply(503); - - expect.assertions(1); - await expect( - getPkgReleases({ - ...config, - depName: 'org:artifact', - registryUrls: ['https://repo.maven.apache.org/maven2/'], - }) - ).rejects.toThrow(EXTERNAL_HOST_ERROR); - }); + it('returns releases from custom repository', async () => { + mockGenericPackage({ base: baseUrlCustom }); - it('should return all versions of a specific library if a repository fails because invalid protocol', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: [ - 'https://repo.maven.apache.org/maven2/', - 'http://failed_repo/', - 'ftp://protocol_error_repo', - ], - }); - expect(releases.releases).toMatchSnapshot(); - }); + const res = await get('org.example:package', baseUrlCustom); - it('should return all versions of a specific library if a repository fails because invalid metadata file is found in another repository', async () => { - const invalidMavenMetadata = ` - - mysql - mysql-connector-java - 8.0.12 - - 20130301200000 - - - `; - nock('http://invalid_metadata_repo') - .get('/maven2/mysql/mysql-connector-java/maven-metadata.xml') - .reply(200, invalidMavenMetadata); - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: [ - 'https://repo.maven.apache.org/maven2/', - 'http://invalid_metadata_repo/maven2/', - ], - }); - expect(releases).toMatchSnapshot(); - }); + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); - it('should return all versions of a specific library if a repository fails because a metadata file is not xml', async () => { - const invalidMavenMetadata = ` - Invalid XML - `; - nock('http://invalid_metadata_repo') - .get('/maven2/mysql/mysql-connector-java/maven-metadata.xml') - .reply(200, invalidMavenMetadata); - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: [ - 'https://repo.maven.apache.org/maven2/', - 'http://invalid_metadata_repo/maven2/', - ], - }); - expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS, true)); + it('collects releases from all registry urls', async () => { + mockGenericPackage(); + mockGenericPackage({ + base: baseUrlCustom, + meta: loadFixture('metadata-extra.xml'), + heads: { '3.0.0': 200 }, }); - it('should return all versions of a specific library if a repository does not end with /', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: ['https://repo.maven.apache.org/maven2'], - }); - expect(releases).not.toBeNull(); - }); + const { releases } = await get( + 'org.example:package', + baseUrl, + baseUrlCustom + ); - it('should return null if no repositories defined', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - }); - expect(releases).not.toBeNull(); - }); - it('should return null for invalid registryUrls', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - // eslint-disable-next-line no-template-curly-in-string - registryUrls: ['${project.baseUri}../../repository/'], - }); - expect(releases).toBeNull(); - }); - it('should support scm.url values prefixed with "scm:"', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'io.realm:realm-gradle-plugin', - registryUrls: ['file://lib/datasource/maven/__fixtures__/jcenter/'], - }); - expect(releases.sourceUrl).toEqual('https://github.com/realm/realm-java'); + expect(releases).toMatchObject([ + { version: '1.0.0' }, + { version: '2.0.0' }, + { version: '3.0.0' }, + ]); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('falls back to next registry url', async () => { + mockGenericPackage(); + httpMock + .scope('https://failed_repo') + .get('/org/example/package/maven-metadata.xml') + .reply(404, null); + httpMock + .scope('https://unauthorized_repo') + .get('/org/example/package/maven-metadata.xml') + .reply(403, null); + httpMock + .scope('https://empty_repo') + .get('/org/example/package/maven-metadata.xml') + .reply(200, 'non-sense'); + httpMock + .scope('https://unknown_error') + .get('/org/example/package/maven-metadata.xml') + .replyWithError('unknown'); + + const res = await get( + 'org.example:package', + 'https://failed_repo/', + 'https://unauthorized_repo/', + 'https://empty_repo', + 'https://unknown_error', + baseUrl + ); + + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('throws EXTERNAL_HOST_ERROR for 50x', async () => { + httpMock + .scope(baseUrl) + .get('/org/example/package/maven-metadata.xml') + .reply(503); + + await expect(get('org.example:package')).rejects.toThrow( + EXTERNAL_HOST_ERROR + ); + + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('ignores unsupported protocols', async () => { + const base = baseUrl.replace('https', 'http'); + mockGenericPackage({ base }); + + const { releases } = await get( + 'org.example:package', + 'ftp://protocol_error_repo', + 's3://protocol_error_repo', + base + ); + + expect(releases).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('skips registry with invalid metadata structure', async () => { + mockGenericPackage(); + httpMock + .scope('https://invalid_metadata_repo') + .get('/org/example/package/maven-metadata.xml') + .reply(200, loadFixture('metadata-invalid.xml')); + + const res = await get( + 'org.example:package', + 'https://invalid_metadata_repo', + baseUrl + ); + + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('skips registry with invalid XML', async () => { + mockGenericPackage(); + httpMock + .scope('https://invalid_metadata_repo') + .get('/org/example/package/maven-metadata.xml') + .reply(200, '###'); + + const res = await get( + 'org.example:package', + 'https://invalid_metadata_repo', + baseUrl + ); + + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('handles optional slash at the end of registry url', async () => { + mockGenericPackage(); + const resA = await get('org.example:package', baseUrl.replace(/\/+$/, '')); + mockGenericPackage(); + const resB = await get('org.example:package', baseUrl.replace(/\/*$/, '/')); + expect(resA).not.toBeNull(); + expect(resB).not.toBeNull(); + expect(resA.releases).toEqual(resB.releases); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('returns null for invalid registryUrls', async () => { + const res = await get( + 'org.example:package', + // eslint-disable-next-line no-template-curly-in-string + '${project.baseUri}../../repository/' + ); + expect(res).toBeNull(); + }); + + it('supports scm.url values prefixed with "scm:"', async () => { + const pom = loadFixture('pom.scm-prefix.xml'); + mockGenericPackage({ pom }); + + const { sourceUrl } = await get('org.example:package'); + + expect(sourceUrl).toEqual('https://github.com/example/test'); + }); + + it('removes authentication header after redirect', async () => { + process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK = 'true'; + + const frontendHost = 'frontend_for_private_s3_repository'; + const frontendUrl = `https://${frontendHost}/maven2`; + const backendUrl = 'https://private_s3_repository/maven2'; + const metadataPath = '/org/example/package/maven-metadata.xml'; + const pomfilePath = '/org/example/package/2.0.0/package-2.0.0.pom'; + const queryStr = '?X-Amz-Algorithm=AWS4-HMAC-SHA256'; + + hostRules.add({ + hostType: datasource, + hostName: frontendHost, + username: 'username', + password: 'password', + timeout: 20000, }); - it('should remove authentication header when redirected with authentication in query string', async () => { - const releases = await getPkgReleases({ - ...config, - depName: 'mysql:mysql-connector-java', - registryUrls: ['http://frontend_for_private_s3_repository/maven2'], + httpMock + .scope(frontendUrl) + .get(metadataPath) + .basicAuth({ user: 'username', pass: 'password' }) + .reply(302, '', { + Location: `${backendUrl}${metadataPath}${queryStr}`, + }) + .get(pomfilePath) + .basicAuth({ user: 'username', pass: 'password' }) + .reply(302, '', { + Location: `${backendUrl}${pomfilePath}${queryStr}`, }); - expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS)); - }); + + httpMock + .scope(backendUrl, { badheaders: ['authorization'] }) + .get(`${metadataPath}${queryStr}`) + .reply(200, loadFixture('metadata.xml')) + .get(`${pomfilePath}${queryStr}`) + .reply(200, loadFixture('pom.xml')); + + const res = await get('org.example:package', frontendUrl); + + expect(res).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('supports file protocol', async () => { + fs.exists.mockResolvedValueOnce(false); + + fs.exists.mockResolvedValueOnce(true); + fs.readFile.mockResolvedValueOnce(Buffer.from(loadFixture('metadata.xml'))); + + fs.exists.mockResolvedValueOnce(true); + fs.readFile.mockResolvedValueOnce(Buffer.from(loadFixture('pom.xml'))); + + const res = await get('org.example:package', 'file:///foo', 'file:///bar'); + + expect(res).toMatchSnapshot(); + expect(fs.readFile.mock.calls).toMatchSnapshot(); }); }); diff --git a/lib/datasource/maven/util.ts b/lib/datasource/maven/util.ts index 311c1041d4374d..464d2709fd31ac 100644 --- a/lib/datasource/maven/util.ts +++ b/lib/datasource/maven/util.ts @@ -189,6 +189,7 @@ export async function getDependencyInfo( const pomUrl = getMavenUrl(dependency, repoUrl, path); const { xml: pomContent } = await downloadMavenXml(pomUrl); + // istanbul ignore if if (!pomContent) { return result; }