Implement screenshot task and initial run

This commit is contained in:
Matej Bačo
2025-02-27 15:58:33 +01:00
parent 92daef51f0
commit bf3b21cdb1
25 changed files with 276 additions and 1 deletions
+1
View File
@@ -68,6 +68,7 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/sdks && \
chmod +x /usr/local/bin/specs && \
chmod +x /usr/local/bin/ssl && \
chmod +x /usr/local/bin/screenshot && \
chmod +x /usr/local/bin/test && \
chmod +x /usr/local/bin/upgrade && \
chmod +x /usr/local/bin/vars && \
+5
View File
@@ -208,6 +208,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
'site' => $runtimes[$resource->getAttribute('buildRuntime')] ?? null,
default => null
};
// Static site enforced runtime
if ($resource->getAttribute('adapter', '') === 'static') {
$runtime = $runtimes['static-1'] ?? null;
}
if (\is_null($runtime)) {
throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported');
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php screenshot $@
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php ssl $@
php /usr/src/code/app/cli.php screenshot $@
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

+2
View File
@@ -10,6 +10,7 @@ use Appwrite\Platform\Tasks\QueueRetry;
use Appwrite\Platform\Tasks\ScheduleExecutions;
use Appwrite\Platform\Tasks\ScheduleFunctions;
use Appwrite\Platform\Tasks\ScheduleMessages;
use Appwrite\Platform\Tasks\Screenshot;
use Appwrite\Platform\Tasks\SDKs;
use Appwrite\Platform\Tasks\Specs;
use Appwrite\Platform\Tasks\SSL;
@@ -32,6 +33,7 @@ class Tasks extends Service
->addAction(QueueRetry::getName(), new QueueRetry())
->addAction(SDKs::getName(), new SDKs())
->addAction(SSL::getName(), new SSL())
->addAction(Screenshot::getName(), new Screenshot())
->addAction(ScheduleFunctions::getName(), new ScheduleFunctions())
->addAction(ScheduleExecutions::getName(), new ScheduleExecutions())
->addAction(ScheduleMessages::getName(), new ScheduleMessages())
+264
View File
@@ -0,0 +1,264 @@
<?php
namespace Appwrite\Platform\Tasks;
use Appwrite\ID;
use Tests\E2E\Client;
use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Domains\Contact;
use Utopia\Platform\Action;
use Utopia\Validator\Text;
class Screenshot extends Action
{
public static function getName(): string
{
return 'screenshot';
}
public function __construct()
{
$this
->desc('Create Site template screenshot')
->param('templateId', '', new Text(128), 'Template ID.')
->callback(fn (string $templateId) => $this->action($templateId));
}
public function action(string $templateId): void
{
$templates = Config::getParam('site-templates', []);
$allowedTemplates = \array_filter($templates, function ($item) use ($templateId) {
return $item['key'] === $templateId;
});
$template = \array_shift($allowedTemplates);
if (empty($template)) {
throw new \Exception("Template {$templateId} not found. Find correct ID in app/config/site-templates.php");
}
Console::info("Found: " . $template['name']);
$client = new Client();
$client->setEndpoint('http://localhost/v1');
$client->addHeader('origin', 'http://localhost');
// Register
$email = uniqid() . 'user@localhost.test';
$password = 'password';
$user = $client->call(Client::METHOD_POST, '/account', [
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
], [
'userId' => ID::unique(),
'email' => $email,
'password' => $password,
]);
if($user['headers']['status-code'] !== 201) {
Console::error(\json_encode($user));
throw new \Exception("Failed to register user");
}
Console::info("User created");
// Login
$session = $client->call(Client::METHOD_POST, '/account/sessions/email', [
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
], [
'email' => $email,
'password' => $password,
]);
if($session['headers']['status-code'] !== 201) {
Console::error(\json_encode($session));
throw new \Exception("Failed to login user");
}
Console::info("Session created");
$secret = $session['cookies']['a_session_console'];
$cookieConsole = 'a_session_console=' . $secret;
// Create organization
$team = $client->call(Client::METHOD_POST, '/teams', [
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
'cookie' => $cookieConsole
], [
'teamId' => ID::unique(),
'name' => 'Demo Project Team',
]);
if($team['headers']['status-code'] !== 201) {
Console::error(\json_encode($team));
throw new \Exception("Failed to create team");
}
Console::info("Team created");
// Create project
$project = $client->call(Client::METHOD_POST, '/projects', [
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
'cookie' => $cookieConsole
], [
'projectId' => ID::unique(),
'region' => 'default',
'name' => 'Demo Project',
'teamId' => $team['body']['$id'],
'description' => 'Demo Project Description',
'url' => 'https://appwrite.io',
]);
if($project['headers']['status-code'] !== 201) {
Console::error(\json_encode($project));
throw new \Exception("Failed to create project");
}
Console::info("Project created");
$projectId = $project['body']['$id'];
$framework = $template['frameworks'][0];
// Create site
$site = $client->call(Client::METHOD_POST, '/sites', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-mode' => 'admin',
'cookie' => $cookieConsole
], [
'siteId' => ID::unique(),
'name' => $template["name"],
'framework' => $framework['key'],
'adapter' => $framework['adapter'],
'buildCommand' => $framework['buildCommand'],
'buildRuntime' => $framework['buildRuntime'],
'fallbackFile' => $framework['fallbackFile'],
'installCommand' => $framework['installCommand'],
'outputDirectory' => $framework['outputDirectory'],
'providerRootDirectory' => $framework['providerRootDirectory'],
]);
if($site['headers']['status-code'] !== 201) {
Console::error(\json_encode($site));
throw new \Exception("Failed to create site");
}
Console::info("Site created");
// TODO: Add variables, and replace placeholders
$siteId = $site['body']['$id'];
// Create deployment
$deployment = $client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/template', [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-mode' => 'admin',
'cookie' => $cookieConsole
], [
'owner' => $template['providerOwner'],
'repository' => $template['providerRepositoryId'],
'rootDirectory' => $framework['providerRootDirectory'],
'version' => $template['providerVersion'],
'activate' => true,
]);
if($deployment['headers']['status-code'] !== 202) {
Console::error(\json_encode($deployment));
throw new \Exception("Failed to create deployment");
}
Console::info("Deployment created");
$deploymentId = $deployment['body']['$id'];
// Await screenshot
$attempts = 50;
$sleep = 5;
$idLight = '';
$idDark = '';
Console::log("Awaiting deployment (every $sleep seconds, $attempts attempts)");
for($i = 0; $i < $attempts; $i++) {
$deployment = $client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-mode' => 'admin',
'cookie' => $cookieConsole
]);
if($deployment['headers']['status-code'] !== 200) {
Console::error(\json_encode($deployment));
throw new \Exception("Failed to get deployment");
}
if($deployment['body']['status'] === 'failed') {
Console::error(\json_encode($deployment));
throw new \Exception("Deployment build failed");
}
if($deployment['body']['status'] !== 'ready') {
Console::log("Deployment not ready yet, status: " . $deployment['body']['status']);
\sleep($sleep);
continue;
}
if(empty($deployment['body']['screenshotLight'])) {
Console::log("Light screenshot not available yet");
\sleep($sleep);
continue;
}
if(empty($deployment['body']['screenshotDark'])) {
Console::log("Dark screenshot not available yet");
\sleep($sleep);
continue;
}
$idLight = $deployment['body']['screenshotLight'];
$idDark = $deployment['body']['screenshotDark'];
break;
}
if(empty($idLight) || empty($idDark)) {
Console::error(\json_encode($deployment));
throw new \Exception("Failed to get deployment screenshot");
}
Console::info("Screenshots created");
$themes = [
[ 'fileId' => $idLight, 'suffix' => 'light' ],
[ 'fileId' => $idDark, 'suffix' => 'dark' ]
];
foreach($themes as $theme) {
$file = $client->call(Client::METHOD_GET, '/storage/buckets/screenshots/files/' . $theme['fileId'] . '/download', [
'x-appwrite-project' => 'console',
'x-appwrite-mode' => 'admin',
'cookie' => $cookieConsole
]);
if($file['headers']['status-code'] !== 200) {
Console::error(\json_encode($file));
throw new \Exception("Failed to download {$theme['suffix']} screenshot");
}
$path = "/usr/src/code/public/images/sites/templates/{$template['key']}-{$theme['suffix']}.png";
if(!\file_put_contents($path, $file['body'])) {
throw new \Exception("Failed to save {$theme['suffix']} screenshot");
}
}
Console::success("Screenshots saved");
}
}