From ffb86ace3812c94e1be40d7c1b574f891e521a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 18 Mar 2025 15:29:21 +0100 Subject: [PATCH 1/7] Add latest info detail to site & function --- app/config/collections/projects.php | 101 ++++++++++++++++-- app/controllers/api/vcs.php | 7 ++ .../Platform/Modules/Compute/Base.php | 14 +++ .../Functions/Http/Deployments/Create.php | 14 +++ .../Http/Deployments/Duplicate/Create.php | 7 ++ .../Http/Deployments/Status/Update.php | 5 + .../Http/Deployments/Template/Create.php | 7 ++ .../Modules/Functions/Workers/Builds.php | 20 ++++ .../Modules/Sites/Http/Deployments/Create.php | 14 +++ .../Http/Deployments/Duplicate/Create.php | 7 ++ .../Sites/Http/Deployments/Status/Update.php | 5 + .../Http/Deployments/Template/Create.php | 7 ++ 12 files changed, 197 insertions(+), 11 deletions(-) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index f9a44e169c..c9ab10ddcf 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -590,6 +590,51 @@ return [ 'array' => false, 'filters' => ['datetime'], ], + [ + '$id' => ID::custom('latestDeploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + + [ + '$id' => ID::custom('latestDeploymentStatus'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('vars'), 'type' => Database::VAR_STRING, @@ -1003,17 +1048,6 @@ return [ 'array' => false, 'filters' => [], ], - [ - '$id' => ID::custom('deploymentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => ID::custom('deploymentCreatedAt'), 'type' => Database::VAR_DATETIME, @@ -1047,6 +1081,51 @@ return [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('latestDeploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + + [ + '$id' => ID::custom('latestDeploymentStatus'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('vars'), 'type' => Database::VAR_STRING, diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 89a0e251d4..107be3d888 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -253,6 +253,13 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId 'activate' => $activate, ])); + $resource = $resource + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 1e70c106a7..6d44be239d 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -94,6 +94,13 @@ class Base extends Action 'activate' => $activate, ])); + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) @@ -185,6 +192,13 @@ class Base extends Action 'activate' => $activate, ])); + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index 1f49568249..00c4f402a1 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -240,6 +240,13 @@ class Create extends Action 'sourceMetadata' => $metadata, 'type' => $type ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); } else { $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata)); } @@ -273,6 +280,13 @@ class Create extends Action 'sourceMetadata' => $metadata, 'type' => $type ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); } else { $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata)); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php index aa1142570b..eb672dacf9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -113,6 +113,13 @@ class Create extends Action 'buildLogs' => '', ])); + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php index 6d5cc145c9..053a10f982 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -95,6 +95,11 @@ class Update extends Action 'status' => 'canceled' ])); + if ($deployment->getInternalId() === $function->getAttribute('latestDeploymentInternalId', '')) { + $function = $function->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + } + try { $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); $executor->deleteRuntime($project->getId(), $deploymentId . "-build"); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 9d48c1c112..98a975545d 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -150,6 +150,13 @@ class Create extends Base 'activate' => $activate, ])); + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 16b2e08be1..82dbd99292 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -211,6 +211,11 @@ class Builds extends Action $deployment->setAttribute('status', 'processing'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); @@ -452,6 +457,11 @@ class Builds extends Action $deployment->setAttribute('status', 'building'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); @@ -732,6 +742,11 @@ class Builds extends Action $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); @@ -1017,6 +1032,11 @@ class Builds extends Action $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index c52f958da5..ab2d9282ac 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -250,6 +250,13 @@ class Create extends Action 'type' => $type ])); + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; @@ -310,6 +317,13 @@ class Create extends Action 'type' => $type ])); + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 9982828ec2..9e33a6b839 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -126,6 +126,13 @@ class Create extends Action 'buildLogs' => '', ])); + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + // Preview deployments for sites $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php index 0361c1bc9c..1970fa898e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -93,6 +93,11 @@ class Update extends Action 'status' => 'canceled' ])); + if ($deployment->getInternalId() === $site->getAttribute('latestDeploymentInternalId', '')) { + $site = $site->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + } + try { $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); $executor->deleteRuntime($project->getId(), $deploymentId . "-build"); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 6e077f2713..c3a4b3ca96 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -161,6 +161,13 @@ class Create extends Base 'activate' => $activate, ])); + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; From e75441a0973ef66f0ca7b5e4c8abbed79b37423c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 18 Mar 2025 15:46:28 +0100 Subject: [PATCH 2/7] =?UTF-8?q?Didn't=20mean=20to=20remove=20that=20?= =?UTF-8?q?=F0=9F=8E=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/config/collections/projects.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index c9ab10ddcf..ffae763f6b 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -1048,6 +1048,17 @@ return [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('deploymentCreatedAt'), 'type' => Database::VAR_DATETIME, 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 3/7] 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); } From e34fc92c7c3ef53c1f8e6bbe9bf8d9adb73b82ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Mar 2025 15:44:15 +0100 Subject: [PATCH 4/7] PR review changes --- app/config/collections/projects.php | 2 -- .../Platform/Modules/Functions/Http/Deployments/Delete.php | 2 ++ src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index ffae763f6b..b209a7ec32 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -623,7 +623,6 @@ return [ 'array' => false, 'filters' => ['datetime'], ], - [ '$id' => ID::custom('latestDeploymentStatus'), 'type' => Database::VAR_STRING, @@ -1125,7 +1124,6 @@ return [ 'array' => false, 'filters' => ['datetime'], ], - [ '$id' => ID::custom('latestDeploymentStatus'), 'type' => Database::VAR_STRING, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index b5a84c9122..b66ea30bb2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -99,6 +99,8 @@ class Delete extends Action if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ + Query::equal('resourceType', ['functions']), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::orderDesc('$createdAt'), ]); $function = $dbForProject->updateDocument( diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index b6b347bc04..9d30b21a11 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -99,6 +99,8 @@ class Delete extends Action if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ + Query::equal('resourceType', ['sites']), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::orderDesc('$createdAt'), ]); $site = $dbForProject->updateDocument( From 0f5480cbc0e8fdf126fc41b55c3e1758a4f1638e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Mar 2025 15:48:18 +0100 Subject: [PATCH 5/7] Fix copy --- src/Appwrite/Utopia/Response/Model/Func.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index d2446585b9..e0929684fb 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -79,7 +79,7 @@ class Func extends Model ]) ->addRule('latestDeploymentId', [ 'type' => self::TYPE_STRING, - 'description' => 'Site\'s latest deployment ID.', + 'description' => 'Function\'s latest deployment ID.', 'default' => '', 'example' => '5e5ea5c16897e', ]) From 172ebb5f7f9bae392f82ef65eaf1a6a1bcdf548d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Mar 2025 15:51:15 +0100 Subject: [PATCH 6/7] Update specs --- .../specs/open-api3-latest-console.json | 73 ++++++++++++++++++- app/config/specs/open-api3-latest-server.json | 73 ++++++++++++++++++- app/config/specs/swagger2-latest-console.json | 73 ++++++++++++++++++- app/config/specs/swagger2-latest-server.json | 73 ++++++++++++++++++- 4 files changed, 280 insertions(+), 12 deletions(-) diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 76dd01367e..db615b0411 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -10140,7 +10140,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "schema": { "type": "array", @@ -25699,7 +25699,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "schema": { "type": "array", @@ -36875,6 +36875,36 @@ "description": "Site's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "vars": { "type": "array", "description": "Site variables.", @@ -36959,6 +36989,12 @@ "live", "framework", "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "vars", "timeout", "installCommand", @@ -37183,6 +37219,26 @@ "description": "Function's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "scopes": { "type": "array", "description": "Allowed permission scopes.", @@ -37275,6 +37331,10 @@ "logging", "runtime", "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -37986,6 +38046,12 @@ "x-example": 128, "format": "int32" }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, "buildId": { "type": "string", "description": "The current build ID.", @@ -38008,7 +38074,7 @@ }, "status": { "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\".", "x-example": "ready" }, "buildLogs": { @@ -38083,6 +38149,7 @@ "entrypoint", "sourceSize", "buildSize", + "totalSize", "buildId", "activate", "screenshotLight", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index c7704fd6a8..e819616de5 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -9005,7 +9005,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "schema": { "type": "array", @@ -17574,7 +17574,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "schema": { "type": "array", @@ -27423,6 +27423,36 @@ "description": "Site's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "vars": { "type": "array", "description": "Site variables.", @@ -27507,6 +27537,12 @@ "live", "framework", "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "vars", "timeout", "installCommand", @@ -27580,6 +27616,26 @@ "description": "Function's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "scopes": { "type": "array", "description": "Allowed permission scopes.", @@ -27672,6 +27728,10 @@ "logging", "runtime", "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -27885,6 +27945,12 @@ "x-example": 128, "format": "int32" }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, "buildId": { "type": "string", "description": "The current build ID.", @@ -27907,7 +27973,7 @@ }, "status": { "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\".", "x-example": "ready" }, "buildLogs": { @@ -27982,6 +28048,7 @@ "entrypoint", "sourceSize", "buildSize", + "totalSize", "buildId", "activate", "screenshotLight", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 4bfad91074..cd814521be 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -10322,7 +10322,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "type": "array", "collectionFormat": "multi", @@ -26230,7 +26230,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "type": "array", "collectionFormat": "multi", @@ -37455,6 +37455,36 @@ "description": "Site's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "vars": { "type": "array", "description": "Site variables.", @@ -37540,6 +37570,12 @@ "live", "framework", "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "vars", "timeout", "installCommand", @@ -37766,6 +37802,26 @@ "description": "Function's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "scopes": { "type": "array", "description": "Allowed permission scopes.", @@ -37859,6 +37915,10 @@ "logging", "runtime", "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -38573,6 +38633,12 @@ "x-example": 128, "format": "int32" }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, "buildId": { "type": "string", "description": "The current build ID.", @@ -38595,7 +38661,7 @@ }, "status": { "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\".", "x-example": "ready" }, "buildLogs": { @@ -38670,6 +38736,7 @@ "entrypoint", "sourceSize", "buildSize", + "totalSize", "buildId", "activate", "screenshotLight", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index c86f605f23..db2f32abcc 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -9188,7 +9188,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "type": "array", "collectionFormat": "multi", @@ -18075,7 +18075,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", "required": false, "type": "array", "collectionFormat": "multi", @@ -27974,6 +27974,36 @@ "description": "Site's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "vars": { "type": "array", "description": "Site variables.", @@ -28059,6 +28089,12 @@ "live", "framework", "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "vars", "timeout", "installCommand", @@ -28132,6 +28168,26 @@ "description": "Function's active deployment ID.", "x-example": "5e5ea5c16897e" }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, "scopes": { "type": "array", "description": "Allowed permission scopes.", @@ -28225,6 +28281,10 @@ "logging", "runtime", "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -28439,6 +28499,12 @@ "x-example": 128, "format": "int32" }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, "buildId": { "type": "string", "description": "The current build ID.", @@ -28461,7 +28527,7 @@ }, "status": { "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\".", "x-example": "ready" }, "buildLogs": { @@ -28536,6 +28602,7 @@ "entrypoint", "sourceSize", "buildSize", + "totalSize", "buildId", "activate", "screenshotLight", From 08b74007f73641ada84c815598b27de902f13605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 20 Mar 2025 16:20:31 +0100 Subject: [PATCH 7/7] Fix specs for console --- app/config/specs/open-api3-latest-console.json | 8 +++++++- app/config/specs/open-api3-latest-server.json | 8 +++++++- app/config/specs/swagger2-latest-console.json | 8 +++++++- app/config/specs/swagger2-latest-server.json | 8 +++++++- src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php | 6 ++++++ 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index db615b0411..8cd9ff6aa7 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -37986,13 +37986,19 @@ "type": "string", "description": "Default output directory of build.", "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" } }, "required": [ "key", "installCommand", "buildCommand", - "outputDirectory" + "outputDirectory", + "fallbackFile" ] }, "deployment": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index e819616de5..287ce791c3 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -27885,13 +27885,19 @@ "type": "string", "description": "Default output directory of build.", "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" } }, "required": [ "key", "installCommand", "buildCommand", - "outputDirectory" + "outputDirectory", + "fallbackFile" ] }, "deployment": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index cd814521be..89e23d8117 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -38573,13 +38573,19 @@ "type": "string", "description": "Default output directory of build.", "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" } }, "required": [ "key", "installCommand", "buildCommand", - "outputDirectory" + "outputDirectory", + "fallbackFile" ] }, "deployment": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index db2f32abcc..b7371b1bbd 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -28439,13 +28439,19 @@ "type": "string", "description": "Default output directory of build.", "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" } }, "required": [ "key", "installCommand", "buildCommand", - "outputDirectory" + "outputDirectory", + "fallbackFile" ] }, "deployment": { diff --git a/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php b/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php index 8348f3a6d5..afbd78eda4 100644 --- a/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php +++ b/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php @@ -34,6 +34,12 @@ class FrameworkAdapter extends Model 'default' => '', 'example' => './dist', ]) + ->addRule('fallbackFile', [ + 'type' => self::TYPE_STRING, + 'description' => 'Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.', + 'default' => null, + 'example' => 'index.html', + ]) ; }