Merge branch 'feat-1.8.x-new-schema' into feat-custom-start-commands

This commit is contained in:
Matej Bačo
2025-11-24 15:41:52 +01:00
17 changed files with 378 additions and 76 deletions
@@ -164,7 +164,7 @@ class Create extends Base
$version = $function->getAttribute('version', 'v2');
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
$spec = Config::getParam('specifications')[$function->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$spec = Config::getParam('specifications')[$function->getAttribute('runtimeSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null;
@@ -93,12 +93,18 @@ class Create extends Base
->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function.', true)
->param('providerSilentMode', false, new Boolean(), 'Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.', true)
->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true)
->param('specification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
->param('buildSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function and builds.', true, ['plan'])
), 'Build specification for the function deployments.', true, ['plan'])
->param('runtimeSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function executions.', true, ['plan'])
->param('templateRepository', '', new Text(128, 0), 'Repository name of the template.', true, deprecated: true)
->param('templateOwner', '', new Text(128, 0), 'The name of the owner of the template.', true, deprecated: true)
->param('templateRootDirectory', '', new Text(128, 0), 'Path to function code in the template repo.', true, deprecated: true)
@@ -136,7 +142,8 @@ class Create extends Base
string $providerBranch,
bool $providerSilentMode,
string $providerRootDirectory,
string $specification,
string $buildSpecification,
string $runtimeSpecification,
string $templateRepository,
string $templateOwner,
string $templateRootDirectory,
@@ -231,7 +238,8 @@ class Create extends Base
'providerBranch' => $providerBranch,
'providerRootDirectory' => $providerRootDirectory,
'providerSilentMode' => $providerSilentMode,
'specification' => $specification
'buildSpecification' => $buildSpecification,
'runtimeSpecification' => $runtimeSpecification,
]));
} catch (DuplicateException) {
throw new Exception(Exception::FUNCTION_ALREADY_EXISTS);
@@ -89,12 +89,18 @@ class Update extends Base
->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function', true)
->param('providerSilentMode', false, new Boolean(), 'Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.', true)
->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true)
->param('specification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
->param('buildSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function and builds.', true, ['plan'])
), 'Build specification for the function deployments.', true, ['plan'])
->param('runtimeSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function executions.', true, ['plan'])
->inject('request')
->inject('response')
->inject('dbForProject')
@@ -125,7 +131,8 @@ class Update extends Base
string $providerBranch,
bool $providerSilentMode,
string $providerRootDirectory,
string $specification,
string $buildSpecification,
string $runtimeSpecification,
Request $request,
Response $response,
Database $dbForProject,
@@ -235,13 +242,22 @@ class Update extends Base
}
// Enforce Cold Start if spec limits change.
if ($function->getAttribute('specification') !== $specification && !empty($function->getAttribute('deploymentId'))) {
try {
$executor->deleteRuntime($project->getId(), $function->getAttribute('deploymentId'));
} catch (\Throwable $th) {
// Don't throw if the deployment doesn't exist
if ($th->getCode() !== 404) {
throw $th;
if (!empty($function->getAttribute('deploymentId'))) {
$specsChanged = false;
if ($function->getAttribute('runtimeSpecification') !== $runtimeSpecification) {
$specsChanged = true;
} elseif ($function->getAttribute('buildSpecification') !== $buildSpecification) {
$specsChanged = true;
}
if ($specsChanged) {
try {
$executor->deleteRuntime($project->getId(), $function->getAttribute('deploymentId'));
} catch (\Throwable $th) {
// Don't throw if the deployment doesn't exist
if ($th->getCode() !== 404) {
throw $th;
}
}
}
}
@@ -267,7 +283,8 @@ class Update extends Base
'providerBranch' => $providerBranch,
'providerRootDirectory' => $providerRootDirectory,
'providerSilentMode' => $providerSilentMode,
'specification' => $specification,
'buildSpecification' => $buildSpecification,
'runtimeSpecification' => $runtimeSpecification,
'search' => implode(' ', [$functionId, $name, $runtime]),
])));
@@ -252,7 +252,7 @@ class Builds extends Action
$version = $this->getVersion($resource);
$runtime = $this->getRuntime($resource, $version);
$spec = Config::getParam('specifications')[$resource->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$spec = Config::getParam('specifications')[$resource->getAttribute('buildSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
if ($resource->getCollection() === 'functions' && \is_null($runtime)) {
throw new \Exception('Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported');
@@ -1354,7 +1354,7 @@ class Builds extends Action
protected function sendUsage(Document $resource, Document $deployment, Document $project, StatsUsage $queue): void
{
$spec = Config::getParam('specifications')[$resource->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$spec = Config::getParam('specifications')[$resource->getAttribute('buildSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
switch ($deployment->getAttribute('status')) {
case 'ready':
@@ -79,12 +79,18 @@ class Create extends Base
->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true)
->param('providerSilentMode', false, new Boolean(), 'Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.', true)
->param('providerRootDirectory', '', new Text(128, 0), 'Path to site code in the linked repo.', true)
->param('specification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
->param('buildSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Framework specification for the site and builds.', true, ['plan'])
), 'Build specification for the site deployments.', true, ['plan'])
->param('runtimeSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function SSR executions.', true, ['plan'])
->inject('response')
->inject('dbForProject')
->inject('project')
@@ -112,7 +118,8 @@ class Create extends Base
string $providerBranch,
bool $providerSilentMode,
string $providerRootDirectory,
string $specification,
string $buildSpecification,
string $runtimeSpecification,
Response $response,
Database $dbForProject,
Document $project,
@@ -164,7 +171,8 @@ class Create extends Base
'providerBranch' => $providerBranch,
'providerRootDirectory' => $providerRootDirectory,
'providerSilentMode' => $providerSilentMode,
'specification' => $specification,
'buildSpecification' => $buildSpecification,
'runtimeSpecification' => $runtimeSpecification,
'buildRuntime' => $buildRuntime,
'adapter' => $adapter,
]));
@@ -83,12 +83,18 @@ class Update extends Base
->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true)
->param('providerSilentMode', false, new Boolean(), 'Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.', true)
->param('providerRootDirectory', '', new Text(128, 0), 'Path to site code in the linked repo.', true)
->param('specification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
->param('buildSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Framework specification for the site and builds.', true, ['plan'])
), 'Build specification for the site deployments.', true, ['plan'])
->param('runtimeSpecification', fn (array $plan) => $this->getDefaultSpecification($plan), fn (array $plan) => new Specification(
$plan,
Config::getParam('specifications', []),
System::getEnv('_APP_COMPUTE_CPUS', 0),
System::getEnv('_APP_COMPUTE_MEMORY', 0)
), 'Runtime specification for the function SSR executions.', true, ['plan'])
->inject('request')
->inject('response')
->inject('dbForProject')
@@ -120,7 +126,8 @@ class Update extends Base
string $providerBranch,
bool $providerSilentMode,
string $providerRootDirectory,
string $specification,
string $buildSpecification,
string $runtimeSpecification,
Request $request,
Response $response,
Database $dbForProject,
@@ -236,14 +243,22 @@ class Update extends Base
$live = false;
}
// Enforce Cold Start if spec limits change.
if ($site->getAttribute('specification') !== $specification && !empty($site->getAttribute('deploymentId'))) {
try {
$executor->deleteRuntime($project->getId(), $site->getAttribute('deploymentId'));
} catch (\Throwable $th) {
// Don't throw if the deployment doesn't exist
if ($th->getCode() !== 404) {
throw $th;
if (!empty($site->getAttribute('deploymentId'))) {
$specsChanged = false;
if ($site->getAttribute('runtimeSpecification') !== $runtimeSpecification) {
$specsChanged = true;
} elseif ($site->getAttribute('buildSpecification') !== $buildSpecification) {
$specsChanged = true;
}
if ($specsChanged) {
try {
$executor->deleteRuntime($project->getId(), $site->getAttribute('deploymentId'));
} catch (\Throwable $th) {
// Don't throw if the deployment doesn't exist
if ($th->getCode() !== 404) {
throw $th;
}
}
}
}
@@ -267,7 +282,8 @@ class Update extends Base
'providerBranch' => $providerBranch,
'providerRootDirectory' => $providerRootDirectory,
'providerSilentMode' => $providerSilentMode,
'specification' => $specification,
'buildSpecification' => $buildSpecification,
'runtimeSpecification' => $runtimeSpecification,
'search' => implode(' ', [$siteId, $name, $framework]),
'buildRuntime' => $buildRuntime,
'adapter' => $adapter,
+1 -1
View File
@@ -356,7 +356,7 @@ class Functions extends Action
$user ??= new Document();
$functionId = $function->getId();
$deploymentId = $function->getAttribute('deploymentId', '');
$spec = Config::getParam('specifications')[$function->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$spec = Config::getParam('specifications')[$function->getAttribute('runtimeSpecification', APP_COMPUTE_SPECIFICATION_DEFAULT)];
$log->addTag('deploymentId', $deploymentId);
+18 -1
View File
@@ -6,7 +6,7 @@ use Appwrite\Utopia\Request\Filter;
class V21 extends Filter
{
// Convert 1.8.0 params to 1.8.1
// Convert 1.8.0 params to 1.9.0
public function parse(array $content, string $model): array
{
switch ($model) {
@@ -14,6 +14,12 @@ class V21 extends Filter
case 'sites.createTemplateDeployment':
$content = $this->convertVersionToTypeAndReference($content);
break;
case 'functions.create':
case 'sites.create':
case 'functions.update':
case 'sites.update':
$content = $this->convertSpecs($content);
break;
}
return $content;
}
@@ -31,4 +37,15 @@ class V21 extends Filter
}
return $content;
}
protected function convertSpecs(array $content): array
{
if (!empty($content['specification'])) {
$content['buildSpecification'] = $content['specification'];
$content['runtimeSpecification'] = $content['specification'];
unset($content['specification']);
}
return $content;
}
}
@@ -0,0 +1,51 @@
<?php
namespace Appwrite\Utopia\Response\Filters;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Filter;
// Convert 1.9 Data format to 1.8 format
class V21 extends Filter
{
public function parse(array $content, string $model): array
{
$parsedResponse = $content;
return match ($model) {
Response::MODEL_SITE => $this->parseSite($content),
Response::MODEL_SITE_LIST => $this->handleList(
$content,
"sites",
fn ($item) => $this->parseSite($item),
),
Response::MODEL_FUNCTION => $this->parseFunction($content),
Response::MODEL_FUNCTION_LIST => $this->handleList(
$content,
"functions",
fn ($item) => $this->parseFunction($item),
),
default => $parsedResponse,
};
}
protected function parseSite(array $content): array
{
$content = $this->parseSpecs($content);
return $content;
}
protected function parseFunction(array $content): array
{
$content = $this->parseSpecs($content);
return $content;
}
protected function parseSpecs(array $content): array
{
$content['specification'] = $content['buildSpecification'] ?? null;
unset($content['buildSpecification']);
unset($content['runtimeSpecification']);
return $content;
}
}
+8 -2
View File
@@ -176,9 +176,15 @@ class Func extends Model
'default' => false,
'example' => false,
])
->addRule('specification', [
->addRule('buildSpecification', [
'type' => self::TYPE_STRING,
'description' => 'Machine specification for builds and executions.',
'description' => 'Machine specification for deployment builds.',
'default' => APP_COMPUTE_SPECIFICATION_DEFAULT,
'example' => APP_COMPUTE_SPECIFICATION_DEFAULT,
])
->addRule('runtimeSpecification', [
'type' => self::TYPE_STRING,
'description' => 'Machine specification for executions.',
'default' => APP_COMPUTE_SPECIFICATION_DEFAULT,
'example' => APP_COMPUTE_SPECIFICATION_DEFAULT,
])
+8 -2
View File
@@ -167,9 +167,15 @@ class Site extends Model
'default' => false,
'example' => false,
])
->addRule('specification', [
->addRule('buildSpecification', [
'type' => self::TYPE_STRING,
'description' => 'Machine specification for builds and executions.',
'description' => 'Machine specification for deployment builds.',
'default' => APP_COMPUTE_SPECIFICATION_DEFAULT,
'example' => APP_COMPUTE_SPECIFICATION_DEFAULT,
])
->addRule('runtimeSpecification', [
'type' => self::TYPE_STRING,
'description' => 'Machine specification for SSR executions.',
'default' => APP_COMPUTE_SPECIFICATION_DEFAULT,
'example' => APP_COMPUTE_SPECIFICATION_DEFAULT,
])