From 63f6840d1be86a8e7d3a5fc953deba51dcdf136a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Nov 2025 17:39:19 +0100 Subject: [PATCH] Finish implementation, update tests --- app/controllers/general.php | 8 +++ .../Modules/Sites/Http/Sites/Create.php | 1 - src/Appwrite/Utopia/Request/Filters/V21.php | 19 ++++++- src/Appwrite/Utopia/Response/Filters/V21.php | 51 +++++++++++++++++++ src/Appwrite/Utopia/Response/Model/Site.php | 1 - .../Services/Sites/SitesCustomServerTest.php | 24 +++++---- .../resources/sites/astro/src/pages/specs.js | 13 +++++ 7 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 src/Appwrite/Utopia/Response/Filters/V21.php create mode 100644 tests/resources/sites/astro/src/pages/specs.js diff --git a/app/controllers/general.php b/app/controllers/general.php index 84dde40683..709229241e 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -29,6 +29,8 @@ use Appwrite\Utopia\Response\Filters\V16 as ResponseV16; use Appwrite\Utopia\Response\Filters\V17 as ResponseV17; use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\Response\Filters\V19 as ResponseV19; +use Appwrite\Utopia\Response\Filters\V20 as ResponseV20; +use Appwrite\Utopia\Response\Filters\V21 as ResponseV21; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; @@ -1048,6 +1050,12 @@ App::init() if (version_compare($responseFormat, '1.7.0', '<')) { $response->addFilter(new ResponseV19()); } + if (version_compare($responseFormat, '1.8.0', '<')) { + $response->addFilter(new ResponseV20()); + } + if (version_compare($responseFormat, '1.9.0', '<')) { + $response->addFilter(new ResponseV21()); + } if (version_compare($responseFormat, APP_VERSION_STABLE, '>')) { $warnings[] = "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is " . APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"; } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php index 0fec56efee..fd27bc1b59 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -90,7 +90,6 @@ class Create extends Base System::getEnv('_APP_COMPUTE_CPUS', 0), System::getEnv('_APP_COMPUTE_MEMORY', 0) ), 'Runtime specification for the function SSR executions.', true, ['plan']) - // TODO: Request filter ->inject('response') ->inject('dbForProject') ->inject('project') diff --git a/src/Appwrite/Utopia/Request/Filters/V21.php b/src/Appwrite/Utopia/Request/Filters/V21.php index 3ef0becf1d..4feb8e1926 100644 --- a/src/Appwrite/Utopia/Request/Filters/V21.php +++ b/src/Appwrite/Utopia/Request/Filters/V21.php @@ -6,7 +6,7 @@ use Appwrite\Utopia\Request\Filter; class V21 extends Filter { - // Convert 1.8.0 params to 1.8.1 + // Convert 1.8.0 params to 1.9.0 public function parse(array $content, string $model): array { switch ($model) { @@ -14,6 +14,12 @@ class V21 extends Filter case 'sites.createTemplateDeployment': $content = $this->convertVersionToTypeAndReference($content); break; + case 'functions.create': + case 'sites.create': + case 'functions.update': + case 'sites.update': + $content = $this->convertSpecs($content); + break; } return $content; } @@ -31,4 +37,15 @@ class V21 extends Filter } return $content; } + + protected function convertSpecs(array $content): array + { + if (!empty($content['specification'])) { + $content['buildSpecification'] = $content['specification']; + $content['runtimeSpecification'] = $content['specification']; + unset($content['specification']); + } + + return $content; + } } diff --git a/src/Appwrite/Utopia/Response/Filters/V21.php b/src/Appwrite/Utopia/Response/Filters/V21.php new file mode 100644 index 0000000000..bba1aaa4ca --- /dev/null +++ b/src/Appwrite/Utopia/Response/Filters/V21.php @@ -0,0 +1,51 @@ + $this->parseSite($content), + Response::MODEL_SITE_LIST => $this->handleList( + $content, + "sites", + fn ($item) => $this->parseSite($item), + ), + Response::MODEL_FUNCTION => $this->parseFunction($content), + Response::MODEL_FUNCTION_LIST => $this->handleList( + $content, + "sites", + fn ($item) => $this->parseFunction($item), + ), + default => $parsedResponse, + }; + } + + protected function parseSite(array $content): array + { + $content = $this->parseSpecs($content); + return $content; + } + + protected function parseFunction(array $content): array + { + $content = $this->parseSpecs($content); + return $content; + } + + protected function parseSpecs(array $content): array + { + $content['specification'] = $content['buildSpecification'] ?? null; + unset($content['buildSpecification']); + unset($content['runtimeSpecification']); + return $content; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Site.php b/src/Appwrite/Utopia/Response/Model/Site.php index 8e46cd9043..f9a1298f6e 100644 --- a/src/Appwrite/Utopia/Response/Model/Site.php +++ b/src/Appwrite/Utopia/Response/Model/Site.php @@ -173,7 +173,6 @@ class Site extends Model 'default' => APP_COMPUTE_SPECIFICATION_DEFAULT, 'example' => APP_COMPUTE_SPECIFICATION_DEFAULT, ]) - // TODO: Response filter ->addRule('buildRuntime', [ 'type' => self::TYPE_STRING, 'description' => 'Site build runtime.', diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index a2ffed5e1a..f951a1205b 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -2977,12 +2977,11 @@ class SitesCustomServerTest extends Scope 'adapter' => 'ssr', 'buildRuntime' => 'node-22', 'outputDirectory' => './dist', - 'buildCommand' => 'npm run build', + 'buildCommand' => 'npm run build && echo $APPWRITE_SITE_MEMORY:$APPWRITE_SITE_CPUS', 'installCommand' => 'npm install', 'fallbackFile' => '', 'buildSpecification' => Specification::S_2VCPU_2GB, 'runtimeSpecification' => Specification::S_1VCPU_1GB, - 'commands' => 'echo $APPWRITE_FUNCTION_MEMORY:$APPWRITE_FUNCTION_CPUS', ]); $this->assertEquals(201, $site['headers']['status-code']); @@ -2992,6 +2991,8 @@ class SitesCustomServerTest extends Scope $siteId = $site['body']['$id'] ?? ''; + $domain = $this->setupSiteDomain($siteId); + $deploymentId = $this->setupDeployment($siteId, [ 'code' => $this->packageSite('astro'), 'activate' => true @@ -2999,19 +3000,20 @@ class SitesCustomServerTest extends Scope $this->assertEventually(function () use ($siteId, $deploymentId) { $deployment = $this->getDeployment($siteId, $deploymentId); - $this->assertTrue(str_contains($deployment['body']['buildLogs'], '2048:2')); + \var_dump($deployment['body']['buildLogs']); + $this->assertStringContainsString('2048:2', $deployment['body']['buildLogs']); }, 10000, 500); - // Check if the function specifications are correctly set in executions - // TODO: Finish - $execution = $this->createExecution($functionId); + // Check if the sites specifications are correctly set in executions + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); - $this->assertEquals(201, $execution['headers']['status-code']); - $this->assertNotEmpty($execution['body']['$id']); + $response = $proxyClient->call(Client::METHOD_GET, '/specs'); - $executionResponse = json_decode($execution['body']['responseBody'], true); - $this->assertEquals('1024', $executionResponse['APPWRITE_FUNCTION_MEMORY']); - $this->assertEquals('1', $executionResponse['APPWRITE_FUNCTION_CPUS']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertEquals('1024', $response['body']['APPWRITE_SITE_MEMORY']); + $this->assertEquals('1', $response['body']['APPWRITE_SITE_CPUS']); $this->cleanupSite($siteId); } diff --git a/tests/resources/sites/astro/src/pages/specs.js b/tests/resources/sites/astro/src/pages/specs.js new file mode 100644 index 0000000000..adc2d6768f --- /dev/null +++ b/tests/resources/sites/astro/src/pages/specs.js @@ -0,0 +1,13 @@ +export async function GET(_context) { + return new Response( + JSON.stringify({ + APPWRITE_SITE_MEMORY: process.env.APPWRITE_SITE_MEMORY, + APPWRITE_SITE_CPUS: process.env.APPWRITE_SITE_CPUS, + }), + { + headers: { + "Content-Type": "application/json", + }, + }, + ); +}