Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(datasource/conan): continue on error during fetching package url #23391

Merged
89 changes: 89 additions & 0 deletions lib/modules/datasource/conan/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,5 +383,94 @@ describe('modules/datasource/conan/index', () => {
})
).toBeNull();
});

viceice marked this conversation as resolved.
Show resolved Hide resolved
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',
},
],
});
});
});
});
86 changes: 48 additions & 38 deletions lib/modules/datasource/conan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,48 +153,58 @@ export class ConanDatasource extends Datasource {
}
}

if (isArtifactoryServer(rep)) {
const conanApiRegexp =
/(?<host>.*)\/artifactory\/api\/conan\/(?<repo>[^/]+)/;
const groups = url.match(conanApiRegexp)?.groups;
if (!groups) {
return dep;
}
const semver = allVersioning.get('semver');
try {
if (isArtifactoryServer(rep)) {
const conanApiRegexp =
/(?<host>.*)\/artifactory\/api\/conan\/(?<repo>[^/]+)/;
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<ConanRevisionJSON>(
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<ConanProperties>(
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<ConanRevisionJSON>(
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<ConanProperties>(
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;
}
Expand Down