From bb01c9e9e99e15a78700ffaa4232886ca57acbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Mar 2025 15:22:35 +0100 Subject: [PATCH] Add latest deployment tests --- .../Functions/Http/Deployments/Delete.php | 16 ++++++ .../Modules/Sites/Http/Deployments/Delete.php | 16 ++++++ .../Utopia/Response/Model/Deployment.php | 2 +- src/Appwrite/Utopia/Response/Model/Func.php | 18 +++++++ src/Appwrite/Utopia/Response/Model/Site.php | 18 +++++++ .../e2e/Services/Functions/FunctionsBase.php | 10 ++++ .../Functions/FunctionsCustomServerTest.php | 32 ++++++++++++ tests/e2e/Services/Sites/SitesBase.php | 10 ++++ .../Services/Sites/SitesCustomServerTest.php | 49 +++++++++++++++---- 9 files changed, 161 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index 27eded178a..b5a84c9122 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Query; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -96,6 +97,21 @@ class Delete extends Action } } + if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) { + $latestDeployment = $dbForProject->findOne('deployments', [ + Query::orderDesc('$createdAt'), + ]); + $function = $dbForProject->updateDocument( + 'functions', + $function->getId(), + $function + ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) + ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) + ); + } + if ($function->getAttribute('deploymentId') === $deployment->getId()) { // Reset function deployment $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ 'deploymentId' => '', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index 00342a7667..b6b347bc04 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Query; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -96,6 +97,21 @@ class Delete extends Action } } + if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) { + $latestDeployment = $dbForProject->findOne('deployments', [ + Query::orderDesc('$createdAt'), + ]); + $site = $dbForProject->updateDocument( + 'sites', + $site->getId(), + $site + ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) + ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) + ); + } + if ($site->getAttribute('deploymentId') === $deployment->getId()) { // Reset site deployment $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ 'deploymentId' => '', diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index 4729e8a122..55c1589af0 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -96,7 +96,7 @@ class Deployment extends Model ]) ->addRule('status', [ 'type' => self::TYPE_STRING, - 'description' => 'The deployment status. Possible values are "waiting", "processing", "building", "waiting", "ready", and "failed".', + 'description' => 'The deployment status. Possible values are "waiting", "processing", "building", "ready", and "failed".', 'default' => '', 'example' => 'ready', ]) diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index 5d937ab075..d2446585b9 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -77,6 +77,24 @@ class Func extends Model 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) + ->addRule('latestDeploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site\'s latest deployment ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('latestDeploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Latest deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('latestDeploymentStatus', [ + 'type' => self::TYPE_STRING, + 'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".', + 'default' => '', + 'example' => 'ready', + ]) ->addRule('scopes', [ 'type' => self::TYPE_STRING, 'description' => 'Allowed permission scopes.', diff --git a/src/Appwrite/Utopia/Response/Model/Site.php b/src/Appwrite/Utopia/Response/Model/Site.php index fad4856f3e..478b7881b3 100644 --- a/src/Appwrite/Utopia/Response/Model/Site.php +++ b/src/Appwrite/Utopia/Response/Model/Site.php @@ -76,6 +76,24 @@ class Site extends Model 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('latestDeploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site\'s latest deployment ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('latestDeploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Latest deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('latestDeploymentStatus', [ + 'type' => self::TYPE_STRING, + 'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".', + 'default' => '', + 'example' => 'ready', + ]) ->addRule('vars', [ 'type' => Response::MODEL_VARIABLE, 'description' => 'Site variables.', diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index 2d82de22f2..475eb9b9b4 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -231,6 +231,16 @@ trait FunctionsBase return $deployment; } + protected function deleteDeployment(string $functionId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $deployment; + } + protected function createTemplateDeployment(string $functionId, mixed $params = []): mixed { $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments/template', array_merge([ diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index e13e7f9147..933d5d5a12 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -2101,12 +2101,27 @@ class FunctionsCustomServerTest extends Scope ]); $this->assertNotEmpty($functionId); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertArrayHasKey('latestDeploymentId', $function['body']); + $this->assertArrayHasKey('latestDeploymentCreatedAt', $function['body']); + $this->assertArrayHasKey('latestDeploymentStatus', $function['body']); + $this->assertEmpty($function['body']['latestDeploymentId']); + $this->assertEmpty($function['body']['latestDeploymentCreatedAt']); + $this->assertEmpty($function['body']['latestDeploymentStatus']); + $deploymentId1 = $this->setupDeployment($functionId, [ 'code' => $this->packageFunction('php-cookie'), 'activate' => true ]); $this->assertNotEmpty($deploymentId1); + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + $execution = $this->createExecution($functionId, [ 'headers' => [ 'cookie' => 'cookieName=cookieValue' ] ]); @@ -2120,6 +2135,11 @@ class FunctionsCustomServerTest extends Scope ]); $this->assertNotEmpty($deploymentId2); + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + $execution = $this->createExecution($functionId); $this->assertEquals(201, $execution['headers']['status-code']); $this->assertNotEmpty($execution['body']['$id']); @@ -2128,6 +2148,8 @@ class FunctionsCustomServerTest extends Scope $function = $this->getFunction($functionId); $this->assertEquals(200, $function['headers']['status-code']); $this->assertEquals($deploymentId2, $function['body']['deploymentId']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); $function = $this->updateFunctionDeployment($functionId, $deploymentId1); $this->assertEquals(200, $function['headers']['status-code']); @@ -2136,6 +2158,8 @@ class FunctionsCustomServerTest extends Scope $function = $this->getFunction($functionId); $this->assertEquals(200, $function['headers']['status-code']); $this->assertEquals($deploymentId1, $function['body']['deploymentId']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); $execution = $this->createExecution($functionId, [ 'headers' => [ 'cookie' => 'cookieName=cookieValue' ] @@ -2144,6 +2168,14 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($execution['body']['$id']); $this->assertStringContainsString('cookieValue', $execution['body']['responseBody']); + $deployment = $this->deleteDeployment($functionId, $deploymentId2); + $this->assertEquals(204, $deployment['headers']['status-code']); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + $this->cleanupFunction($functionId); } } diff --git a/tests/e2e/Services/Sites/SitesBase.php b/tests/e2e/Services/Sites/SitesBase.php index abfce68d89..ff7e4b283f 100644 --- a/tests/e2e/Services/Sites/SitesBase.php +++ b/tests/e2e/Services/Sites/SitesBase.php @@ -244,6 +244,16 @@ trait SitesBase return $deployment; } + protected function deleteDeployment(string $siteId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $deployment; + } + protected function setupDuplicateDeployment(string $siteId, string $deploymentId): string { $deployment = $this->createDuplicateDeployment($siteId, $deploymentId); diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index c1609bfb80..a95568c7ce 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -2057,6 +2057,15 @@ class SitesCustomServerTest extends Scope ]); $this->assertNotEmpty($siteId); + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertArrayHasKey('latestDeploymentId', $site['body']); + $this->assertArrayHasKey('latestDeploymentCreatedAt', $site['body']); + $this->assertArrayHasKey('latestDeploymentStatus', $site['body']); + $this->assertEmpty($site['body']['latestDeploymentId']); + $this->assertEmpty($site['body']['latestDeploymentCreatedAt']); + $this->assertEmpty($site['body']['latestDeploymentStatus']); + $domain = $this->setupSiteDomain($siteId); $this->assertNotEmpty($domain); $proxyClient = new Client(); @@ -2068,6 +2077,11 @@ class SitesCustomServerTest extends Scope ]); $this->assertNotEmpty($deploymentId1); + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + $response = $proxyClient->call(Client::METHOD_GET, '/'); $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString('Hello Appwrite', $response['body']); @@ -2078,26 +2092,43 @@ class SitesCustomServerTest extends Scope ]); $this->assertNotEmpty($deploymentId2); + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + $response = $proxyClient->call(Client::METHOD_GET, '/'); $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString('Index page', $response['body']); - $function = $this->getSite($siteId); - $this->assertEquals(200, $function['headers']['status-code']); - $this->assertEquals($deploymentId2, $function['body']['deploymentId']); + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId2, $site['body']['deploymentId']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); - $function = $this->updateSiteDeployment($siteId, $deploymentId1); - $this->assertEquals(200, $function['headers']['status-code']); - $this->assertEquals($deploymentId1, $function['body']['deploymentId']); + $site = $this->updateSiteDeployment($siteId, $deploymentId1); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['deploymentId']); - $function = $this->getSite($siteId); - $this->assertEquals(200, $function['headers']['status-code']); - $this->assertEquals($deploymentId1, $function['body']['deploymentId']); + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['deploymentId']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); $response = $proxyClient->call(Client::METHOD_GET, '/'); $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString('Hello Appwrite', $response['body']); + $deployment = $this->deleteDeployment($siteId, $deploymentId2); + $this->assertEquals(204, $deployment['headers']['status-code']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + $this->cleanupSite($siteId); }