From c4fe9690c2b97aa4e4243460686df5afc76b840b Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Fri, 23 Oct 2026 12:58:56 +0000 Subject: [PATCH 1/3] fix(harp): require HaRP 0.4.8 in the version check Signed-off-by: Oleksandr Piskun --- lib/AppInfo/Application.php | 2 +- lib/SetupChecks/HarpVersionCheck.php | 7 ++- .../php/SetupChecks/HarpVersionCheckTest.php | 55 +++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 tests/php/SetupChecks/HarpVersionCheckTest.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 670bed03e..3e4c5fe2a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -44,7 +44,7 @@ class Application extends App implements IBootstrap { public const APP_ID = 'app_api'; public const TEST_DEPLOY_APPID = 'test-deploy'; public const TEST_DEPLOY_INFO_XML = 'https://raw.githubusercontent.com/nextcloud/test-deploy/main/appinfo/info.xml'; - public const MINIMUM_HARP_VERSION = '0.3.0'; + public const MINIMUM_HARP_VERSION = '0.4.8'; public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); diff --git a/lib/SetupChecks/HarpVersionCheck.php b/lib/SetupChecks/HarpVersionCheck.php index 424c3576a..9ff1dd551 100644 --- a/lib/SetupChecks/HarpVersionCheck.php +++ b/lib/SetupChecks/HarpVersionCheck.php @@ -91,12 +91,13 @@ private function fulfillsMinimumVersionRequirement(string $version): bool { } private function getHarpVersion(DaemonConfig $daemonConfig): ?string { - $cacheKey = $daemonConfig->getName() . '_' . (string)crc32(json_encode($daemonConfig)); + // With the minimum in the key, a version cached against an older minimum is asked again. + $cacheKey = $daemonConfig->getName() . '_' . (string)crc32(json_encode($daemonConfig)) . '_' . Application::MINIMUM_HARP_VERSION; $version = $this->cache?->get($cacheKey); if ($version === null) { $version = $this->harpService->getHarpVersion($daemonConfig); - $oneWeek = 60 * 60 * 24 * 7; - $this->cache?->set($cacheKey, $version, $oneWeek); + $ttl = $version !== null && $this->fulfillsMinimumVersionRequirement($version) ? 60 * 60 * 24 * 7 : 60 * 60; + $this->cache?->set($cacheKey, $version, $ttl); } return $version; } diff --git a/tests/php/SetupChecks/HarpVersionCheckTest.php b/tests/php/SetupChecks/HarpVersionCheckTest.php new file mode 100644 index 000000000..b42559715 --- /dev/null +++ b/tests/php/SetupChecks/HarpVersionCheckTest.php @@ -0,0 +1,55 @@ +createMock(IL10N::class); + $l10n->method('t')->willReturnCallback(fn (string $text, array $parameters = []) => vsprintf($text, $parameters)); + $daemonConfigService = $this->createMock(DaemonConfigService::class); + $daemonConfigService->method('getRegisteredDaemonConfigs')->willReturn([ + new DaemonConfig(['name' => 'harp_proxy', 'deploy_config' => ['harp' => ['exapp_direct' => false]]]), + ]); + $harpService = $this->createMock(HarpService::class); + $harpService->method('getHarpVersion')->willReturn($harpVersion); + $cache = $this->createMock(ICache::class); + $cache->method('get')->willReturn(null); + $cache->expects(self::once())->method('set')->with(self::anything(), $harpVersion, $expectedCacheTtl); + $cacheFactory = $this->createMock(ICacheFactory::class); + $cacheFactory->method('isAvailable')->willReturn(true); + $cacheFactory->method('createDistributed')->willReturn($cache); + + $check = new HarpVersionCheck($l10n, $this->createMock(LoggerInterface::class), $daemonConfigService, $harpService, $cacheFactory); + return $check->run(); + } + + public function testHarpWithoutRouteVerbChecksIsTooOld(): void { + $result = $this->runCheck('0.4.7', 60 * 60); + self::assertSame(SetupResult::WARNING, $result->getSeverity()); + self::assertStringContainsString('"0.4.7", which is too old. The minimum required version is "0.4.8"', $result->getDescription()); + } + + public function testCurrentHarpPasses(): void { + $result = $this->runCheck('0.4.8', 60 * 60 * 24 * 7); + self::assertSame(SetupResult::SUCCESS, $result->getSeverity()); + } +} From ed79952d401916e1ac1e7a01f0c188a66cb0320a Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Fri, 23 Oct 2026 14:06:16 +0000 Subject: [PATCH 2/3] test(harp): the version check reports an unreachable HaRP Signed-off-by: Oleksandr Piskun --- tests/php/SetupChecks/HarpVersionCheckTest.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/php/SetupChecks/HarpVersionCheckTest.php b/tests/php/SetupChecks/HarpVersionCheckTest.php index b42559715..29e4aeab7 100644 --- a/tests/php/SetupChecks/HarpVersionCheckTest.php +++ b/tests/php/SetupChecks/HarpVersionCheckTest.php @@ -22,7 +22,7 @@ class HarpVersionCheckTest extends TestCase { - private function runCheck(string $harpVersion, int $expectedCacheTtl): SetupResult { + private function runCheck(?string $harpVersion, int $expectedCacheTtl): SetupResult { $l10n = $this->createMock(IL10N::class); $l10n->method('t')->willReturnCallback(fn (string $text, array $parameters = []) => vsprintf($text, $parameters)); $daemonConfigService = $this->createMock(DaemonConfigService::class); @@ -48,6 +48,12 @@ public function testHarpWithoutRouteVerbChecksIsTooOld(): void { self::assertStringContainsString('"0.4.7", which is too old. The minimum required version is "0.4.8"', $result->getDescription()); } + public function testUnreachableHarpIsReported(): void { + $result = $this->runCheck(null, 60 * 60); + self::assertSame(SetupResult::WARNING, $result->getSeverity()); + self::assertStringContainsString('Could not retrieve HaRP version from daemon "harp_proxy"', $result->getDescription()); + } + public function testCurrentHarpPasses(): void { $result = $this->runCheck('0.4.8', 60 * 60 * 24 * 7); self::assertSame(SetupResult::SUCCESS, $result->getSeverity()); From 65427209c1edb169c54aa7edbe34ab372b2f6b71 Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Fri, 23 Oct 2026 14:24:03 +0000 Subject: [PATCH 3/3] test(harp): the version check keys its cache by the minimum version Signed-off-by: Oleksandr Piskun --- tests/php/SetupChecks/HarpVersionCheckTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/php/SetupChecks/HarpVersionCheckTest.php b/tests/php/SetupChecks/HarpVersionCheckTest.php index 29e4aeab7..b8f20a53f 100644 --- a/tests/php/SetupChecks/HarpVersionCheckTest.php +++ b/tests/php/SetupChecks/HarpVersionCheckTest.php @@ -9,6 +9,7 @@ namespace OCA\AppAPI\Tests\php\SetupChecks; +use OCA\AppAPI\AppInfo\Application; use OCA\AppAPI\Db\DaemonConfig; use OCA\AppAPI\Service\DaemonConfigService; use OCA\AppAPI\Service\HarpService; @@ -33,7 +34,8 @@ private function runCheck(?string $harpVersion, int $expectedCacheTtl): SetupRes $harpService->method('getHarpVersion')->willReturn($harpVersion); $cache = $this->createMock(ICache::class); $cache->method('get')->willReturn(null); - $cache->expects(self::once())->method('set')->with(self::anything(), $harpVersion, $expectedCacheTtl); + // The minimum is part of the key, so a version cached by an older AppAPI is not reused after an upgrade. + $cache->expects(self::once())->method('set')->with(self::stringEndsWith('_' . Application::MINIMUM_HARP_VERSION), $harpVersion, $expectedCacheTtl); $cacheFactory = $this->createMock(ICacheFactory::class); $cacheFactory->method('isAvailable')->willReturn(true); $cacheFactory->method('createDistributed')->willReturn($cache);