From bca81756843d1eb8f419bdb4ddfdfcf71667afc4 Mon Sep 17 00:00:00 2001
From: MartijnLeijssen-TomTom
 <46988880+MartijnLeijssen-TomTom@users.noreply.github.com>
Date: Fri, 21 Jul 2023 21:07:06 +0200
Subject: [PATCH] fix(datasource/conan): continue on error during fetching
 package url (#23391)

---
 lib/modules/datasource/conan/index.spec.ts | 89 ++++++++++++++++++++++
 lib/modules/datasource/conan/index.ts      | 86 ++++++++++++---------
 2 files changed, 137 insertions(+), 38 deletions(-)

diff --git a/lib/modules/datasource/conan/index.spec.ts b/lib/modules/datasource/conan/index.spec.ts
index 9128a16d66..e9025f4386 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 8fa550a0ae..9e4f3b05db 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 =
-              /(?<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;
         }
-- 
GitLab