diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 597f02f7d6..0612b50566 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -1154,7 +1154,6 @@ return [ ] ], ], - 'deployments' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('deployments'), @@ -1193,28 +1192,6 @@ return [ 'array' => false, 'filters' => [], ], - [ - '$id' => ID::custom('buildInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('buildId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ 'array' => false, '$id' => ID::custom('entrypoint'), @@ -1228,18 +1205,7 @@ return [ ], [ 'array' => false, - '$id' => ID::custom('commands'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('buildCommand'), + '$id' => ID::custom('buildCommands'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 16384, @@ -1250,7 +1216,7 @@ return [ ], [ 'array' => false, - '$id' => ID::custom('installCommand'), + '$id' => ID::custom('buildOutput'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 16384, @@ -1260,18 +1226,7 @@ return [ 'filters' => [], ], [ - 'array' => false, - '$id' => ID::custom('outputDirectory'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), + '$id' => ID::custom('sourcePath'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 2048, @@ -1285,7 +1240,7 @@ return [ '$id' => ID::custom('type'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 2048, + 'size' => 32, 'signed' => true, 'required' => true, 'default' => null, @@ -1464,7 +1419,7 @@ return [ 'array' => false, ], [ - '$id' => ID::custom('size'), + '$id' => ID::custom('sourceSize'), 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -1475,7 +1430,7 @@ return [ 'filters' => [], ], [ - '$id' => ID::custom('metadata'), + '$id' => ID::custom('sourceMetadata'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2 @@ -1486,7 +1441,7 @@ return [ 'filters' => ['json'], ], [ - '$id' => ID::custom('chunksTotal'), + '$id' => ID::custom('sourceChunksTotal'), 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -1497,7 +1452,7 @@ return [ 'filters' => [], ], [ - '$id' => ID::custom('chunksUploaded'), + '$id' => ID::custom('sourceChunksUploaded'), 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -1551,6 +1506,83 @@ return [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('buildStartAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('buildEndAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('buildDuration'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildSize'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => true, + 'default' => 'processing', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildPath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildLogs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ] ], 'indexes' => [ [ @@ -1575,16 +1607,23 @@ return [ 'orders' => [], ], [ - '$id' => ID::custom('_key_size'), + '$id' => ID::custom('_key_sourceSize'), 'type' => Database::INDEX_KEY, - 'attributes' => ['size'], + 'attributes' => ['sourceSize'], 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], [ - '$id' => ID::custom('_key_buildId'), + '$id' => ID::custom('_key_buildSize'), 'type' => Database::INDEX_KEY, - 'attributes' => ['buildId'], + 'attributes' => ['buildSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_buildDuration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['buildDuration'], 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], @@ -1595,155 +1634,19 @@ return [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - ], - ], - - 'builds' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('builds'), - 'name' => 'Builds', - 'attributes' => [ [ - '$id' => ID::custom('startTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('endTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - '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('runtime'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => 'processing', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => 'local', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('source'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_deployment'), + '$id' => ID::custom('_key_type'), 'type' => Database::INDEX_KEY, - 'attributes' => ['deploymentId'], - 'lengths' => [Database::LENGTH_KEY], + 'attributes' => ['type'], + 'lengths' => [32], 'orders' => [Database::ORDER_ASC], - ] + ], [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], ], ], diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 0f277a4661..80dff6ceaf 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -196,6 +196,17 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $providerRepositoryOwner = $pullRequestResponse['head']['repo']['name']; } + $commands = []; + if (!empty($resource->getAttribute('buildCommand', ''))) { + $commands[] = $resource->getAttribute('buildCommand', ''); + } + if (!empty($resource->getAttribute('installCommand', ''))) { + $commands[] = $resource->getAttribute('installCommand', ''); + } + if (!empty($resource->getAttribute('commands', ''))) { + $commands[] = $resource->getAttribute('commands', ''); + } + $deployment = $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ @@ -207,10 +218,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId 'resourceInternalId' => $resourceInternalId, 'resourceType' => $resourceCollection, 'entrypoint' => $resource->getAttribute('entrypoint', ''), - 'commands' => $resource->getAttribute('commands', ''), - 'installCommand' => $resource->getAttribute('installCommand', ''), - 'buildCommand' => $resource->getAttribute('buildCommand', ''), - 'outputDirectory' => $resource->getAttribute('outputDirectory', ''), + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $resource->getAttribute('outputDirectory', ''), 'type' => 'vcs', 'installationId' => $installationId, 'installationInternalId' => $installationInternalId, diff --git a/app/controllers/general.php b/app/controllers/general.php index 1ebb1c80b3..36ee66d580 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -191,13 +191,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported'); } - /** Check if build has completed */ - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - if ($build->isEmpty()) { - throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { throw new AppwriteException(AppwriteException::BUILD_NOT_READY); } @@ -388,7 +382,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw variables: $vars, timeout: $resource->getAttribute('timeout', 30), image: $runtime['image'], - source: $build->getAttribute('path', ''), + source: $deployment->getAttribute('buildPath', ''), entrypoint: $entrypoint, version: $version, path: $path, diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 7880df189e..2204e171cf 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -70,7 +70,7 @@ class Base extends Action 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, - 'commands' => $function->getAttribute('commands', ''), + 'buildCommands' => $function->getAttribute('commands', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), 'installationInternalId' => $installation->getInternalId(), @@ -139,6 +139,14 @@ class Base extends Action } } + $commands = []; + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + $deployment = $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ @@ -149,9 +157,8 @@ class Base extends Action 'resourceId' => $site->getId(), 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'sites', - 'buildCommand' => $site->getAttribute('buildCommand', ''), - 'installCommand' => $site->getAttribute('installCommand', ''), - 'outputDirectory' => $site->getAttribute('outputDirectory', ''), + 'buildCommands' => implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), 'installationInternalId' => $installation->getInternalId(), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index 6885ecde6c..580959589b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -174,8 +174,8 @@ class Create extends Action $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; if (!$deployment->isEmpty()) { - $chunks = $deployment->getAttribute('chunksTotal', 1); - $metadata = $deployment->getAttribute('metadata', []); + $chunks = $deployment->getAttribute('sourceChunksTotal', 1); + $metadata = $deployment->getAttribute('sourceMetadata', []); if ($chunk === -1) { $chunk = $chunks; } @@ -217,18 +217,17 @@ class Create extends Action 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'buildInternalId' => '', 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'path' => $path, - 'size' => $fileSize, + 'buildCommands' => $commands, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, 'search' => implode(' ', [$deploymentId, $entrypoint]), 'activate' => $activate, - 'metadata' => $metadata, + 'sourceMetadata' => $metadata, 'type' => $type ])); } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('size', $fileSize)->setAttribute('metadata', $metadata)); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata)); } // Start the build @@ -248,20 +247,19 @@ class Create extends Action 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'buildInternalId' => '', 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'path' => $path, - 'size' => $fileSize, - 'chunksTotal' => $chunks, - 'chunksUploaded' => $chunksUploaded, + 'buildCommands' => $commands, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'sourceChunksTotal' => $chunks, + 'sourceChunksUploaded' => $chunksUploaded, 'search' => implode(' ', [$deploymentId, $entrypoint]), 'activate' => $activate, - 'metadata' => $metadata, + 'sourceMetadata' => $metadata, 'type' => $type ])); } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('chunksUploaded', $chunksUploaded)->setAttribute('metadata', $metadata)); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata)); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index 5bde7903d9..c02c470980 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -83,8 +83,8 @@ class Delete extends Action throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); } - if (!empty($deployment->getAttribute('path', ''))) { - if (!($deviceForFunctions->delete($deployment->getAttribute('path', '')))) { + if (!empty($deployment->getAttribute('sourcePath', ''))) { + if (!($deviceForFunctions->delete($deployment->getAttribute('sourcePath', '')))) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage'); } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php index a63ac18354..4fa279a3d7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php @@ -81,16 +81,11 @@ class Get extends Action switch ($type) { case 'output': - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - $path = $build->getAttribute('path', ''); + $path = $deployment->getAttribute('buildPath', ''); $device = $deviceForBuilds; break; case 'source': - $path = $deployment->getAttribute('path', ''); + $path = $deployment->getAttribute('sourcePath', ''); $device = $deviceForFunctions; break; } 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 624a410dcd..b942ba9ab7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -77,7 +77,7 @@ class Create extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $path = $deployment->getAttribute('path'); + $path = $deployment->getAttribute('sourcePath'); if (empty($path) || !$deviceForFunctions->exists($path)) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } @@ -91,12 +91,17 @@ class Create extends Action $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ '$internalId' => '', '$id' => $deploymentId, - 'buildId' => '', - 'buildInternalId' => '', - 'path' => $destination, + 'sourcePath' => $destination, 'entrypoint' => $function->getAttribute('entrypoint'), - 'commands' => $function->getAttribute('commands', ''), + 'buildCommands' => $function->getAttribute('commands', ''), 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]), + 'buildStartAt' => null, + 'buildEndAt' => null, + 'buildDuration' => null, + 'buildSize' => null, + 'status' => 'processing', + 'buildPath' => '', + 'buildLogs' => '', ])); $queueForBuilds diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php index 1d074e9e2a..8e58433e7c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php @@ -69,13 +69,6 @@ class Get extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - $deployment->setAttribute('status', $build->getAttribute('status', 'waiting')); - $deployment->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $deployment->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $deployment->setAttribute('buildSize', $build->getAttribute('size', 0)); - $deployment->setAttribute('size', $deployment->getAttribute('size', 0)); - $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); } } 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 e349292e4b..6c8cacdcfd 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -13,8 +13,6 @@ use Utopia\App; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -50,7 +48,7 @@ class Update extends Action responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_BUILD, + model: Response::MODEL_DEPLOYMENT, ) ] )) @@ -77,46 +75,19 @@ class Update extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - - if ($build->isEmpty()) { - $buildId = ID::unique(); - $build = $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$permissions' => [], - 'startTime' => DateTime::now(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'status' => 'canceled', - 'path' => '', - 'runtime' => $function->getAttribute('runtime'), - 'source' => $deployment->getAttribute('path', ''), - 'sourceType' => '', - 'logs' => '', - 'duration' => 0, - 'size' => 0 - ])); - - $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } else { - if (\in_array($build->getAttribute('status'), ['ready', 'failed'])) { - throw new Exception(Exception::BUILD_ALREADY_COMPLETED); - } - - $startTime = new \DateTime($build->getAttribute('startTime')); - $endTime = new \DateTime('now'); - $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); - - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttributes([ - 'endTime' => DateTime::now(), - 'duration' => $duration, - 'status' => 'canceled' - ])); + if (\in_array($deployment->getAttribute('status'), ['ready', 'failed'])) { + throw new Exception(Exception::BUILD_ALREADY_COMPLETED); } - $dbForProject->purgeCachedDocument('deployments', $deployment->getId()); + $startTime = new \DateTime($deployment->getAttribute('buildStartAt')); + $endTime = new \DateTime('now'); + $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttributes([ + 'buildEndAt' => DateTime::now(), + 'buildDuration' => $duration, + 'status' => 'canceled' + ])); try { $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); @@ -132,6 +103,6 @@ class Update extends Action ->setParam('functionId', $function->getId()) ->setParam('deploymentId', $deployment->getId()); - $response->dynamic($build, Response::MODEL_BUILD); + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); } } 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 9a61693e15..1f6fa364f3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -130,7 +130,7 @@ class Create extends Base 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), - 'commands' => $function->getAttribute('commands', ''), + 'buildCommands' => $function->getAttribute('commands', ''), 'type' => 'manual', 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint', '')]), 'activate' => $activate, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 9e03a86bc7..a416001e2f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -110,15 +110,6 @@ class XList extends Action $results = $dbForProject->find('deployments', $queries); $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); - foreach ($results as $result) { - $build = $dbForProject->getDocument('builds', $result->getAttribute('buildId', '')); - $result->setAttribute('status', $build->getAttribute('status', 'processing')); - $result->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $result->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $result->setAttribute('buildSize', $build->getAttribute('size', 0)); - $result->setAttribute('size', $result->getAttribute('size', 0)); - } - $response->dynamic(new Document([ 'deployments' => $results, 'total' => $total, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index d59a3322a4..0bb755a1f2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -4,8 +4,6 @@ namespace Appwrite\Platform\Modules\Functions\Http\Executions; use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; -use Appwrite\Event\Build; -use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\StatsUsage; @@ -158,13 +156,7 @@ class Create extends Base throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); } - /** Check if build has completed */ - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { throw new Exception(Exception::BUILD_NOT_READY); } @@ -385,7 +377,7 @@ class Create extends Base variables: $vars, timeout: $function->getAttribute('timeout', 0), image: $runtime['image'], - source: $build->getAttribute('path', ''), + source: $deployment->getAttribute('buildPath', ''), entrypoint: $deployment->getAttribute('entrypoint', ''), version: $version, path: $path, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index f45aa0a108..cda0b8b6d9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -68,7 +68,6 @@ class Update extends Base { $function = $dbForProject->getDocument('functions', $functionId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); if ($function->isEmpty()) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -78,11 +77,7 @@ class Update extends Base throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { throw new Exception(Exception::BUILD_NOT_READY); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index ba922b89c0..5d6a518e10 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -186,39 +186,19 @@ class Builds extends Action $startTime = DateTime::now(); $durationStart = \microtime(true); - $buildId = $deployment->getAttribute('buildId', ''); - $build = $dbForProject->getDocument('builds', $buildId); - $isNewBuild = empty($buildId); - if ($build->isEmpty()) { - $buildId = ID::unique(); - $build = $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$permissions' => [], - 'startTime' => $startTime, - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'status' => 'processing', - 'path' => '', - 'runtime' => $resource->getAttribute('runtime'), - 'source' => $deployment->getAttribute('path', ''), - 'sourceType' => strtolower($deviceForFunctions->getType()), - 'logs' => '', - 'endTime' => null, - 'duration' => 0, - 'size' => 0 - ])); - $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } elseif ($build->getAttribute('status') === 'canceled') { + if ($deployment->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; - } else { - $build = $dbForProject->getDocument('builds', $buildId); } - $source = $deployment->getAttribute('path', ''); + $deploymentId = $deployment->getId(); + + $deployment->setAttribute('buildStartAt', $startTime); + $deployment->setAttribute('status', 'processing'); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $source = $deployment->getAttribute('sourcePath', ''); $installationId = $deployment->getAttribute('installationId', ''); $providerRepositoryId = $deployment->getAttribute('providerRepositoryId', ''); $providerCommitHash = $deployment->getAttribute('providerCommitHash', ''); @@ -236,7 +216,7 @@ class Builds extends Action } try { - if ($isNewBuild && !$isVcsEnabled) { + if (!$isVcsEnabled) { // Non-VCS + Template $templateRepositoryName = $template->getAttribute('repositoryName', ''); $templateOwnerName = $template->getAttribute('ownerName', ''); @@ -252,7 +232,7 @@ class Builds extends Action $stderr = ''; // Clone template repo - $tmpTemplateDirectory = '/tmp/builds/' . $buildId . '-template'; + $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '-template'; $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); @@ -286,12 +266,14 @@ class Builds extends Action Console::execute('rm -rf ' . \escapeshellarg($tmpTemplateDirectory), '', $stdout, $stderr); $directorySize = $device->getFileSize($source); - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttribute('source', $source)); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize)); + $deployment + ->setAttribute('sourcePath', $source) + ->setAttribute('sourceSize', $directorySize); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); } - } elseif ($isNewBuild && $isVcsEnabled) { + } elseif ($isVcsEnabled) { // VCS and VCS+Temaplte - $tmpDirectory = '/tmp/builds/' . $buildId . '/code'; + $tmpDirectory = '/tmp/builds/' . $deploymentId . '/code'; $rootDirectory = $resource->getAttribute('providerRootDirectory', ''); $rootDirectory = \rtrim($rootDirectory, '/'); $rootDirectory = \ltrim($rootDirectory, '.'); @@ -317,9 +299,9 @@ class Builds extends Action $stdout = ''; $stderr = ''; - Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds/' . $buildId), '', $stdout, $stderr); + Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds/' . $deploymentId), '', $stdout, $stderr); - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; } @@ -356,7 +338,7 @@ class Builds extends Action if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { // Clone template repo - $tmpTemplateDirectory = '/tmp/builds/' . $buildId . '/template'; + $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '/template'; $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); @@ -401,19 +383,19 @@ class Builds extends Action $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], - payload: $build, + payload: $deployment, project: $project ); Realtime::send( projectId: 'console', - payload: $build->getArrayCopy(), + payload: $deployment->getArrayCopy(), events: $allEvents, channels: $target['channels'], roles: $target['roles'] ); } - $tmpPath = '/tmp/builds/' . $buildId; + $tmpPath = '/tmp/builds/' . $deployment; $tmpPathFile = $tmpPath . '/code.tar.gz'; $localDevice = new Local(); @@ -430,7 +412,7 @@ class Builds extends Action Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); - $tarParamDirectory = '/tmp/builds/' . $buildId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); + $tarParamDirectory = '/tmp/builds/' . $deploymentId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax $source = $device->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); @@ -442,17 +424,19 @@ class Builds extends Action Console::execute('rm -rf ' . \escapeshellarg($tmpPath), '', $stdout, $stderr); - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttribute('source', $source)); - $directorySize = $device->getFileSize($source); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize)); + + $deployment + ->setAttribute('sourcePath', $source) + ->setAttribute('sourceSize', $directorySize); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); $this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); } /** Request the executor to build the code... */ - $build->setAttribute('status', 'building'); - $build = $dbForProject->updateDocument('builds', $buildId, $build); + $deployment->setAttribute('status', 'building'); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); if ($isVcsEnabled) { $this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); @@ -481,13 +465,13 @@ class Builds extends Action $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], - payload: $build, + payload: $deployment, project: $project ); Realtime::send( projectId: 'console', - payload: $build->getArrayCopy(), + payload: $deployment->getArrayCopy(), events: $allEvents, channels: $target['channels'], roles: $target['roles'] @@ -582,7 +566,7 @@ class Builds extends Action $response = null; $err = null; - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; } @@ -615,26 +599,22 @@ class Builds extends Action $err = $error; } }), - Co\go(function () use ($executor, $project, $deployment, &$response, &$build, $dbForProject, $allEvents, $timeout, &$err, &$isCanceled) { + Co\go(function () use ($executor, $project, &$deployment, &$response, $dbForProject, $allEvents, $timeout, &$err, &$isCanceled) { try { $executor->getLogs( deploymentId: $deployment->getId(), projectId: $project->getId(), timeout: $timeout, - callback: function ($logs) use (&$response, &$err, &$build, $dbForProject, $allEvents, $project, &$isCanceled) { + callback: function ($logs) use (&$response, &$err, $dbForProject, $allEvents, $project, &$isCanceled, &$deployment) { if ($isCanceled) { return; } // If we have response or error from concurrent coroutine, we already have latest logs if ($response === null && $err === null) { - $build = $dbForProject->getDocument('builds', $build->getId()); + $deployment = $dbForProject->getDocument('deployments', $deployment->getId()); - if ($build->isEmpty()) { - throw new \Exception('Build not found'); - } - - if ($build->getAttribute('status') === 'canceled') { + if ($deployment->getAttribute('status') === 'canceled') { $isCanceled = true; Console::info('Ignoring realtime logs because build has been canceled'); return; @@ -643,7 +623,7 @@ class Builds extends Action // Get only valid UTF8 part - removes leftover half-multibytes causing SQL errors $logs = \mb_substr($logs, 0, null, 'UTF-8'); - $currentLogs = $build->getAttribute('logs', ''); + $currentLogs = $deployment->getAttribute('buildLogs', ''); $streamLogs = \str_replace("\\n", "{APPWRITE_LINEBREAK_PLACEHOLDER}", $logs); foreach (\explode("\n", $streamLogs) as $streamLog) { @@ -658,8 +638,8 @@ class Builds extends Action $currentLogs .= $streamParts[1]; } - $build = $build->setAttribute('logs', $currentLogs); - $build = $dbForProject->updateDocument('builds', $build->getId(), $build); + $deployment = $deployment->setAttribute('buildLogs', $currentLogs); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); /** * Send realtime Event @@ -667,12 +647,12 @@ class Builds extends Action $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], - payload: $build, + payload: $deployment, project: $project ); Realtime::send( projectId: 'console', - payload: $build->getArrayCopy(), + payload: $deployment->getArrayCopy(), events: $allEvents, channels: $target['channels'], roles: $target['roles'] @@ -688,7 +668,7 @@ class Builds extends Action }), ]); - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; } @@ -706,26 +686,26 @@ class Builds extends Action } /** Update the build document */ - $build->setAttribute('startTime', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); - $build->setAttribute('endTime', $endTime); - $build->setAttribute('duration', \intval(\ceil($durationEnd - $durationStart))); - $build->setAttribute('status', 'ready'); - $build->setAttribute('path', $response['path']); - $build->setAttribute('size', $response['size']); + $deployment->setAttribute('buildStartAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); + $deployment->setAttribute('buildEndAt', $endTime); + $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); + $deployment->setAttribute('status', 'ready'); + $deployment->setAttribute('buildPath', $response['path']); + $deployment->setAttribute('buildSize', $response['size']); $logs = ''; foreach ($response['output'] as $log) { $logs .= $log['content']; } - $build->setAttribute('logs', $logs); + $deployment->setAttribute('buildLogs', $logs); - $build = $dbForProject->updateDocument('builds', $buildId, $build); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); if ($isVcsEnabled) { $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); } - Console::success("Build id: $buildId created"); + Console::success("Build id: $deploymentId created"); if ($resource->getCollection() === 'sites') { try { @@ -884,7 +864,7 @@ class Builds extends Action } - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; } @@ -901,20 +881,19 @@ class Builds extends Action Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } catch (\Throwable $th) { - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return; } $endTime = DateTime::now(); $durationEnd = \microtime(true); - $build->setAttribute('endTime', $endTime); - $build->setAttribute('duration', \intval(\ceil($durationEnd - $durationStart))); - $build->setAttribute('status', 'failed'); + $deployment->setAttribute('buildEndAt', $endTime); + $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); + $deployment->setAttribute('status', 'failed'); + $deployment->setAttribute('buildLogs', "" . $th->getMessage()); - $build->setAttribute('logs', "[31m" . $th->getMessage() . "[0m"); - - $build = $dbForProject->updateDocument('builds', $buildId, $build); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); if ($isVcsEnabled) { $this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); @@ -926,26 +905,26 @@ class Builds extends Action $target = Realtime::fromPayload( // Pass first, most verbose event pattern event: $allEvents[0], - payload: $build, + payload: $deployment, project: $project ); Realtime::send( projectId: 'console', - payload: $build->getArrayCopy(), + payload: $deployment->getArrayCopy(), events: $allEvents, channels: $target['channels'], roles: $target['roles'] ); $this->sendUsage( resource:$resource, - build: $build, + deployment: $deployment, project: $project, queue: $queueForStatsUsage ); } } - protected function sendUsage(Document $resource, Document $build, Document $project, StatsUsage $queue): void + protected function sendUsage(Document $resource, Document $deployment, Document $project, StatsUsage $queue): void { $key = match($resource->getCollection()) { 'functions' => 'functionInternalId', @@ -976,32 +955,32 @@ class Builds extends Action ] }; - switch ($build->getAttribute('status')) { + switch ($deployment->getAttribute('status')) { case 'ready': $queue ->addMetric(METRIC_BUILDS_SUCCESS, 1) // per project - ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_SUCCESS), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS), (int)$build->getAttribute('duration', 0) * 1000); + ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; case 'failed': $queue ->addMetric(METRIC_BUILDS_FAILED, 1) // per project - ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace($key, $resource->getInternalId(), $metrics['buildsFailed']), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), $metrics['buildsComputeFailed']), (int)$build->getAttribute('duration', 0) * 1000); + ->addMetric(str_replace($key, $resource->getInternalId(), $metrics['buildsComputeFailed']), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; } $queue ->addMetric(METRIC_BUILDS, 1) // per project - ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) - ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $build->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(METRIC_BUILDS_STORAGE, $deployment->getAttribute('buildSize', 0)) + ->addMetric(METRIC_BUILDS_COMPUTE, (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $build->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) + ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace($key, $resource->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->setProject($project) ->trigger(); } @@ -1033,7 +1012,7 @@ class Builds extends Action protected function getCommand(Document $resource, Document $deployment): string { if ($resource->getCollection() === 'functions') { - return $deployment->getAttribute('commands', ''); + return $deployment->getAttribute('buildCommands', ''); } elseif ($resource->getCollection() === 'sites') { $commands = []; @@ -1054,8 +1033,7 @@ class Builds extends Action } $commands[] = $envCommand; - $commands[] = $deployment->getAttribute('installCommand', ''); - $commands[] = $deployment->getAttribute('buildCommand', ''); + $commands[] = $deployment->getAttribute('buildCommands', ''); $commands[] = $bundleCommand; $commands = array_filter($commands, fn ($command) => !empty($command)); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index fc70f2fe25..a899e1aa3e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -173,8 +173,8 @@ class Create extends Action $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; if (!$deployment->isEmpty()) { - $chunks = $deployment->getAttribute('chunksTotal', 1); - $metadata = $deployment->getAttribute('metadata', []); + $chunks = $deployment->getAttribute('sourceChunksTotal', 1); + $metadata = $deployment->getAttribute('sourceMetadata', []); if ($chunk === -1) { $chunk = $chunks; } @@ -188,6 +188,14 @@ class Create extends Action $type = $request->getHeader('x-sdk-language') === 'cli' ? 'cli' : 'manual'; + $commands = []; + if (!empty($installCommand)) { + $commands[] = $installCommand; + } + if (!empty($buildCommand)) { + $commands[] = $buildCommand; + } + if ($chunksUploaded === $chunks) { if ($activate) { // Remove deploy for all other deployments. @@ -216,15 +224,13 @@ class Create extends Action 'resourceInternalId' => $site->getInternalId(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', - 'buildInternalId' => '', - 'installCommand' => $installCommand, - 'buildCommand' => $buildCommand, - 'outputDirectory' => $outputDirectory, - 'path' => $path, - 'size' => $fileSize, + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $outputDirectory, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, 'search' => implode(' ', [$deploymentId]), 'activate' => $activate, - 'metadata' => $metadata, + 'sourceMetadata' => $metadata, 'type' => $type ])); @@ -245,7 +251,7 @@ class Create extends Action ])) ); } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('size', $fileSize)->setAttribute('metadata', $metadata)); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata)); } // Start the build @@ -265,17 +271,15 @@ class Create extends Action 'resourceInternalId' => $site->getInternalId(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', - 'buildInternalId' => '', - 'installCommand' => $installCommand, - 'buildCommand' => $buildCommand, - 'outputDirectory' => $outputDirectory, - 'path' => $path, - 'size' => $fileSize, - 'chunksTotal' => $chunks, - 'chunksUploaded' => $chunksUploaded, + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $outputDirectory, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'sourceChunksTotal' => $chunks, + 'sourceChunksUploaded' => $chunksUploaded, 'search' => implode(' ', [$deploymentId]), 'activate' => $activate, - 'metadata' => $metadata, + 'sourceMetadata' => $metadata, 'type' => $type ])); @@ -296,7 +300,7 @@ class Create extends Action ])) ); } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('chunksUploaded', $chunksUploaded)->setAttribute('metadata', $metadata)); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata)); } } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index fe16dafae1..7065ac1917 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -83,8 +83,8 @@ class Delete extends Action throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); } - if (!empty($deployment->getAttribute('path', ''))) { - if (!($deviceForSites->delete($deployment->getAttribute('path', '')))) { + if (!empty($deployment->getAttribute('sourcePath', ''))) { + if (!($deviceForSites->delete($deployment->getAttribute('sourcePath', '')))) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage'); } } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php index f4b6b73784..6d969f883f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php @@ -80,16 +80,11 @@ class Get extends Action switch ($type) { case 'output': - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - $path = $build->getAttribute('path', ''); + $path = $deployment->getAttribute('buildPath', ''); $device = $deviceForBuilds; break; case 'source': - $path = $deployment->getAttribute('path', ''); + $path = $deployment->getAttribute('sourcePath', ''); $device = $deviceForSites; break; } 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 b30c07838f..f32056cbe9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -78,7 +78,7 @@ class Create extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $path = $deployment->getAttribute('path'); + $path = $deployment->getAttribute('sourcePath'); if (empty($path) || !$deviceForSites->exists($path)) { throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } @@ -88,19 +88,31 @@ class Create extends Action $destination = $deviceForSites->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $deviceForSites->transfer($path, $destination, $deviceForSites); + $commands = []; + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + $deployment->removeAttribute('$internalId'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ '$internalId' => '', '$id' => $deploymentId, - 'buildId' => '', - 'buildInternalId' => '', - 'path' => $destination, - 'buildCommand' => $site->getAttribute('buildCommand', ''), - 'installCommand' => $site->getAttribute('installCommand', ''), - 'outputDirectory' => $site->getAttribute('outputDirectory', ''), + 'sourcePath' => $destination, + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), 'search' => implode(' ', [$deploymentId]), 'screenshotLight' => '', - 'screenshotDark' => '' + 'screenshotDark' => '', + 'buildStartAt' => null, + 'buildEndAt' => null, + 'buildDuration' => null, + 'buildSize' => null, + 'status' => 'processing', + 'buildPath' => '', + 'buildLogs' => '', ])); // Preview deployments for sites diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php index c7929b2e7a..8c3beaf2c0 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php @@ -69,13 +69,6 @@ class Get extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - $deployment->setAttribute('status', $build->getAttribute('status', 'waiting')); - $deployment->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $deployment->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $deployment->setAttribute('buildSize', $build->getAttribute('size', 0)); - $deployment->setAttribute('size', $deployment->getAttribute('size', 0)); - $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); } } 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 0a15053df1..632ad51c9b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -13,8 +13,6 @@ use Utopia\App; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -48,7 +46,7 @@ class Update extends Action responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_BUILD, + model: Response::MODEL_DEPLOYMENT, ) ] )) @@ -75,46 +73,19 @@ class Update extends Action throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - - if ($build->isEmpty()) { - $buildId = ID::unique(); - $build = $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$permissions' => [], - 'startTime' => DateTime::now(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'status' => 'canceled', - 'path' => '', - 'runtime' => $site->getAttribute('framework'), - 'source' => $deployment->getAttribute('path', ''), - 'sourceType' => '', - 'logs' => '', - 'duration' => 0, - 'size' => 0 - ])); - - $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } else { - if (\in_array($build->getAttribute('status'), ['ready', 'failed'])) { - throw new Exception(Exception::BUILD_ALREADY_COMPLETED); - } - - $startTime = new \DateTime($build->getAttribute('startTime')); - $endTime = new \DateTime('now'); - $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); - - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttributes([ - 'endTime' => DateTime::now(), - 'duration' => $duration, - 'status' => 'canceled' - ])); + if (\in_array($deployment->getAttribute('status'), ['ready', 'failed'])) { + throw new Exception(Exception::BUILD_ALREADY_COMPLETED); } - $dbForProject->purgeCachedDocument('deployments', $deployment->getId()); + $startTime = new \DateTime($deployment->getAttribute('buildStartAt')); + $endTime = new \DateTime('now'); + $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttributes([ + 'buildEndAt' => DateTime::now(), + 'buildDuration' => $duration, + 'status' => 'canceled' + ])); try { $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); @@ -130,6 +101,6 @@ class Update extends Action ->setParam('siteId', $site->getId()) ->setParam('deploymentId', $deployment->getId()); - $response->dynamic($build, Response::MODEL_BUILD); + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); } } 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 5fa7a68e82..7ab20cecb0 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -121,6 +121,14 @@ class Create extends Base return; } + $commands = []; + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + $deploymentId = ID::unique(); $deployment = $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, @@ -132,9 +140,8 @@ class Create extends Base 'resourceId' => $site->getId(), 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'sites', - 'installCommand' => $site->getAttribute('installCommand', ''), - 'buildCommand' => $site->getAttribute('buildCommand', ''), - 'outputDirectory' => $site->getAttribute('outputDirectory', ''), + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), 'type' => 'manual', 'search' => implode(' ', [$deploymentId]), 'activate' => $activate, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index c29b14b840..e041554132 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -110,15 +110,6 @@ class XList extends Action $results = $dbForProject->find('deployments', $queries); $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); - foreach ($results as $result) { - $build = $dbForProject->getDocument('builds', $result->getAttribute('buildId', '')); - $result->setAttribute('status', $build->getAttribute('status', 'processing')); - $result->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $result->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $result->setAttribute('buildSize', $build->getAttribute('size', 0)); - $result->setAttribute('size', $result->getAttribute('size', 0)); - } - $response->dynamic(new Document([ 'deployments' => $results, 'total' => $total, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index fcb0532929..611cdcb104 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -65,7 +65,6 @@ class Update extends Base { $site = $dbForProject->getDocument('sites', $siteId); $deployment = $dbForProject->getDocument('deployments', $deploymentId); - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); if ($site->isEmpty()) { throw new Exception(Exception::SITE_NOT_FOUND); @@ -75,11 +74,7 @@ class Update extends Base throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { throw new Exception(Exception::BUILD_NOT_READY); } diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 09fe98dd7f..a875f9e940 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -784,9 +784,10 @@ class Deletes extends Action $deploymentIds = []; $this->deleteByGroup('deployments', [ Query::equal('resourceInternalId', [$siteInternalId]) - ], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { + ], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { $deploymentInternalIds[] = $document->getInternalId(); $deploymentIds[] = $document->getId(); + $this->deleteBuildFiles($deviceForBuilds, $document); $this->deleteDeploymentFiles($deviceForSites, $document); $this->deleteDeploymentScreenshots($deviceForFiles, $dbForPlatform, $document); $this->deleteDeploymentRules($dbForPlatform, $document, $project, $certificates); @@ -806,18 +807,6 @@ class Deletes extends Action }); } - /** - * Delete builds - */ - Console::info("Deleting builds for site " . $siteId); - foreach ($deploymentInternalIds as $deploymentInternalId) { - $this->deleteByGroup('builds', [ - Query::equal('deploymentInternalId', [$deploymentInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForBuilds) { - $this->deleteBuildFiles($deviceForBuilds, $document); - }); - } - /** * Delete VCS Repositories and VCS Comments */ @@ -881,25 +870,13 @@ class Deletes extends Action $deploymentInternalIds = []; $this->deleteByGroup('deployments', [ Query::equal('resourceInternalId', [$functionInternalId]) - ], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, &$deploymentInternalIds) { + ], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) { $deploymentInternalIds[] = $document->getInternalId(); $this->deleteDeploymentFiles($deviceForFunctions, $document); + $this->deleteBuildFiles($deviceForBuilds, $document); $this->deleteDeploymentRules($dbForPlatform, $document, $project, $certificates); }); - /** - * Delete builds - */ - Console::info("Deleting builds for function " . $functionId); - - foreach ($deploymentInternalIds as $deploymentInternalId) { - $this->deleteByGroup('builds', [ - Query::equal('deploymentInternalId', [$deploymentInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForBuilds) { - $this->deleteBuildFiles($deviceForBuilds, $document); - }); - } - /** * Delete Executions */ @@ -999,7 +976,7 @@ class Deletes extends Action private function deleteDeploymentFiles(Device $device, Document $deployment): void { $deploymentId = $deployment->getId(); - $deploymentPath = $deployment->getAttribute('path', ''); + $deploymentPath = $deployment->getAttribute('sourcePath', ''); if (empty($deploymentPath)) { Console::info("No deployment files for deployment " . $deploymentId); @@ -1028,13 +1005,13 @@ class Deletes extends Action * @param Document $build * @return void */ - private function deleteBuildFiles(Device $device, Document $build): void + private function deleteBuildFiles(Device $device, Document $deployment): void { - $buildId = $build->getId(); - $buildPath = $build->getAttribute('path', ''); + $deploymentId = $deployment->getId(); + $buildPath = $deployment->getAttribute('buildPath', ''); if (empty($buildPath)) { - Console::info("No build files for build " . $buildId); + Console::info("No build files for deployment " . $deploymentId); return; } @@ -1085,15 +1062,9 @@ class Deletes extends Action $this->deleteDeploymentScreenshots($deviceForFiles, $dbForPlatform, $document); /** - * Delete builds + * Delete deployment build */ - Console::info("Deleting builds for deployment " . $deploymentId); - - $this->deleteByGroup('builds', [ - Query::equal('deploymentInternalId', [$deploymentInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForBuilds) { - $this->deleteBuildFiles($deviceForBuilds, $document); - }); + $this->deleteBuildFiles($deviceForBuilds, $document); /** * Delete rules associated with the deployment diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index b0a9512f8e..febaec54d7 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -346,19 +346,7 @@ class Functions extends Action return; } - $buildId = $deployment->getAttribute('buildId', ''); - - $log->addTag('buildId', $buildId); - - /** Check if build has exists */ - $build = $dbForProject->getDocument('builds', $buildId); - if ($build->isEmpty()) { - $errorMessage = 'The execution could not be completed because a corresponding deployment was not found. A function deployment needs to be created before it can be executed. Please create a deployment for your function and try again.'; - $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); - return; - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { $errorMessage = 'The execution could not be completed because the build is not ready. Please wait for the build to complete and try again.'; $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; @@ -513,7 +501,7 @@ class Functions extends Action variables: $vars, timeout: $function->getAttribute('timeout', 0), image: $runtime['image'], - source: $build->getAttribute('path', ''), + source: $deployment->getAttribute('buildPath', ''), entrypoint: $deployment->getAttribute('entrypoint', ''), version: $version, path: $path, diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index a6101522fb..fa8d7490ea 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -268,15 +268,13 @@ class StatsResources extends Action protected function countForFunctions(Database $dbForProject, Database $dbForLogs, string $region) { $deploymentsStorage = $dbForProject->sum('deployments', 'size'); - $buildsStorage = $dbForProject->sum('builds', 'size'); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize'); $this->createStatsDocuments($region, METRIC_DEPLOYMENTS_STORAGE, $deploymentsStorage); $this->createStatsDocuments($region, METRIC_BUILDS_STORAGE, $buildsStorage); $deployments = $dbForProject->count('deployments'); - $builds = $dbForProject->count('builds'); $this->createStatsDocuments($region, METRIC_DEPLOYMENTS, $deployments); - $this->createStatsDocuments($region, METRIC_BUILDS, $builds); - + $this->createStatsDocuments($region, METRIC_BUILDS, $deployments); $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $dbForLogs, $region) { $functionDeploymentsStorage = $dbForProject->sum('deployments', 'size', [ @@ -302,9 +300,8 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'deployments', [ Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), - ], function (Document $deployment) use ($dbForProject, &$functionBuildsStorage): void { - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - $functionBuildsStorage += $build->getAttribute('size', 0); + ], function (Document $deployment) use (&$functionBuildsStorage): void { + $functionBuildsStorage += $deployment->getAttribute('buildSize', 0); }); $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index 42aed88ef6..75035ad501 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -5,13 +5,12 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Deployments extends Base { public const ALLOWED_ATTRIBUTES = [ - 'size', - 'buildId', + 'buildSize', + 'sourceSize', + 'buildDuration', + 'status', 'activate', - 'entrypoint', - 'commands', 'type', - 'size' ]; /** diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index da222822e0..d93c2178d8 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -30,7 +30,6 @@ use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\Branch; use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Continent; @@ -272,8 +271,6 @@ class Response extends SwooleResponse public const MODEL_DEPLOYMENT_LIST = 'deploymentList'; public const MODEL_EXECUTION = 'execution'; public const MODEL_EXECUTION_LIST = 'executionList'; - public const MODEL_BUILD = 'build'; - public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; public const MODEL_HEADERS = 'headers'; public const MODEL_SPECIFICATION = 'specification'; @@ -381,7 +378,6 @@ class Response extends SwooleResponse ->setModel(new BaseList('Runtimes List', self::MODEL_RUNTIME_LIST, 'runtimes', self::MODEL_RUNTIME)) ->setModel(new BaseList('Deployments List', self::MODEL_DEPLOYMENT_LIST, 'deployments', self::MODEL_DEPLOYMENT)) ->setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION)) - ->setModel(new BaseList('Builds List', self::MODEL_BUILD_LIST, 'builds', self::MODEL_BUILD)) // Not used anywhere yet ->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false)) ->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false)) ->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false)) @@ -461,7 +457,6 @@ class Response extends SwooleResponse ->setModel(new FrameworkAdapter()) ->setModel(new Deployment()) ->setModel(new Execution()) - ->setModel(new Build()) ->setModel(new Project()) ->setModel(new Webhook()) ->setModel(new Key()) diff --git a/src/Appwrite/Utopia/Response/Model/Build.php b/src/Appwrite/Utopia/Response/Model/Build.php deleted file mode 100644 index d80c17645a..0000000000 --- a/src/Appwrite/Utopia/Response/Model/Build.php +++ /dev/null @@ -1,94 +0,0 @@ -addRule('$id', [ - 'type' => self::TYPE_STRING, - 'description' => 'Build ID.', - 'default' => '', - 'example' => '5e5ea5c16897e', - ]) - ->addRule('deploymentId', [ - 'type' => self::TYPE_STRING, - 'description' => 'The deployment that created this build.', - 'default' => '', - 'example' => '5e5ea5c16897e', - ]) - // Build Status - // Failed - The deployment build has failed. More details can usually be found in buildStderr - // Ready - The deployment build was successful and the deployment is ready to be deployed - // Processing - The deployment is currently waiting to have a build triggered - // Building - The deployment is currently being built - ->addRule('status', [ - 'type' => self::TYPE_STRING, - 'description' => 'The build status. There are a few different types and each one means something different. \nFailed - The deployment build has failed. More details can usually be found in buildStderr\nReady - The deployment build was successful and the deployment is ready to be deployed\nProcessing - The deployment is currently waiting to have a build triggered\nBuilding - The deployment is currently being built', - 'default' => '', - 'example' => 'ready', - ]) - ->addRule('stdout', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stdout of the build.', - 'default' => '', - 'example' => '', - ]) - ->addRule('stderr', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stderr of the build.', - 'default' => '', - 'example' => '', - ]) - ->addRule('startTime', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'The deployment creation date in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('endTime', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'The time the build was finished in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('duration', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The build duration in seconds.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('size', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The code size in bytes.', - 'default' => 0, - 'example' => 128, - ]) - ; - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Build'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_BUILD; - } -} diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index f42ce6d334..2b14977a7e 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -52,7 +52,7 @@ class Deployment extends Model 'default' => '', 'example' => 'index.js', ]) - ->addRule('size', [ + ->addRule('sourceSize', [ 'type' => self::TYPE_INTEGER, 'description' => 'The code size in bytes.', 'default' => 0, @@ -100,7 +100,7 @@ class Deployment extends Model 'default' => '', 'example' => 'Compiling source files...', ]) - ->addRule('buildTime', [ + ->addRule('buildDuration', [ 'type' => self::TYPE_INTEGER, 'description' => 'The current build time in seconds.', 'default' => 0, diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 472d6f430e..c3adc25799 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -417,7 +417,7 @@ class FunctionsCustomServerTest extends Scope $lastDeployment = $deployments['body']['deployments'][0]; $this->assertNotEmpty($lastDeployment['$id']); - $this->assertEquals(0, $lastDeployment['size']); + $this->assertEquals(0, $lastDeployment['sourceSize']); $deploymentId = $lastDeployment['$id']; @@ -633,10 +633,10 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($largeTag['body']['$id']); $this->assertEquals(true, (new DatetimeValidator())->isValid($largeTag['body']['$createdAt'])); $this->assertEquals('index.php', $largeTag['body']['entrypoint']); - $this->assertGreaterThan(1024 * 1024 * 5, $largeTag['body']['size']); // ~7MB video file - $this->assertLessThan(1024 * 1024 * 10, $largeTag['body']['size']); // ~7MB video file + $this->assertGreaterThan(1024 * 1024 * 5, $largeTag['body']['sourceSize']); // ~7MB video file + $this->assertLessThan(1024 * 1024 * 10, $largeTag['body']['sourceSize']); // ~7MB video file - $deploymentSize = $largeTag['body']['size']; + $deploymentSize = $largeTag['body']['sourceSize']; $deploymentId = $largeTag['body']['$id']; $this->assertEventually(function () use ($functionId, $deploymentId, $deploymentSize) { @@ -644,7 +644,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployment['headers']['status-code']); $this->assertEquals('ready', $deployment['body']['status']); - $this->assertEquals($deploymentSize, $deployment['body']['size']); + $this->assertEquals($deploymentSize, $deployment['body']['sourceSize']); $this->assertGreaterThan(1024 * 1024 * 10, $deployment['body']['buildSize']); // ~7MB video file + 10MB sample file }, 500000, 1000); @@ -690,7 +690,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($deployments['body']['total'], 3); $this->assertIsArray($deployments['body']['deployments']); $this->assertCount(3, $deployments['body']['deployments']); - $this->assertArrayHasKey('size', $deployments['body']['deployments'][0]); + $this->assertArrayHasKey('sourceSize', $deployments['body']['deployments'][0]); $this->assertArrayHasKey('buildSize', $deployments['body']['deployments'][0]); $deployments = $this->listDeployments($functionId, [ @@ -711,24 +711,6 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($deployments['headers']['status-code'], 200); $this->assertCount(2, $deployments['body']['deployments']); - $deployments = $this->listDeployments($functionId, [ - 'queries' => [ - Query::equal('entrypoint', ['index.php'])->toString(), - ], - ]); - - $this->assertEquals($deployments['headers']['status-code'], 200); - $this->assertCount(3, $deployments['body']['deployments']); - - $deployments = $this->listDeployments($functionId, [ - 'queries' => [ - Query::equal('entrypoint', ['index.js'])->toString(), - ], - ]); - - $this->assertEquals($deployments['headers']['status-code'], 200); - $this->assertCount(0, $deployments['body']['deployments']); - $deployments = $this->listDeployments($functionId, [ 'search' => 'php-8.0' ]); @@ -779,7 +761,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', 10000)->toString(), + Query::greaterThan('sourceSize', 10000)->toString(), ], ] ); @@ -791,7 +773,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', 0)->toString(), + Query::greaterThan('sourceSize', 0)->toString(), ], ] ); @@ -803,7 +785,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', -100)->toString(), + Query::greaterThan('sourceSize', -100)->toString(), ], ] ); @@ -824,16 +806,16 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployments['headers']['status-code']); $this->assertGreaterThanOrEqual(1, $deployments['body']['total']); $this->assertNotEmpty($deployments['body']['deployments'][0]['$id']); - $this->assertNotEmpty($deployments['body']['deployments'][0]['size']); + $this->assertNotEmpty($deployments['body']['deployments'][0]['sourceSize']); $deploymentId = $deployments['body']['deployments'][0]['$id']; - $deploymentSize = $deployments['body']['deployments'][0]['size']; + $deploymentSize = $deployments['body']['deployments'][0]['sourceSize']; $deployments = $this->listDeployments( $functionId, [ 'queries' => [ - Query::equal('size', [$deploymentSize])->toString(), + Query::equal('sourceSize', [$deploymentSize])->toString(), ], ] ); @@ -850,7 +832,7 @@ class FunctionsCustomServerTest extends Scope if (!empty($matchingDeployment)) { $deployment = reset($matchingDeployment); - $this->assertEquals($deploymentSize, $deployment['size']); + $this->assertEquals($deploymentSize, $deployment['sourceSize']); } return $data; @@ -867,10 +849,10 @@ class FunctionsCustomServerTest extends Scope $deployment = $this->getDeployment($data['functionId'], $data['deploymentId']); $this->assertEquals(200, $deployment['headers']['status-code']); - $this->assertGreaterThan(0, $deployment['body']['buildTime']); + $this->assertGreaterThan(0, $deployment['body']['buildDuration']); $this->assertNotEmpty($deployment['body']['status']); $this->assertNotEmpty($deployment['body']['buildLogs']); - $this->assertArrayHasKey('size', $deployment['body']); + $this->assertArrayHasKey('sourceSize', $deployment['body']); $this->assertArrayHasKey('buildSize', $deployment['body']); /** diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 5c38a10472..121d40156e 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1568,7 +1568,7 @@ trait Base _id buildId entrypoint - size + buildSize status buildLogs } diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 891882b1f9..b961596fc6 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -635,7 +635,7 @@ class SitesCustomServerTest extends Scope $lastDeployment = $deployments['body']['deployments'][0]; $this->assertNotEmpty($lastDeployment['$id']); - $this->assertEquals(0, $lastDeployment['size']); + $this->assertEquals(0, $lastDeployment['sourceSize']); $deploymentId = $lastDeployment['$id']; @@ -849,7 +849,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals($deployments['body']['total'], 2); $this->assertIsArray($deployments['body']['deployments']); $this->assertCount(2, $deployments['body']['deployments']); - $this->assertArrayHasKey('size', $deployments['body']['deployments'][0]); + $this->assertArrayHasKey('sourceSize', $deployments['body']['deployments'][0]); $this->assertArrayHasKey('buildSize', $deployments['body']['deployments'][0]); $deployments = $this->listDeployments($siteId, [ @@ -910,7 +910,7 @@ class SitesCustomServerTest extends Scope $siteId, [ 'queries' => [ - Query::greaterThan('size', 10000)->toString(), + Query::greaterThan('sourceSize', 10000)->toString(), ], ] ); @@ -922,7 +922,7 @@ class SitesCustomServerTest extends Scope $siteId, [ 'queries' => [ - Query::greaterThan('size', 0)->toString(), + Query::greaterThan('sourceSize', 0)->toString(), ], ] ); @@ -934,7 +934,7 @@ class SitesCustomServerTest extends Scope $siteId, [ 'queries' => [ - Query::greaterThan('size', -100)->toString(), + Query::greaterThan('sourceSize', -100)->toString(), ], ] ); @@ -955,16 +955,16 @@ class SitesCustomServerTest extends Scope $this->assertEquals(200, $deployments['headers']['status-code']); $this->assertGreaterThanOrEqual(1, $deployments['body']['total']); $this->assertNotEmpty($deployments['body']['deployments'][0]['$id']); - $this->assertNotEmpty($deployments['body']['deployments'][0]['size']); + $this->assertNotEmpty($deployments['body']['deployments'][0]['sourceSize']); $deploymentId = $deployments['body']['deployments'][0]['$id']; - $deploymentSize = $deployments['body']['deployments'][0]['size']; + $deploymentSize = $deployments['body']['deployments'][0]['sourceSize']; $deployments = $this->listDeployments( $siteId, [ 'queries' => [ - Query::equal('size', [$deploymentSize])->toString(), + Query::equal('sourceSize', [$deploymentSize])->toString(), ], ] ); @@ -981,7 +981,7 @@ class SitesCustomServerTest extends Scope if (!empty($matchingDeployment)) { $deployment = reset($matchingDeployment); - $this->assertEquals($deploymentSize, $deployment['size']); + $this->assertEquals($deploymentSize, $deployment['sourceSize']); } $this->cleanupDeployment($siteId, $deploymentIdActive); @@ -1023,10 +1023,10 @@ class SitesCustomServerTest extends Scope $deployment = $this->getDeployment($siteId, $deploymentId); $this->assertEquals(200, $deployment['headers']['status-code']); - $this->assertGreaterThan(0, $deployment['body']['buildTime']); + $this->assertGreaterThan(0, $deployment['body']['buildDuration']); $this->assertNotEmpty($deployment['body']['status']); $this->assertNotEmpty($deployment['body']['buildLogs']); - $this->assertArrayHasKey('size', $deployment['body']); + $this->assertArrayHasKey('sourceSize', $deployment['body']); $this->assertArrayHasKey('buildSize', $deployment['body']); /**