fix(maven): don't cache private (#9038)

This commit is contained in:
Rhys Arkins 2021-03-09 21:03:45 +01:00 committed by GitHub
parent 607b151f0e
commit 95ab97c647
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 21 deletions

View file

@ -0,0 +1,34 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`datasource/maven getReleases should return all versions from a custom repository 1`] = `
Object {
"display": "mysql:mysql-connector-java",
"group": "mysql",
"homepage": "http://dev.mysql.com/doc/connector-j/en/",
"name": "mysql-connector-java",
"releases": Array [
Object {
"version": "6.0.5",
},
Object {
"version": "6.0.6",
},
Object {
"version": "8.0.7",
},
Object {
"version": "8.0.8",
},
Object {
"version": "8.0.9",
},
Object {
"version": "8.0.11",
},
Object {
"version": "8.0.12",
},
],
"sourceUrl": "https://github.com/mysql/mysql-connector-j",
}
`;

View file

@ -54,6 +54,11 @@ describe('datasource/maven', () => {
password: 'password', password: 'password',
timeout: 20000, timeout: 20000,
}); });
hostRules.add({
hostType: datasource,
hostName: 'custom.registry.renovatebot.com',
token: 'abc123',
});
jest.resetAllMocks(); jest.resetAllMocks();
nock.cleanAll(); nock.cleanAll();
nock.disableNetConnect(); nock.disableNetConnect();
@ -65,6 +70,12 @@ describe('datasource/maven', () => {
'/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' '/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom'
) )
.reply(200, MYSQL_MAVEN_MYSQL_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') nock('http://failed_repo')
.get('/mysql/mysql-connector-java/maven-metadata.xml') .get('/mysql/mysql-connector-java/maven-metadata.xml')
.reply(404, null); .reply(404, null);
@ -119,6 +130,7 @@ describe('datasource/maven', () => {
afterEach(() => { afterEach(() => {
nock.enableNetConnect(); nock.enableNetConnect();
delete process.env.RENOVATE_EXPERIMENTAL_NO_MAVEN_POM_CHECK;
}); });
describe('getReleases', () => { describe('getReleases', () => {
@ -180,6 +192,16 @@ describe('datasource/maven', () => {
expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS, true)); expect(releases.releases).toEqual(generateReleases(MYSQL_VERSIONS, true));
}); });
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();
});
it('should return all versions of a specific library if a repository fails', async () => { it('should return all versions of a specific library if a repository fails', async () => {
const releases = await getPkgReleases({ const releases = await getPkgReleases({
...config, ...config,

View file

@ -37,36 +37,44 @@ function getMavenUrl(
return new url.URL(`${dependency.dependencyUrl}/${path}`, repoUrl); return new url.URL(`${dependency.dependencyUrl}/${path}`, repoUrl);
} }
interface MavenXml {
authorization?: boolean;
xml?: XmlDocument;
}
async function downloadMavenXml( async function downloadMavenXml(
pkgUrl: url.URL | null pkgUrl: url.URL | null
): Promise<XmlDocument | null> { ): Promise<MavenXml | null> {
/* istanbul ignore if */ /* istanbul ignore if */
if (!pkgUrl) { if (!pkgUrl) {
return null; return {};
} }
let rawContent: string; let rawContent: string;
let authorization: boolean;
switch (pkgUrl.protocol) { switch (pkgUrl.protocol) {
case 'file:': case 'file:':
rawContent = await downloadFileProtocol(pkgUrl); rawContent = await downloadFileProtocol(pkgUrl);
break; break;
case 'http:': case 'http:':
case 'https:': case 'https:':
rawContent = await downloadHttpProtocol(pkgUrl); ({ authorization, body: rawContent } = await downloadHttpProtocol(
pkgUrl
));
break; break;
case 's3:': case 's3:':
logger.debug('Skipping s3 dependency'); logger.debug('Skipping s3 dependency');
return null; return {};
default: default:
logger.debug({ url: pkgUrl.toString() }, `Unsupported Maven protocol`); logger.debug({ url: pkgUrl.toString() }, `Unsupported Maven protocol`);
return null; return {};
} }
if (!rawContent) { if (!rawContent) {
logger.debug(`Content is not found for Maven url: ${pkgUrl.toString()}`); logger.debug(`Content is not found for Maven url: ${pkgUrl.toString()}`);
return null; return {};
} }
return new XmlDocument(rawContent); return { authorization, xml: new XmlDocument(rawContent) };
} }
async function getDependencyInfo( async function getDependencyInfo(
@ -78,7 +86,7 @@ async function getDependencyInfo(
const path = `${version}/${dependency.name}-${version}.pom`; const path = `${version}/${dependency.name}-${version}.pom`;
const pomUrl = getMavenUrl(dependency, repoUrl, path); const pomUrl = getMavenUrl(dependency, repoUrl, path);
const pomContent = await downloadMavenXml(pomUrl); const { xml: pomContent } = await downloadMavenXml(pomUrl);
if (!pomContent) { if (!pomContent) {
return result; return result;
} }
@ -156,13 +164,17 @@ async function getVersionsFromMetadata(
return cachedVersions; return cachedVersions;
} }
const mavenMetadata = await downloadMavenXml(metadataUrl); const { authorization, xml: mavenMetadata } = await downloadMavenXml(
metadataUrl
);
if (!mavenMetadata) { if (!mavenMetadata) {
return null; return null;
} }
const versions = extractVersions(mavenMetadata); const versions = extractVersions(mavenMetadata);
await packageCache.set(cacheNamespace, cacheKey, versions, 30); if (!authorization) {
await packageCache.set(cacheNamespace, cacheKey, versions, 30);
}
return versions; return versions;
} }

View file

@ -2,7 +2,7 @@ import url from 'url';
import { HOST_DISABLED } from '../../constants/error-messages'; import { HOST_DISABLED } from '../../constants/error-messages';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { ExternalHostError } from '../../types/errors/external-host-error'; import { ExternalHostError } from '../../types/errors/external-host-error';
import { Http } from '../../util/http'; import { Http, HttpResponse } from '../../util/http';
import { MAVEN_REPO, id } from './common'; import { MAVEN_REPO, id } from './common';
@ -57,12 +57,12 @@ function isUnsupportedHostError(err: { name: string }): boolean {
export async function downloadHttpProtocol( export async function downloadHttpProtocol(
pkgUrl: url.URL | string, pkgUrl: url.URL | string,
hostType = id hostType = id
): Promise<string | null> { ): Promise<Partial<HttpResponse>> {
let raw: { body: string }; let raw: HttpResponse;
try { try {
const httpClient = httpByHostType(hostType); const httpClient = httpByHostType(hostType);
raw = await httpClient.get(pkgUrl.toString()); raw = await httpClient.get(pkgUrl.toString());
return raw.body; return raw;
} catch (err) { } catch (err) {
const failedUrl = pkgUrl.toString(); const failedUrl = pkgUrl.toString();
if (err.message === HOST_DISABLED) { if (err.message === HOST_DISABLED) {
@ -92,7 +92,7 @@ export async function downloadHttpProtocol(
} else { } else {
logger.info({ failedUrl, err }, 'Unknown error'); logger.info({ failedUrl, err }, 'Unknown error');
} }
return null; return {};
} }
} }

View file

@ -19,7 +19,7 @@ export async function getArtifactSubdirs(
artifact: string, artifact: string,
scalaVersion: string scalaVersion: string
): Promise<string[]> { ): Promise<string[]> {
const indexContent = await downloadHttpProtocol( const { body: indexContent } = await downloadHttpProtocol(
ensureTrailingSlash(searchRoot), ensureTrailingSlash(searchRoot),
'sbt' 'sbt'
); );
@ -59,7 +59,7 @@ export async function getPackageReleases(
const parseReleases = (content: string): string[] => const parseReleases = (content: string): string[] =>
parseIndexDir(content, (x) => !/^\.+$/.test(x)); parseIndexDir(content, (x) => !/^\.+$/.test(x));
for (const searchSubdir of artifactSubdirs) { for (const searchSubdir of artifactSubdirs) {
const content = await downloadHttpProtocol( const { body: content } = await downloadHttpProtocol(
ensureTrailingSlash(`${searchRoot}/${searchSubdir}`), ensureTrailingSlash(`${searchRoot}/${searchSubdir}`),
'sbt' 'sbt'
); );
@ -109,7 +109,7 @@ export async function getUrls(
for (const pomFileName of pomFileNames) { for (const pomFileName of pomFileNames) {
const pomUrl = `${searchRoot}/${artifactDir}/${version}/${pomFileName}`; const pomUrl = `${searchRoot}/${artifactDir}/${version}/${pomFileName}`;
const content = await downloadHttpProtocol(pomUrl, 'sbt'); const { body: content } = await downloadHttpProtocol(pomUrl, 'sbt');
if (content) { if (content) {
const pomXml = new XmlDocument(content); const pomXml = new XmlDocument(content);

View file

@ -26,7 +26,7 @@ async function resolvePluginReleases(
const searchRoot = `${rootUrl}/${artifact}`; const searchRoot = `${rootUrl}/${artifact}`;
const parse = (content: string): string[] => const parse = (content: string): string[] =>
parseIndexDir(content, (x) => !/^\.+$/.test(x)); parseIndexDir(content, (x) => !/^\.+$/.test(x));
const indexContent = await downloadHttpProtocol( const { body: indexContent } = await downloadHttpProtocol(
ensureTrailingSlash(searchRoot), ensureTrailingSlash(searchRoot),
'sbt' 'sbt'
); );
@ -41,7 +41,7 @@ async function resolvePluginReleases(
: scalaVersions; : scalaVersions;
for (const searchVersion of searchVersions) { for (const searchVersion of searchVersions) {
const searchSubRoot = `${searchRoot}/scala_${searchVersion}`; const searchSubRoot = `${searchRoot}/scala_${searchVersion}`;
const subRootContent = await downloadHttpProtocol( const { body: subRootContent } = await downloadHttpProtocol(
ensureTrailingSlash(searchSubRoot), ensureTrailingSlash(searchSubRoot),
'sbt' 'sbt'
); );
@ -49,7 +49,7 @@ async function resolvePluginReleases(
const sbtVersionItems = parse(subRootContent); const sbtVersionItems = parse(subRootContent);
for (const sbtItem of sbtVersionItems) { for (const sbtItem of sbtVersionItems) {
const releasesRoot = `${searchSubRoot}/${sbtItem}`; const releasesRoot = `${searchSubRoot}/${sbtItem}`;
const releasesIndexContent = await downloadHttpProtocol( const { body: releasesIndexContent } = await downloadHttpProtocol(
ensureTrailingSlash(releasesRoot), ensureTrailingSlash(releasesRoot),
'sbt' 'sbt'
); );