mirror of
https://github.com/appwrite/appwrite
synced 2026-05-15 04:59:01 +00:00
Add all deployment endpoints for sites
This commit is contained in:
parent
a4bdc23aef
commit
9793cf4ece
9 changed files with 718 additions and 2 deletions
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Executor\Executor;
|
||||
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;
|
||||
|
||||
class CancelDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'cancelDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/build')
|
||||
->desc('Cancel deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.write') //TODO: Update the scope to sites later
|
||||
->label('audits.event', 'deployment.update')
|
||||
->label('audits.resource', 'site/{request.siteId}')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'updateDeploymentBuild')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_BUILD)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $queueForEvents)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
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'
|
||||
]));
|
||||
}
|
||||
|
||||
$dbForProject->purgeCachedDocument('deployments', $deployment->getId());
|
||||
|
||||
try {
|
||||
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
|
||||
$executor->deleteRuntime($project->getId(), $deploymentId . "-build");
|
||||
} catch (\Throwable $th) {
|
||||
// Don't throw if the deployment doesn't exist
|
||||
if ($th->getCode() !== 404) {
|
||||
throw $th;
|
||||
}
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
->setParam('siteId', $site->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$response->dynamic($build, Response::MODEL_BUILD);
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,6 @@ class CreateDeployment extends Action
|
|||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('project')
|
||||
->inject('deviceForSites')
|
||||
->inject('deviceForFunctions') // TODO: Remove this later once volume is added to executor
|
||||
->inject('deviceForLocal')
|
||||
|
|
@ -73,7 +72,7 @@ class CreateDeployment extends Action
|
|||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, ?string $installCommand, ?string $buildCommand, ?string $outputDirectory, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds)
|
||||
public function action(string $siteId, ?string $installCommand, ?string $buildCommand, ?string $outputDirectory, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds)
|
||||
{
|
||||
$activate = \strval($activate) === 'true' || \strval($activate) === '1';
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
class DeleteDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'deleteDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId')
|
||||
->desc('Delete deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.write') //TODO: Update the scope to sites later
|
||||
->label('event', 'sites.[siteId].deployments.[deploymentId].delete')
|
||||
->label('audits.event', 'deployment.delete')
|
||||
->label('audits.resource', 'site/{request.siteId}')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'deleteDeployment')
|
||||
->label('sdk.description', '/docs/references/sites/delete-deployment.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForDeletes')
|
||||
->inject('queueForEvents')
|
||||
->inject('deviceForSites')
|
||||
->inject('deviceForFunctions') //TODO: remove it later
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Device $deviceForSites, Device $deviceForFunctions)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $site->getId()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB');
|
||||
}
|
||||
|
||||
if (!empty($deployment->getAttribute('path', ''))) {
|
||||
if (!($deviceForFunctions->delete($deployment->getAttribute('path', '')))) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage');
|
||||
}
|
||||
}
|
||||
|
||||
if ($site->getAttribute('deployment') === $deployment->getId()) { // Reset site deployment
|
||||
$site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [
|
||||
'deployment' => '',
|
||||
'deploymentInternalId' => '',
|
||||
])));
|
||||
}
|
||||
|
||||
$queueForEvents
|
||||
->setParam('siteId', $site->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($deployment);
|
||||
|
||||
$response->noContent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Swoole\Request;
|
||||
|
||||
class DownloadDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'downloadDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/download')
|
||||
->desc('Download deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.read') //TODO: Update the scope to sites later
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'getDeploymentDownload')
|
||||
->label('sdk.description', '/docs/references/sites/get-deployment-download.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', '*/*')
|
||||
->label('sdk.methodType', 'location')
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('request')
|
||||
->inject('dbForProject')
|
||||
->inject('deviceForSites')
|
||||
->inject('deviceForFunctions') //TODO: Remove this later
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Request $request, Database $dbForProject, Device $deviceForSites, Device $deviceForFunctions)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $site->getId()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $deployment->getAttribute('path', '');
|
||||
if (!$deviceForFunctions->exists($path)) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response
|
||||
->setContentType('application/gzip')
|
||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
|
||||
->addHeader('X-Peak', \memory_get_peak_usage())
|
||||
->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '.tar.gz"');
|
||||
|
||||
$size = $deviceForFunctions->getFileSize($path);
|
||||
$rangeHeader = $request->getHeader('range');
|
||||
|
||||
if (!empty($rangeHeader)) {
|
||||
$start = $request->getRangeStart();
|
||||
$end = $request->getRangeEnd();
|
||||
$unit = $request->getRangeUnit();
|
||||
|
||||
if ($end === null) {
|
||||
$end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1));
|
||||
}
|
||||
|
||||
if ($unit !== 'bytes' || $start >= $end || $end >= $size) {
|
||||
throw new Exception(Exception::STORAGE_INVALID_RANGE);
|
||||
}
|
||||
|
||||
$response
|
||||
->addHeader('Accept-Ranges', 'bytes')
|
||||
->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size)
|
||||
->addHeader('Content-Length', $end - $start + 1)
|
||||
->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT);
|
||||
|
||||
$response->send($deviceForFunctions->read($path, $start, ($end - $start + 1)));
|
||||
}
|
||||
|
||||
if ($size > APP_STORAGE_READ_BUFFER) {
|
||||
for ($i = 0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) {
|
||||
$response->chunk(
|
||||
$deviceForFunctions->read(
|
||||
$path,
|
||||
($i * MAX_OUTPUT_CHUNK_SIZE),
|
||||
min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE))
|
||||
),
|
||||
(($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response->send($deviceForFunctions->read($path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class GetDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'getDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId')
|
||||
->desc('Get deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.read') //TODO: Update the scope to sites later
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'getDeployment')
|
||||
->label('sdk.description', '/docs/references/sites/get-deployment.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_DEPLOYMENT)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $site->getId()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Deployments;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Query\Cursor;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class ListDeployments extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'listDeployments';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments')
|
||||
->desc('List deployments')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.read') //TODO: Update the scope to sites later
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'listDeployments')
|
||||
->label('sdk.description', '/docs/references/sites/list-deployments.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Deployments::ALLOWED_ATTRIBUTES), true)
|
||||
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, array $queries, string $search, Response $response, Database $dbForProject)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
} catch (QueryException $e) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
$queries[] = Query::search('search', $search);
|
||||
}
|
||||
|
||||
// Set resource queries
|
||||
$queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]);
|
||||
$queries[] = Query::equal('resourceType', ['sites']);
|
||||
|
||||
/**
|
||||
* Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries
|
||||
*/
|
||||
$cursor = \array_filter($queries, function ($query) {
|
||||
return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]);
|
||||
});
|
||||
$cursor = reset($cursor);
|
||||
if ($cursor) {
|
||||
/** @var Query $cursor */
|
||||
|
||||
$validator = new Cursor();
|
||||
if (!$validator->isValid($cursor)) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$deploymentId = $cursor->getValue();
|
||||
$cursorDocument = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Deployment '{$deploymentId}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$cursor->setValue($cursorDocument);
|
||||
}
|
||||
|
||||
$filterQueries = Query::groupByType($queries)['filters'];
|
||||
|
||||
$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,
|
||||
]), Response::MODEL_DEPLOYMENT_LIST);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
class RebuildDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'rebuildDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/build')
|
||||
->desc('Rebuild deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.write') //TODO: Update the scope to sites later
|
||||
->label('event', 'sites.[siteId].deployments.[deploymentId].update')
|
||||
->label('audits.event', 'deployment.update')
|
||||
->label('audits.resource', 'site/{request.siteId}')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'createBuild')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
|
||||
->label('sdk.response.model', Response::MODEL_NONE)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForBuilds')
|
||||
->inject('deviceForSites')
|
||||
->inject('deviceForFunctions') //TODO: remove it later
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Build $queueForBuilds, Device $deviceForSites, Device $deviceForFunctions)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
if ($site->isEmpty()) {
|
||||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $deployment->getAttribute('path');
|
||||
if (empty($path) || !$deviceForFunctions->exists($path)) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deploymentId = ID::unique();
|
||||
|
||||
$destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION));
|
||||
$deviceForFunctions->transfer($path, $destination, $deviceForFunctions);
|
||||
|
||||
$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', ''),
|
||||
'search' => implode(' ', [$deploymentId]),
|
||||
]));
|
||||
|
||||
$queueForBuilds
|
||||
->setType(BUILD_TYPE_DEPLOYMENT)
|
||||
->setResource($site)
|
||||
->setDeployment($deployment);
|
||||
|
||||
$queueForEvents
|
||||
->setParam('siteId', $site->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$response->noContent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
|
||||
class UpdateDeployment extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'updateDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId')
|
||||
->desc('Update deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'functions.write') //TODO: Update the scope to sites later
|
||||
->label('event', 'sites.[siteId].deployments.[deploymentId].update')
|
||||
->label('audits.event', 'deployment.update')
|
||||
->label('audits.resource', 'site/{request.siteId}')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'sites')
|
||||
->label('sdk.method', 'updateDeployment')
|
||||
->label('sdk.description', '/docs/references/sites/update-site-deployment.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_SITE)
|
||||
->param('siteId', '', new UID(), 'Site ID.')
|
||||
->param('deploymentId', '', new UID(), 'Deployment ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('queueForEvents')
|
||||
->inject('dbForConsole')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForConsole)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception(Exception::BUILD_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->getAttribute('status') !== 'ready') {
|
||||
throw new Exception(Exception::BUILD_NOT_READY);
|
||||
}
|
||||
|
||||
$site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [
|
||||
'deploymentInternalId' => $deployment->getInternalId(),
|
||||
'deploymentId' => $deployment->getId(),
|
||||
])));
|
||||
|
||||
$queueForEvents
|
||||
->setParam('siteId', $site->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$response->dynamic($site, Response::MODEL_SITE);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,14 @@
|
|||
|
||||
namespace Appwrite\Platform\Modules\Sites\Services;
|
||||
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\CancelDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\CreateDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\DeleteDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\DownloadDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\GetDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\ListDeployments;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\RebuildDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\UpdateDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Sites\CreateSite;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Sites\GetSite;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Sites\ListFrameworks;
|
||||
|
|
@ -21,5 +28,12 @@ class Http extends Service
|
|||
$this->addAction(UpdateSite::getName(), new UpdateSite());
|
||||
$this->addAction(ListFrameworks::getName(), new ListFrameworks());
|
||||
$this->addAction(CreateDeployment::getName(), new CreateDeployment());
|
||||
$this->addAction(GetDeployment::getName(), new GetDeployment());
|
||||
$this->addAction(ListDeployments::getName(), new ListDeployments());
|
||||
$this->addAction(UpdateDeployment::getName(), new UpdateDeployment());
|
||||
$this->addAction(DeleteDeployment::getName(), new DeleteDeployment());
|
||||
$this->addAction(DownloadDeployment::getName(), new DownloadDeployment());
|
||||
$this->addAction(RebuildDeployment::getName(), new RebuildDeployment());
|
||||
$this->addAction(CancelDeployment::getName(), new CancelDeployment());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue