From d2f2f8d672136b980a73acac9937be7e33de19a0 Mon Sep 17 00:00:00 2001
From: Zack Pollard <zackpollard@ymail.com>
Date: Wed, 23 Apr 2025 17:10:43 +0100
Subject: [PATCH] fix: retrieve version from lockfile and fallback to cli
 command (#17812)

---
 .../repositories/server-info.repository.ts    | 48 ++++++++++++++-----
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/server/src/repositories/server-info.repository.ts b/server/src/repositories/server-info.repository.ts
index cc7e1770fc..4500094899 100644
--- a/server/src/repositories/server-info.repository.ts
+++ b/server/src/repositories/server-info.repository.ts
@@ -75,27 +75,49 @@ export class ServerInfoRepository {
 
   buildVersions?: ServerBuildVersions;
 
+  private async retrieveVersionFallback(
+    command: string,
+    commandTransform?: (output: string) => string,
+    version?: string,
+  ): Promise<string> {
+    if (!version) {
+      const output = await maybeFirstLine(command);
+      version = commandTransform ? commandTransform(output) : output;
+    }
+    return version;
+  }
+
   async getBuildVersions(): Promise<ServerBuildVersions> {
     if (!this.buildVersions) {
       const { nodeVersion, resourcePaths } = this.configRepository.getEnv();
 
-      const [nodejsOutput, ffmpegOutput, magickOutput] = await Promise.all([
-        maybeFirstLine('node --version'),
-        maybeFirstLine('ffmpeg -version'),
-        maybeFirstLine('convert --version'),
-      ]);
-
-      const lockfile = await readFile(resourcePaths.lockFile)
+      const lockfile: BuildLockfile | undefined = await readFile(resourcePaths.lockFile)
         .then((buffer) => JSON.parse(buffer.toString()))
         .catch(() => this.logger.warn(`Failed to read ${resourcePaths.lockFile}`));
 
+      const [nodejsVersion, ffmpegVersion, magickVersion, exiftoolVersion] = await Promise.all([
+        this.retrieveVersionFallback('node --version', undefined, nodeVersion),
+        this.retrieveVersionFallback(
+          'ffmpeg -version',
+          (output) => output.replaceAll('ffmpeg version ', ''),
+          getLockfileVersion('ffmpeg', lockfile),
+        ),
+        this.retrieveVersionFallback(
+          'magick --version',
+          (output) => output.replaceAll('Version: ImageMagick ', ''),
+          getLockfileVersion('imagemagick', lockfile),
+        ),
+        exiftool.version(),
+      ]);
+
+      const libvipsVersion = getLockfileVersion('libvips', lockfile) || sharp.versions.vips;
+
       this.buildVersions = {
-        nodejs: nodejsOutput || nodeVersion || '',
-        exiftool: await exiftool.version(),
-        ffmpeg: getLockfileVersion('ffmpeg', lockfile) || ffmpegOutput.replaceAll('ffmpeg version', '') || '',
-        libvips: getLockfileVersion('libvips', lockfile) || sharp.versions.vips,
-        imagemagick:
-          getLockfileVersion('imagemagick', lockfile) || magickOutput.replaceAll('Version: ImageMagick ', '') || '',
+        nodejs: nodejsVersion,
+        exiftool: exiftoolVersion,
+        ffmpeg: ffmpegVersion,
+        libvips: libvipsVersion,
+        imagemagick: magickVersion,
       };
     }