Merge branch 'feat-sites' into chore-add-test-for-empty-source

This commit is contained in:
Khushboo Verma
2025-03-19 16:16:25 +05:30
27 changed files with 396 additions and 111 deletions
+7
View File
@@ -0,0 +1,7 @@
reviews:
auto_review:
base_branches:
- main
- 1.6.x
- 1.7.x
- feat-sites # temporary until merged to 1.7.x
+8
View File
@@ -122,6 +122,14 @@ jobs:
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose up -d
sleep 10
- name: Wait for Open Runtimes
timeout-minutes: 3
run: |
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
echo "Waiting for Executor to come online"
sleep 1
done
- name: Run General Tests
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/General --debug
+62
View File
@@ -579,6 +579,17 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,
@@ -1003,6 +1014,39 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('deploymentScreenshotLight'), // File ID from 'screenshots' Console bucket
'type' => Database::VAR_STRING,
'format' => '',
'size' => 32,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('deploymentScreenshotDark'), // File ID from 'screenshots' Console bucket
'type' => Database::VAR_STRING,
'format' => '',
'size' => 32,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,
@@ -1550,6 +1594,17 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('totalSize'),
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('status'),
'type' => Database::VAR_STRING,
@@ -1620,6 +1675,13 @@ return [
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_totalSize'),
'type' => Database::INDEX_KEY,
'attributes' => ['totalSize'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => ID::custom('_key_buildDuration'),
'type' => Database::INDEX_KEY,
+12
View File
@@ -19,6 +19,7 @@ return [
'analog' => [
'key' => 'analog',
'name' => 'Analog',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/analog/bundle.sh',
@@ -44,6 +45,7 @@ return [
'angular' => [
'key' => 'angular',
'name' => 'Angular',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/angular/bundle.sh',
@@ -69,6 +71,7 @@ return [
'nextjs' => [
'key' => 'nextjs',
'name' => 'Next.js',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/next-js/bundle.sh',
@@ -93,6 +96,7 @@ return [
'react' => [
'key' => 'react',
'name' => 'React',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -109,6 +113,7 @@ return [
'nuxt' => [
'key' => 'nuxt',
'name' => 'Nuxt',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/nuxt/bundle.sh',
@@ -133,6 +138,7 @@ return [
'vue' => [
'key' => 'vue',
'name' => 'Vue.js',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -149,6 +155,7 @@ return [
'sveltekit' => [
'key' => 'sveltekit',
'name' => 'SvelteKit',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/sveltekit/bundle.sh',
@@ -173,6 +180,7 @@ return [
'astro' => [
'key' => 'astro',
'name' => 'Astro',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/astro/bundle.sh',
@@ -197,6 +205,7 @@ return [
'remix' => [
'key' => 'remix',
'name' => 'Remix',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'bundleCommand' => 'sh /usr/local/server/helpers/remix/bundle.sh',
@@ -221,6 +230,7 @@ return [
'flutter' => [
'key' => 'flutter',
'name' => 'Flutter',
'screenshotSleep' => 5000,
'buildRuntime' => 'flutter-3.29',
'runtimes' => getVersions($templateRuntimes['FLUTTER']['versions'], 'flutter'),
'adapters' => [
@@ -236,6 +246,7 @@ return [
'vite' => [
'key' => 'vite',
'name' => 'Vite',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
@@ -251,6 +262,7 @@ return [
'other' => [
'key' => 'other',
'name' => 'Other',
'screenshotSleep' => 3000,
'buildRuntime' => 'node-22',
'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'),
'adapters' => [
+1 -1
View File
@@ -73,7 +73,7 @@
"utopia-php/swoole": "0.8.*",
"utopia-php/system": "0.9.*",
"utopia-php/telemetry": "0.1.*",
"utopia-php/vcs": "0.9.*",
"utopia-php/vcs": "0.10.*",
"utopia-php/websocket": "0.1.*",
"matomo/device-detector": "6.1.*",
"dragonmantank/cron-expression": "3.3.2",
Generated
+29 -30
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "566b9b71f179c9ff6368dbd353bc20d2",
"content-hash": "eca74b44aa6dc476aa8056344e87f363",
"packages": [
{
"name": "adhocore/jwt",
@@ -3761,16 +3761,16 @@
},
{
"name": "utopia-php/detector",
"version": "0.1.1",
"version": "0.1.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/detector.git",
"reference": "5dcabbfcf99731f3a37d86b7cb1e93c968baf64b"
"reference": "8617ea205738743ef3363ad95791139e82ae44d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/detector/zipball/5dcabbfcf99731f3a37d86b7cb1e93c968baf64b",
"reference": "5dcabbfcf99731f3a37d86b7cb1e93c968baf64b",
"url": "https://api.github.com/repos/utopia-php/detector/zipball/8617ea205738743ef3363ad95791139e82ae44d5",
"reference": "8617ea205738743ef3363ad95791139e82ae44d5",
"shasum": ""
},
"require": {
@@ -3800,9 +3800,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/detector/issues",
"source": "https://github.com/utopia-php/detector/tree/0.1.1"
"source": "https://github.com/utopia-php/detector/tree/0.1.2"
},
"time": "2025-03-08T22:25:49+00:00"
"time": "2025-03-11T13:01:25+00:00"
},
{
"name": "utopia-php/domains",
@@ -4805,16 +4805,16 @@
},
{
"name": "utopia-php/telemetry",
"version": "0.1.0",
"version": "0.1.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/telemetry.git",
"reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80"
"reference": "437f0021777f0e575dfb9e8a1a081b3aed75e33f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/telemetry/zipball/d35f2f0632f4ee0be63fb7ace6a94a6adda71a80",
"reference": "d35f2f0632f4ee0be63fb7ace6a94a6adda71a80",
"url": "https://api.github.com/repos/utopia-php/telemetry/zipball/437f0021777f0e575dfb9e8a1a081b3aed75e33f",
"reference": "437f0021777f0e575dfb9e8a1a081b3aed75e33f",
"shasum": ""
},
"require": {
@@ -4835,7 +4835,7 @@
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\": "src/"
"Utopia\\Telemetry\\": "src/Telemetry"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -4849,22 +4849,22 @@
],
"support": {
"issues": "https://github.com/utopia-php/telemetry/issues",
"source": "https://github.com/utopia-php/telemetry/tree/0.1.0"
"source": "https://github.com/utopia-php/telemetry/tree/0.1.1"
},
"time": "2024-11-13T10:29:53+00:00"
"time": "2025-03-17T11:57:52+00:00"
},
{
"name": "utopia-php/vcs",
"version": "0.9.4",
"version": "0.10.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/vcs.git",
"reference": "1a8d280b176acc99ea8d9e7364b8767cbb206b4a"
"reference": "6be02650cc361764900ade8c129f309df263eb74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/1a8d280b176acc99ea8d9e7364b8767cbb206b4a",
"reference": "1a8d280b176acc99ea8d9e7364b8767cbb206b4a",
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/6be02650cc361764900ade8c129f309df263eb74",
"reference": "6be02650cc361764900ade8c129f309df263eb74",
"shasum": ""
},
"require": {
@@ -4882,8 +4882,7 @@
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\VCS\\": "src/VCS",
"Utopia\\Detector\\": "src/Detector"
"Utopia\\VCS\\": "src/VCS"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -4899,9 +4898,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/vcs/issues",
"source": "https://github.com/utopia-php/vcs/tree/0.9.4"
"source": "https://github.com/utopia-php/vcs/tree/0.10.1"
},
"time": "2025-03-13T10:09:45+00:00"
"time": "2025-03-18T11:44:09+00:00"
},
{
"name": "utopia-php/websocket",
@@ -5088,16 +5087,16 @@
"packages-dev": [
{
"name": "appwrite/sdk-generator",
"version": "0.40.7",
"version": "0.40.9",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "9e89b0bc4d8e6c81817d27096629f34a149fa873"
"reference": "dbb45a5db22cdc3368fe2573c07ba6088f188fa4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/9e89b0bc4d8e6c81817d27096629f34a149fa873",
"reference": "9e89b0bc4d8e6c81817d27096629f34a149fa873",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/dbb45a5db22cdc3368fe2573c07ba6088f188fa4",
"reference": "dbb45a5db22cdc3368fe2573c07ba6088f188fa4",
"shasum": ""
},
"require": {
@@ -5133,9 +5132,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.7"
"source": "https://github.com/appwrite/sdk-generator/tree/0.40.9"
},
"time": "2025-03-12T08:43:55+00:00"
"time": "2025-03-17T18:39:14+00:00"
},
{
"name": "doctrine/annotations",
@@ -8506,7 +8505,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@@ -8530,5 +8529,5 @@
"platform-overrides": {
"php": "8.3"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}
+1 -1
View File
@@ -205,7 +205,7 @@ services:
appwrite-console:
<<: *x-logging
container_name: appwrite-console
image: appwrite/console:5.3.0-sites-rc.26
image: appwrite/console:5.3.0-sites-rc.27
restart: unless-stopped
networks:
- appwrite
@@ -59,7 +59,6 @@ class Base extends Action
}
}
$authorUrl = "https://github.com/$owner";
$repositoryUrl = "https://github.com/$owner/$repositoryName";
$deployment = $dbForProject->createDocument('deployments', new Document([
@@ -85,7 +84,7 @@ class Base extends Action
'providerRepositoryOwner' => $owner,
'providerRepositoryUrl' => $repositoryUrl,
'providerCommitHash' => $commitDetails['commitHash'] ?? '',
'providerCommitAuthorUrl' => $authorUrl,
'providerCommitAuthorUrl' => $commitDetails['commitAuthorUrl'] ?? '',
'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '',
'providerCommitMessage' => mb_strimwidth($commitDetails['commitMessage'] ?? '', 0, 255, '...'),
'providerCommitUrl' => $commitDetails['commitUrl'] ?? '',
@@ -143,7 +142,6 @@ class Base extends Action
}
}
$authorUrl = "https://github.com/$owner";
$repositoryUrl = "https://github.com/$owner/$repositoryName";
$commands = [];
@@ -177,7 +175,7 @@ class Base extends Action
'providerRepositoryOwner' => $owner,
'providerRepositoryUrl' => $repositoryUrl,
'providerCommitHash' => $commitDetails['commitHash'] ?? '',
'providerCommitAuthorUrl' => $authorUrl,
'providerCommitAuthorUrl' => $commitDetails['commitAuthorUrl'] ?? '',
'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '',
'providerCommitMessage' => mb_strimwidth($commitDetails['commitMessage'] ?? '', 0, 255, '...'),
'providerCommitUrl' => $commitDetails['commitUrl'] ?? '',
@@ -234,6 +234,7 @@ class Create extends Action
'buildCommands' => $commands,
'sourcePath' => $path,
'sourceSize' => $fileSize,
'totalSize' => $fileSize,
'search' => implode(' ', [$deploymentId, $entrypoint]),
'activate' => $activate,
'sourceMetadata' => $metadata,
@@ -264,6 +265,7 @@ class Create extends Action
'buildCommands' => $commands,
'sourcePath' => $path,
'sourceSize' => $fileSize,
'totalSize' => $fileSize,
'sourceChunksTotal' => $chunks,
'sourceChunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$deploymentId, $entrypoint]),
@@ -100,6 +100,7 @@ class Delete extends Action
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'deploymentId' => '',
'deploymentInternalId' => '',
'deploymentCreatedAt' => '',
])));
}
@@ -100,6 +100,7 @@ class Create extends Action
'$internalId' => '',
'$id' => $deploymentId,
'sourcePath' => $destination,
'totalSize' => $deployment->getAttribute('sourceSize', 0),
'entrypoint' => $function->getAttribute('entrypoint'),
'buildCommands' => $function->getAttribute('commands', ''),
'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]),
@@ -93,6 +93,7 @@ class Update extends Base
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentId' => $deployment->getId(),
'deploymentCreatedAt' => $deployment->getCreatedAt(),
])));
// Inform scheduler if function is still active
@@ -190,6 +190,12 @@ class Builds extends Action
// Realtime preparation
$event = "{$resource->getCollection()}.[{$resourceKey}].deployments.[deploymentId].update";
$queueForRealtime
->setSubscribers(['console'])
->setProject($project)
->setEvent($event)
->setParam($resourceKey, $resource->getId())
->setParam('deploymentId', $deployment->getId());
$startTime = DateTime::now();
$durationStart = \microtime(true);
@@ -205,6 +211,10 @@ class Builds extends Action
$deployment->setAttribute('status', 'processing');
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
$source = $deployment->getAttribute('sourcePath', '');
$installationId = $deployment->getAttribute('installationId', '');
$providerRepositoryId = $deployment->getAttribute('providerRepositoryId', '');
@@ -275,8 +285,13 @@ class Builds extends Action
$directorySize = $device->getFileSize($source);
$deployment
->setAttribute('sourcePath', $source)
->setAttribute('sourceSize', $directorySize);
->setAttribute('sourceSize', $directorySize)
->setAttribute('totalSize', $directorySize);
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
}
} elseif ($isVcsEnabled) {
// VCS and VCS+Temaplte
@@ -384,15 +399,7 @@ class Builds extends Action
$deployment->setAttribute('providerCommitUrl', "https://github.com/$cloneOwner/$cloneRepository/commit/$providerCommitHash");
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
/**
* Trigger Realtime Event
*/
$queueForRealtime
->setSubscribers(['console'])
->setProject($project)
->setEvent($event)
->setParam($resourceKey, $resource->getId())
->setParam('deploymentId', $deployment->getId())
->setPayload($deployment->getArrayCopy())
->trigger();
}
@@ -430,9 +437,14 @@ class Builds extends Action
$deployment
->setAttribute('sourcePath', $source)
->setAttribute('sourceSize', $directorySize);
->setAttribute('sourceSize', $directorySize)
->setAttribute('totalSize', $directorySize);
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
$this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
}
@@ -440,6 +452,10 @@ class Builds extends Action
$deployment->setAttribute('status', 'building');
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
if ($isVcsEnabled) {
$this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
}
@@ -465,11 +481,6 @@ class Builds extends Action
/** Trigger Realtime Event */
$queueForRealtime
->setSubscribers(['console'])
->setProject($project)
->setEvent($event)
->setParam($resourceKey, $resource->getId())
->setParam('deploymentId', $deployment->getId())
->setPayload($deployment->getArrayCopy())
->trigger();
@@ -577,7 +588,6 @@ class Builds extends Action
try {
$command = $version === 'v2' ? 'tar -zxf /tmp/code.tar.gz -C /usr/code && cd /usr/local/src/ && ./build.sh' : 'tar -zxf /tmp/code.tar.gz -C /mnt/code && helpers/build.sh "' . \trim(\escapeshellarg($command), "\'") . '"';
// TODO: Detect adapter if adapter is empty
$response = $executor->createRuntime(
deploymentId: $deployment->getId(),
projectId: $project->getId(),
@@ -598,13 +608,13 @@ class Builds extends Action
$err = $error;
}
}),
Co\go(function () use ($executor, $project, &$deployment, &$response, $dbForProject, $event, $timeout, &$err, $queueForRealtime, &$isCanceled, $resourceKey, $resource) {
Co\go(function () use ($executor, $project, &$deployment, &$response, $dbForProject, $timeout, &$err, $queueForRealtime, &$isCanceled) {
try {
$executor->getLogs(
deploymentId: $deployment->getId(),
projectId: $project->getId(),
timeout: $timeout,
callback: function ($logs) use (&$response, &$err, $dbForProject, $event, $project, &$isCanceled, &$deployment, $queueForRealtime, $resourceKey, $resource) {
callback: function ($logs) use (&$response, &$err, $dbForProject, &$isCanceled, &$deployment, $queueForRealtime) {
if ($isCanceled) {
return;
}
@@ -640,15 +650,7 @@ class Builds extends Action
$deployment = $deployment->setAttribute('buildLogs', $currentLogs);
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
/**
* Trigger Realtime Event
*/
$queueForRealtime
->setSubscribers(['console'])
->setProject($project)
->setEvent($event)
->setParam($resourceKey, $resource->getId())
->setParam('deploymentId', $deployment->getId())
->setPayload($deployment->getArrayCopy())
->trigger();
}
@@ -720,6 +722,7 @@ class Builds extends Action
$deployment->setAttribute('status', 'ready');
$deployment->setAttribute('buildPath', $response['path']);
$deployment->setAttribute('buildSize', $response['size']);
$deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0));
$logs = '';
foreach ($response['output'] as $log) {
@@ -729,6 +732,10 @@ class Builds extends Action
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
if ($isVcsEnabled) {
$this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
}
@@ -780,12 +787,12 @@ class Builds extends Action
'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey
]);
$config['sleep'] = 3000; // 3 seconds
$config['sleep'] = 3000;
// Makes tests much faster
$isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development';
if ($isDevelopment) {
$config['sleep'] = 0; // Override this when running Screenshot.php task
$frameworks = Config::getParam('frameworks', []);
$framework = $frameworks[$resource->getAttribute('framework', '')] ?? null;
if (!is_null($framework)) {
$config['sleep'] = $framework['screenshotSleep'];
}
$response = $client->fetch(
@@ -841,6 +848,10 @@ class Builds extends Action
}
$dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
} catch (\Throwable $th) {
Console::warning("Screenshot failed to generate:");
Console::warning($th->getMessage());
@@ -857,6 +868,7 @@ class Builds extends Action
$resource->setAttribute('deploymentId', $deployment->getId());
$resource->setAttribute('deploymentInternalId', $deployment->getInternalId());
$resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt());
$resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource);
$queries = [
@@ -873,7 +885,9 @@ class Builds extends Action
$queries[] = Query::equal("deploymentInternalId", [$oldDeploymentInternalId]);
}
$this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) {
$rulesUpdated = false;
$this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment, &$rulesUpdated) {
$rulesUpdated = true;
$rule = $rule
->setAttribute('deploymentId', $deployment->getId())
->setAttribute('deploymentInternalId', $deployment->getInternalId());
@@ -885,8 +899,10 @@ class Builds extends Action
$resource->setAttribute('deploymentId', $deployment->getId());
$resource->setAttribute('deploymentInternalId', $deployment->getInternalId());
$resource->setAttribute('deploymentScreenshotDark', $deployment->getAttribute('screenshotDark', ''));
$resource->setAttribute('deploymentScreenshotLight', $deployment->getAttribute('screenshotLight', ''));
$resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt());
$resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource);
$queries = [
Query::equal("projectInternalId", [$project->getInternalId()]),
Query::equal("type", ["deployment"]),
@@ -1001,19 +1017,15 @@ class Builds extends Action
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
if ($isVcsEnabled) {
$this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform);
}
} finally {
/**
* Trigger Realtime Event
*/
$queueForRealtime
->setSubscribers(['console'])
->setProject($project)
->setEvent($event)
->setParam($resourceKey, $resource->getId())
->setParam('deploymentId', $deployment->getId())
->setPayload($deployment->getArrayCopy())
->trigger();
@@ -243,6 +243,7 @@ class Create extends Action
'buildOutput' => $outputDirectory,
'sourcePath' => $path,
'sourceSize' => $fileSize,
'totalSize' => $fileSize,
'search' => implode(' ', [$deploymentId]),
'activate' => $activate,
'sourceMetadata' => $metadata,
@@ -300,6 +301,7 @@ class Create extends Action
'buildOutput' => $outputDirectory,
'sourcePath' => $path,
'sourceSize' => $fileSize,
'totalSize' => $fileSize,
'sourceChunksTotal' => $chunks,
'sourceChunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$deploymentId]),
@@ -100,6 +100,9 @@ class Delete extends Action
$site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [
'deploymentId' => '',
'deploymentInternalId' => '',
'deploymentScreenshotDark' => '',
'deploymentScreenshotLight' => '',
'deploymentCreatedAt' => '',
])));
}
@@ -111,6 +111,7 @@ class Create extends Action
'$internalId' => '',
'$id' => $deploymentId,
'sourcePath' => $destination,
'totalSize' => $deployment->getAttribute('sourceSize', 0),
'buildCommands' => \implode(' && ', $commands),
'buildOutput' => $site->getAttribute('outputDirectory', ''),
'search' => implode(' ', [$deploymentId]),
@@ -118,8 +119,8 @@ class Create extends Action
'screenshotDark' => '',
'buildStartAt' => null,
'buildEndAt' => null,
'buildDuration' => null,
'buildSize' => null,
'buildDuration' => 0,
'buildSize' => 0,
'status' => 'waiting',
'buildPath' => '',
'buildLogs' => '',
@@ -52,6 +52,12 @@ class XList extends Base
{
$frameworks = Config::getParam('frameworks');
foreach ($frameworks as $key => $framework) {
if (!empty($framework['adapters'])) {
$frameworks[$key]['adapters'] = \array_values($framework['adapters']);
}
}
$response->dynamic(new Document([
'total' => count($frameworks),
'frameworks' => \array_values($frameworks)
@@ -90,6 +90,9 @@ class Update extends Base
$site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [
'deploymentInternalId' => $deployment->getInternalId(),
'deploymentId' => $deployment->getId(),
'deploymentScreenshotDark' => $deployment->getAttribute('screenshotDark', ''),
'deploymentScreenshotLight' => $deployment->getAttribute('screenshotLight', ''),
'deploymentCreatedAt' => $deployment->getCreatedAt(),
])));
$queries = [
@@ -1111,6 +1111,7 @@ class Deletes extends Action
*/
Console::info("Deleting rules for deployment " . $deploymentId);
$this->deleteByGroup('rules', [
Query::equal('trigger', ['manual']),
Query::equal('type', ['deployment']),
Query::equal('deploymentResourceInternalId', [$deploymentInternalId]),
Query::equal('projectInternalId', [$project->getInternalId()])
@@ -7,6 +7,7 @@ class Deployments extends Base
public const ALLOWED_ATTRIBUTES = [
'buildSize',
'sourceSize',
'totalSize',
'buildDuration',
'status',
'activate',
@@ -64,6 +64,12 @@ class Deployment extends Model
'default' => 0,
'example' => 128,
])
->addRule('totalSize', [
'type' => self::TYPE_INTEGER,
'description' => 'The total size in bytes (source and build output).',
'default' => 0,
'example' => 128,
])
->addRule('buildId', [
'type' => self::TYPE_STRING,
'description' => 'The current build ID.',
@@ -71,6 +71,12 @@ class Func extends Model
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('deploymentCreatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Active deployment creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('scopes', [
'type' => self::TYPE_STRING,
'description' => 'Allowed permission scopes.',
@@ -58,6 +58,24 @@ class Site extends Model
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('deploymentCreatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Active deployment creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('deploymentScreenshotLight', [
'type' => self::TYPE_STRING,
'description' => 'Screenshot of active deployment with light theme preference file ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('deploymentScreenshotDark', [
'type' => self::TYPE_STRING,
'description' => 'Screenshot of active deployment with dark theme preference file ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('vars', [
'type' => Response::MODEL_VARIABLE,
'description' => 'Site variables.',
+6 -23
View File
@@ -882,29 +882,12 @@ class UsageTest extends Scope
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$response = $this->client->call(
Client::METHOD_POST,
'/functions/' . $functionId . '/deployments',
array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id']
], $this->getHeaders()),
[
'entrypoint' => 'index.php',
'code' => $this->packageFunction('php'),
'activate' => true,
]
);
$deploymentId = $response['body']['$id'] ?? '';
$this->assertEquals(202, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt']));
$this->assertEquals('index.php', $response['body']['entrypoint']);
// Wait for deployment to build.
sleep(self::WAIT + 20);
$deploymentId = $this->setupDeployment($functionId, [
'entrypoint' => 'index.php',
'code' => $this->packageFunction('php'),
'activate' => true,
]);
$this->assertNotEmpty($deploymentId);
$response = $this->client->call(
Client::METHOD_PATCH,
@@ -408,6 +408,12 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(202, $deployment['headers']['status-code']);
$this->assertNotEmpty($deployment['body']['$id']);
$deployment = $this->getDeployment($functionId, $deployment['body']['$id']);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertEquals(0, $deployment['body']['sourceSize']);
$this->assertEquals(0, $deployment['body']['buildSize']);
$this->assertEquals(0, $deployment['body']['totalSize']);
$deployments = $this->listDeployments($functionId);
$this->assertEquals(200, $deployments['headers']['status-code']);
@@ -480,7 +486,21 @@ class FunctionsCustomServerTest extends Scope
$this->assertStringContainsString("Total users: " . $totalUsers, $execution['body']['logs']);
}, 10000, 500);
$function = $this->deleteFunction($functionId);
$deployment = $this->getDeployment($functionId, $deployment['body']['$id']);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertNotEmpty($function['body']['deploymentId']);
$this->assertNotEmpty($function['body']['deploymentCreatedAt']);
$this->assertEquals($deployment['body']['$id'], $function['body']['deploymentId']);
$this->assertEquals($deployment['body']['$createdAt'], $function['body']['deploymentCreatedAt']);
$function = $this->cleanupFunction($functionId);
}
/**
@@ -1634,11 +1654,14 @@ class FunctionsCustomServerTest extends Scope
'entrypoint' => 'index.php',
'timeout' => 15,
]);
$this->setupDeployment($functionId, [
$this->assertNotEmpty($functionId);
$deploymentId = $this->setupDeployment($functionId, [
'entrypoint' => 'index.php',
'code' => $this->packageFunction('php-cookie'),
'activate' => true
]);
$this->assertNotEmpty($deploymentId);
$cookie = 'cookieName=cookieValue; cookie2=value2; cookie3=value=3; cookie4=val:ue4; cookie5=value5';
$execution = $this->createExecution($functionId, [
@@ -1654,6 +1677,13 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals($cookie, $execution['body']['responseBody']);
$this->assertGreaterThan(0, $execution['body']['duration']);
$deployment = $this->getDeployment($functionId, $deploymentId);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$this->cleanupFunction($functionId);
}
@@ -2029,13 +2059,34 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertStringContainsString('maintenance.js', $function['body']['commands']);
$deploymentId2 = $this->setupDuplicateDeployment($functionId, $deploymentId1);
$deployment = $this->createDuplicateDeployment($functionId, $deploymentId1);
$this->assertEquals(202, $deployment['headers']['status-code']);
$deploymentId2 = $deployment['body']['$id'];
$this->assertNotEmpty($deploymentId2);
$deployment = $this->getDeployment($functionId, $deploymentId2);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertEquals(0, $deployment['body']['buildSize']);
$this->assertEquals($deployment['body']['sourceSize'], $deployment['body']['totalSize']);
$this->assertEventually(function () use ($functionId, $deploymentId2) {
$function = $this->getFunction($functionId);
$this->assertEquals($deploymentId2, $function['body']['deploymentId']);
}, 50000, 500);
$execution = $this->createExecution($functionId);
$this->assertEquals(201, $execution['headers']['status-code']);
$this->assertStringContainsString('Maintenance', $execution['body']['responseBody']);
$deployment = $this->getDeployment($functionId, $deploymentId2);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$this->cleanupFunction($functionId);
}
@@ -534,10 +534,11 @@ class RealtimeConsoleClientTest extends Scope
'timeout' => 10
]);
$functionId = $response1['body']['$id'] ?? '';
$this->assertEquals(201, $response1['headers']['status-code']);
$functionId = $response1['body']['$id'];
$this->assertNotEmpty($functionId);
$projectId = 'console';
$client = $this->getWebsocket(['console'], [
@@ -570,6 +571,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals(202, $deployment['headers']['status-code']);
$deploymentId = $deployment['body']['$id'];
$this->assertNotEmpty($deploymentId);
$response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response);
@@ -580,8 +584,48 @@ class RealtimeConsoleClientTest extends Scope
$this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
// $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']); TODO @christyjacob4 : enable test once we allow functions.* events
$this->assertNotEmpty($response['data']['payload']);
$this->assertEquals("waiting", $response['data']['payload']['status']);
$this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']);
$response = json_decode($client->receive(), true);
$this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']);
$this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertEquals("processing", $response['data']['payload']['status']);
$response = json_decode($client->receive(), true);
$this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']);
$this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertEquals("building", $response['data']['payload']['status']);
$previousBuildLogs = null;
while (true) {
$response = json_decode($client->receive(), true);
$this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']);
$this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertArrayHasKey('buildLogs', $response['data']['payload']);
// Ignore comparasion for first payload
if ($previousBuildLogs !== null) {
$this->assertNotEquals($previousBuildLogs, $response['data']['payload']['buildLogs']);
}
$previousBuildLogs = $response['data']['payload']['buildLogs'];
$this->assertThat(
$response['data']['payload']['status'],
$this->logicalOr(
$this->equalTo('building'),
$this->equalTo('ready'),
),
);
if ($response['data']['payload']['status'] === 'ready') {
break;
}
}
$client->close();
}
@@ -360,6 +360,20 @@ class SitesCustomServerTest extends Scope
$this->assertStringContainsString("Env variable is Appwrite", $response['body']);
$this->assertStringNotContainsString("Variable not found", $response['body']);
$deployment = $this->getDeployment($siteId, $deploymentId);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertNotEmpty($site['body']['deploymentId']);
$this->assertNotEmpty($site['body']['deploymentCreatedAt']);
$this->assertEquals($deployment['body']['$id'], $site['body']['deploymentId']);
$this->assertEquals($deployment['body']['$createdAt'], $site['body']['deploymentCreatedAt']);
$this->cleanupSite($siteId);
}
@@ -1364,6 +1378,11 @@ class SitesCustomServerTest extends Scope
$this->assertArrayHasKey('buildRuntime', $framework);
$this->assertArrayHasKey('runtimes', $framework);
$this->assertArrayHasKey('adapters', $framework);
$this->assertIsArray($framework['adapters']);
$this->assertArrayHasKey('key', $framework['adapters'][0]);
$this->assertArrayHasKey('installCommand', $framework['adapters'][0]);
$this->assertArrayHasKey('buildCommand', $framework['adapters'][0]);
$this->assertArrayHasKey('outputDirectory', $framework['adapters'][0]);
}
public function testSiteStatic(): void
@@ -1510,6 +1529,12 @@ class SitesCustomServerTest extends Scope
$this->assertEquals(202, $deployment['headers']['status-code']);
$this->assertNotEmpty($deployment['body']['$id']);
$deployment = $this->getDeployment($siteId, $deployment['body']['$id']);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertEquals(0, $deployment['body']['sourceSize']);
$this->assertEquals(0, $deployment['body']['buildSize']);
$this->assertEquals(0, $deployment['body']['totalSize']);
$this->assertEventually(function () use ($siteId) {
$site = $this->getSite($siteId);
$this->assertNotEmpty($site['body']['deploymentId']);
@@ -1531,6 +1556,13 @@ class SitesCustomServerTest extends Scope
$this->assertStringContainsString("Astro Blog", $response['body']);
$this->assertStringContainsString("About Me", $response['body']);
$deployment = $this->getDeployment($siteId, $deployment['body']['$id']);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$this->cleanupSite($siteId);
}
@@ -1791,11 +1823,15 @@ class SitesCustomServerTest extends Scope
$this->assertStringContainsString("@media (prefers-color-scheme: dark)", $response['body']);
$deployment = $this->getDeployment($siteId, $deploymentId);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertNotEmpty($deployment['body']['screenshotLight']);
$this->assertNotEmpty($deployment['body']['screenshotDark']);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deployment['body']['screenshotLight'], $site['body']['deploymentScreenshotLight']);
$this->assertEquals($deployment['body']['screenshotDark'], $site['body']['deploymentScreenshotDark']);
$screenshotId = $deployment['body']['screenshotLight'];
$file = $this->client->call(Client::METHOD_GET, "/storage/buckets/screenshots/files/$screenshotId/view?project=console", array_merge([
], $this->getHeaders()));
@@ -1980,12 +2016,33 @@ class SitesCustomServerTest extends Scope
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals('index.html', $site['body']['fallbackFile']);
$deploymentId2 = $this->setupDuplicateDeployment($siteId, $deploymentId1);
$deployment = $this->createDuplicateDeployment($siteId, $deploymentId1);
$this->assertEquals(202, $deployment['headers']['status-code']);
$deploymentId2 = $deployment['body']['$id'];
$this->assertNotEmpty($deploymentId2);
$deployment = $this->getDeployment($siteId, $deploymentId2);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertEquals(0, $deployment['body']['buildSize']);
$this->assertEquals($deployment['body']['sourceSize'], $deployment['body']['totalSize']);
$this->assertEventually(function () use ($siteId, $deploymentId2) {
$site = $this->getSite($siteId);
$this->assertEquals($deploymentId2, $site['body']['deploymentId']);
}, 50000, 500);
$response = $proxyClient->call(Client::METHOD_GET, '/not-found');
$this->assertStringContainsString("Index page", $response['body']);
$deployment = $this->getDeployment($siteId, $deploymentId2);
$this->assertEquals(200, $deployment['headers']['status-code']);
$this->assertGreaterThan(0, $deployment['body']['sourceSize']);
$this->assertGreaterThan(0, $deployment['body']['buildSize']);
$totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize'];
$this->assertEquals($totalSize, $deployment['body']['totalSize']);
$this->cleanupSite($siteId);
}