diff --git a/lib/modules/datasource/conan/index.spec.ts b/lib/modules/datasource/conan/index.spec.ts index 9128a16d6651db..e9025f4386118d 100644 --- a/lib/modules/datasource/conan/index.spec.ts +++ b/lib/modules/datasource/conan/index.spec.ts @@ -383,5 +383,94 @@ describe('modules/datasource/conan/index', () => { }) ).toBeNull(); }); + + it('artifactory no package url', async () => { + httpMock + .scope('https://fake.artifactory.com/artifactory/api/conan/test-repo/') + .get('/v2/conans/search?q=arti') + .reply( + 200, + { results: ['arti/1.0.0@_/_', 'arti/1.1.1@_/_'] }, + { + 'x-jfrog-version': 'latest', + } + ); + httpMock + .scope('https://fake.artifactory.com/artifactory/api/conan/test-repo/') + .get('/v2/conans/arti/1.1.1/_/_/latest') + .reply(200, { + revision: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + time: '2032-06-23T00:00:00.000+0000', + }); + httpMock + .scope( + 'https://fake.artifactory.com/artifactory/api/storage/test-repo/' + ) + .get( + '/_/arti/1.1.1/_/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/export/conanfile.py?properties=conan.package.url' + ) + .reply(200); + + config.registryUrls = [ + 'https://fake.artifactory.com/artifactory/api/conan/test-repo', + ]; + config.packageName = 'arti'; + expect( + await getPkgReleases({ + ...config, + packageName: 'arti/1.1@_/_', + }) + ).toEqual({ + registryUrl: + 'https://fake.artifactory.com/artifactory/api/conan/test-repo', + releases: [ + { + version: '1.0.0', + }, + { + version: '1.1.1', + }, + ], + }); + }); + + it('artifactory http error', async () => { + httpMock + .scope('https://fake.artifactory.com/artifactory/api/conan/test-repo/') + .get('/v2/conans/search?q=arti') + .reply( + 200, + { results: ['arti/1.0.0@_/_', 'arti/1.1.1@_/_'] }, + { + 'x-jfrog-version': 'latest', + } + ); + httpMock + .scope('https://fake.artifactory.com/artifactory/api/conan/test-repo/') + .get('/v2/conans/arti/1.1.1/_/_/latest') + .reply(404); + + config.registryUrls = [ + 'https://fake.artifactory.com/artifactory/api/conan/test-repo', + ]; + config.packageName = 'arti'; + expect( + await getPkgReleases({ + ...config, + packageName: 'arti/1.1@_/_', + }) + ).toEqual({ + registryUrl: + 'https://fake.artifactory.com/artifactory/api/conan/test-repo', + releases: [ + { + version: '1.0.0', + }, + { + version: '1.1.1', + }, + ], + }); + }); }); }); diff --git a/lib/modules/datasource/conan/index.ts b/lib/modules/datasource/conan/index.ts index 8fa550a0aeeea4..9e4f3b05db83b6 100644 --- a/lib/modules/datasource/conan/index.ts +++ b/lib/modules/datasource/conan/index.ts @@ -153,48 +153,58 @@ export class ConanDatasource extends Datasource { } } - if (isArtifactoryServer(rep)) { - const conanApiRegexp = - /(?.*)\/artifactory\/api\/conan\/(?[^/]+)/; - const groups = url.match(conanApiRegexp)?.groups; - if (!groups) { - return dep; - } - const semver = allVersioning.get('semver'); + try { + if (isArtifactoryServer(rep)) { + const conanApiRegexp = + /(?.*)\/artifactory\/api\/conan\/(?[^/]+)/; + const groups = url.match(conanApiRegexp)?.groups; + if (!groups) { + return dep; + } + const semver = allVersioning.get('semver'); - const sortedReleases = dep.releases - .filter((release) => semver.isVersion(release.version)) - .sort((a, b) => semver.sortVersions(a.version, b.version)); + const sortedReleases = dep.releases + .filter((release) => semver.isVersion(release.version)) + .sort((a, b) => semver.sortVersions(a.version, b.version)); - const latestVersion = sortedReleases.at(-1)?.version; + const latestVersion = sortedReleases.at(-1)?.version; - if (!latestVersion) { - return dep; + if (!latestVersion) { + return dep; + } + logger.debug( + `Conan package ${packageName} has latest version ${latestVersion}` + ); + + const latestRevisionUrl = joinUrlParts( + url, + `v2/conans/${conanPackage.conanName}/${latestVersion}/${conanPackage.userAndChannel}/latest` + ); + const revResp = await this.http.getJson( + latestRevisionUrl + ); + const packageRev = revResp.body.revision; + + const [user, channel] = conanPackage.userAndChannel.split('/'); + const packageUrl = joinUrlParts( + `${groups.host}/artifactory/api/storage/${groups.repo}`, + `${user}/${conanPackage.conanName}/${latestVersion}/${channel}/${packageRev}/export/conanfile.py?properties=conan.package.url` + ); + const packageUrlResp = await this.http.getJson( + packageUrl + ); + + if ( + packageUrlResp.body.properties && + 'conan.package.url' in packageUrlResp.body.properties + ) { + const conanPackageUrl = + packageUrlResp.body.properties['conan.package.url'][0]; + dep.sourceUrl = conanPackageUrl; + } } - logger.debug( - `Conan package ${packageName} has latest version ${latestVersion}` - ); - - const latestRevisionUrl = joinUrlParts( - url, - `v2/conans/${conanPackage.conanName}/${latestVersion}/${conanPackage.userAndChannel}/latest` - ); - const revResp = await this.http.getJson( - latestRevisionUrl - ); - const packageRev = revResp.body.revision; - - const [user, channel] = conanPackage.userAndChannel.split('/'); - const packageUrl = joinUrlParts( - `${groups.host}/artifactory/api/storage/${groups.repo}`, - `${user}/${conanPackage.conanName}/${latestVersion}/${channel}/${packageRev}/export/conanfile.py?properties=conan.package.url` - ); - const packageUrlResp = await this.http.getJson( - packageUrl - ); - const conanPackageUrl = - packageUrlResp.body.properties['conan.package.url'][0]; - dep.sourceUrl = conanPackageUrl; + } catch (err) { + logger.debug({ err }, "Couldn't determine Conan package url"); } return dep; }