Merge pull request #8877 from appwrite/feat-preview-deployments

Feat: Implement preview deployments
This commit is contained in:
Matej Bačo 2024-10-27 21:25:27 +01:00 committed by GitHub
commit fd02ca00f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 80 additions and 14 deletions

View file

@ -99,10 +99,11 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
$type = $rule->getAttribute('resourceType');
if ($type === 'function' || $type === 'site') {
if ($type === 'function' || $type === 'site' || $type === 'deployment') {
$resourceCollection = match($type) {
'function' => 'functions',
'site' => 'sites'
'site' => 'sites',
'deployment' => 'deployments',
};
$utopia->getRoute()?->label('sdk.namespace', 'functions');
@ -136,7 +137,12 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
/** @var Database $dbForProject */
$dbForProject = $getProjectDB($project);
$resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
if ($resourceCollection === 'deployments') {
$subResource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
$resource = Authorization::skip(fn () => $dbForProject->getDocument($subResource->getAttribute('resourceType'), $subResource->getAttribute('resourceId')));
} else {
$resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId));
}
if ($resource->isEmpty() || !$resource->getAttribute('enabled')) {
throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND);
@ -144,7 +150,8 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
$version = match($type) {
'function' => $resource->getAttribute('version', 'v2'),
'site' => 'v4'
'site' => 'v4',
'deployment' => 'v4'
};
$runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []);
@ -153,6 +160,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
$runtime = match($type) {
'function' => $runtimes[$resource->getAttribute('runtime')] ?? null,
'site' => $runtimes[$resource->getAttribute('serveRuntime')] ?? null,
'deployment' => $runtimes[$resource->getAttribute('serveRuntime')] ?? null,
default => null
};
@ -162,7 +170,8 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
$deploymentId = match($type) {
'function' => $resource->getAttribute('deployment', ''),
'site' => $resource->getAttribute('deploymentId', '')
'site' => $resource->getAttribute('deploymentId', ''),
'deployment' => $subResource->getId()
};
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $deploymentId));
@ -321,11 +330,13 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
try {
$version = match($type) {
'function' => $resource->getAttribute('version', 'v2'),
'site' => 'v4'
'site' => 'v4',
'deployment' => 'v4'
};
$entrypoint = match($type) {
'function' => $deployment->getAttribute('entrypoint', ''),
'site' => ''
'site' => '',
'deployment' => ''
};
$runtimeEntrypoint = match ($version) {
'v2' => '',

View file

@ -797,7 +797,7 @@ $image = $this->getParam('image', '');
<<: *x-logging
restart: unless-stopped
stop_signal: SIGINT
image: openruntimes/executor:0.6.25
image: openruntimes/executor:0.6.26
networks:
- appwrite
- runtimes

View file

@ -481,6 +481,7 @@ services:
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- _APP_DATABASE_SHARED_TABLES
- _APP_DOMAIN_SITES
appwrite-worker-certificates:
entrypoint: worker-certificates
@ -878,7 +879,7 @@ services:
hostname: exc1
<<: *x-logging
stop_signal: SIGINT
image: openruntimes/executor:0.6.25
image: openruntimes/executor:0.6.26
restart: unless-stopped
networks:
- appwrite

View file

@ -692,6 +692,31 @@ class Builds extends Action
}
}
// Preview deployments for sites
if ($resource->getCollection() === 'sites') {
$ruleId = ID::unique();
$deploymentId = $deployment->getId();
$projectId = $project->getId();
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = "{$deploymentId}-{$projectId}.{$sitesDomain}";
$rule = Authorization::skip(
fn () => $dbForConsole->createDocument('rules', new Document([
'$id' => $ruleId,
'projectId' => $project->getId(),
'projectInternalId' => $project->getInternalId(),
'domain' => $domain,
'resourceType' => 'deployment',
'resourceId' => $deployment->getId(),
'resourceInternalId' => $deployment->getInternalId(),
'status' => 'verified',
'certificateId' => '',
]))
);
}
if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') {
Console::info('Build has been canceled');
return;

View file

@ -3,8 +3,10 @@
namespace Appwrite\Platform\Modules\Sites\Http\Deployments;
use Appwrite\Extend\Exception;
use Appwrite\Query;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@ -37,10 +39,11 @@ class GetDeployment extends Action
->param('deploymentId', '', new UID(), 'Deployment ID.')
->inject('response')
->inject('dbForProject')
->inject('dbForConsole')
->callback([$this, 'action']);
}
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject)
public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject, Database $dbForConsole)
{
$site = $dbForProject->getDocument('sites', $siteId);
@ -65,6 +68,15 @@ class GetDeployment extends Action
$deployment->setAttribute('buildSize', $build->getAttribute('size', 0));
$deployment->setAttribute('size', $deployment->getAttribute('size', 0));
$rule = Authorization::skip(fn () => $dbForConsole->findOne('rules', [
Query::equal("resourceType", ["deployment"]),
Query::equal("resourceId", [$deployment->getId()])
]));
if (!empty($rule)) {
$deployment->setAttribute('domain', $rule->getAttribute('domain', ''));
}
$response->dynamic($deployment, Response::MODEL_DEPLOYMENT);
}
}

View file

@ -9,6 +9,7 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Query\Cursor;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
@ -44,10 +45,11 @@ class ListDeployments extends Action
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('response')
->inject('dbForProject')
->inject('dbForConsole')
->callback([$this, 'action']);
}
public function action(string $siteId, array $queries, string $search, Response $response, Database $dbForProject)
public function action(string $siteId, array $queries, string $search, Response $response, Database $dbForProject, Database $dbForConsole)
{
$site = $dbForProject->getDocument('sites', $siteId);
@ -106,6 +108,15 @@ class ListDeployments extends Action
$result->setAttribute('buildTime', $build->getAttribute('duration', 0));
$result->setAttribute('buildSize', $build->getAttribute('size', 0));
$result->setAttribute('size', $result->getAttribute('size', 0));
$rule = Authorization::skip(fn () => $dbForConsole->findOne('rules', [
Query::equal("resourceType", ["deployment"]),
Query::equal("resourceId", [$result->getId()])
]));
if (!empty($rule)) {
$result->setAttribute('domain', $rule->getAttribute('domain', ''));
}
}
$response->dynamic(new Document([

View file

@ -66,8 +66,8 @@ class CreateSite extends Base
->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true)
->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true)
->param('subdomain', '', new CustomId(), 'Unique custom sub-domain. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true)
->param('buildRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use during build step.', true)
->param('serveRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use when serving site.', true)
->param('buildRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use during build step.')
->param('serveRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use when serving site.')
->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true)
->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the site.', true)
->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true)
@ -104,7 +104,7 @@ class CreateSite extends Base
if (!empty($sitesDomain)) {
$ruleId = ID::unique();
$routeSubdomain = $subdomain ?? ID::unique();
$routeSubdomain = $subdomain ?: ID::unique();
$domain = "{$routeSubdomain}.{$sitesDomain}";
$subdomain = Authorization::skip(fn () => $dbForConsole->findOne('rules', [

View file

@ -94,6 +94,12 @@ class Deployment extends Model
'default' => 0,
'example' => 128,
])
->addRule('domain', [
'type' => self::TYPE_STRING,
'description' => 'Preview domain.',
'default' => '',
'example' => 'deploy1-project1.appwrite.site',
])
->addRule('providerRepositoryName', [
'type' => self::TYPE_STRING,
'description' => 'The name of the vcs provider repository',