From 232f99c6c9d27e0e581d8fe486f8a8cde1f04659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 8 Mar 2025 16:50:39 +0100 Subject: [PATCH] Finalize PR, review changes, fix tests --- app/config/frameworks.php | 38 ++--- app/controllers/api/vcs.php | 104 +++++++------ composer.lock | 78 +++++++++- docker-compose.yml | 2 +- .../Modules/Functions/Workers/Builds.php | 36 ++--- .../Modules/Sites/Http/Sites/Create.php | 2 +- .../Modules/Sites/Http/Sites/Update.php | 2 +- src/Appwrite/Utopia/Response.php | 32 ++-- ...rkDetection.php => DetectionFramework.php} | 6 +- ...timeDetection.php => DetectionRuntime.php} | 6 +- ...ry.php => ProviderRepositoryFramework.php} | 8 +- ...tory.php => ProviderRepositoryRuntime.php} | 10 +- src/Executor/Executor.php | 6 +- .../Services/Sites/SitesCustomServerTest.php | 144 +++++++++++++++++- .../e2e/Services/VCS/VCSConsoleClientTest.php | 55 ++++--- .../sites/astro-static/astro.config.mjs | 4 + .../resources/sites/astro-static/package.json | 14 ++ .../sites/astro-static/src/pages/index.astro | 10 ++ .../sites/static-single-file/main.html | 10 ++ 19 files changed, 396 insertions(+), 171 deletions(-) rename src/Appwrite/Utopia/Response/Model/{FrameworkDetection.php => DetectionFramework.php} (91%) rename src/Appwrite/Utopia/Response/Model/{RuntimeDetection.php => DetectionRuntime.php} (90%) rename src/Appwrite/Utopia/Response/Model/{FrameworkProviderRepository.php => ProviderRepositoryFramework.php} (65%) rename src/Appwrite/Utopia/Response/Model/{RuntimeProviderRepository.php => ProviderRepositoryRuntime.php} (62%) create mode 100644 tests/resources/sites/astro-static/astro.config.mjs create mode 100644 tests/resources/sites/astro-static/package.json create mode 100644 tests/resources/sites/astro-static/src/pages/index.astro create mode 100644 tests/resources/sites/static-single-file/main.html diff --git a/app/config/frameworks.php b/app/config/frameworks.php index 332035a79c..8aee8b9e16 100644 --- a/app/config/frameworks.php +++ b/app/config/frameworks.php @@ -23,6 +23,8 @@ return [ 'name' => 'Next.js', 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'sh /usr/local/server/helpers/next-js/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh', 'adapters' => [ 'ssr' => [ 'key' => 'ssr', @@ -30,8 +32,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './.next', 'startCommand' => 'sh helpers/next-js/server.sh', - 'bundleCommand' => 'sh /usr/local/server/helpers/next-js/bundle.sh', - 'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh', ], 'static' => [ 'key' => 'static', @@ -39,8 +39,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './out', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ] ] ], @@ -56,8 +54,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './dist', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', 'fallbackFile' => 'index.html' ] ] @@ -67,6 +63,8 @@ return [ 'name' => 'Nuxt', 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'sh /usr/local/server/helpers/nuxt/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh', 'adapters' => [ 'ssr' => [ 'key' => 'ssr', @@ -74,8 +72,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './.output', 'startCommand' => 'sh helpers/nuxt/server.sh', - 'bundleCommand' => 'sh /usr/local/server/helpers/nuxt/bundle.sh', - 'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh', ], 'static' => [ 'key' => 'static', @@ -83,8 +79,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './dist', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ] ] ], @@ -100,8 +94,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './dist', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', 'fallbackFile' => 'index.html' ] ] @@ -111,6 +103,8 @@ return [ 'name' => 'SvelteKit', 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'sh /usr/local/server/helpers/sveltekit/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh', 'adapters' => [ 'ssr' => [ 'key' => 'ssr', @@ -118,8 +112,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './build', 'startCommand' => 'sh helpers/sveltekit/server.sh', - 'bundleCommand' => 'sh /usr/local/server/helpers/sveltekit/bundle.sh', - 'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh', ], 'static' => [ 'key' => 'static', @@ -127,8 +119,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './build', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ] ] ], @@ -137,6 +127,8 @@ return [ 'name' => 'Astro', 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'sh /usr/local/server/helpers/astro/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/astro/env.sh', 'adapters' => [ 'ssr' => [ 'key' => 'ssr', @@ -144,8 +136,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './dist', 'startCommand' => 'sh helpers/astro/server.sh', - 'bundleCommand' => 'sh /usr/local/server/helpers/astro/bundle.sh', - 'envCommand' => 'source /usr/local/server/helpers/astro/env.sh', ], 'static' => [ 'key' => 'static', @@ -153,8 +143,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './dist', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ] ] ], @@ -163,6 +151,8 @@ return [ 'name' => 'Remix', 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'sh /usr/local/server/helpers/remix/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/remix/env.sh', 'adapters' => [ 'ssr' => [ 'key' => 'ssr', @@ -170,8 +160,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './build', 'startCommand' => 'sh helpers/remix/server.sh', - 'bundleCommand' => 'sh /usr/local/server/helpers/remix/bundle.sh', - 'envCommand' => 'source /usr/local/server/helpers/remix/env.sh', ], 'static' => [ 'key' => 'static', @@ -179,8 +167,6 @@ return [ 'installCommand' => 'npm install', 'outputDirectory' => './build/client', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ] ] ], @@ -196,8 +182,6 @@ return [ 'installCommand' => '', 'outputDirectory' => './build/web', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ], ], ], @@ -213,8 +197,6 @@ return [ 'installCommand' => '', 'outputDirectory' => './', 'startCommand' => 'sh helpers/server.sh', - 'bundleCommand' => '', - 'envCommand' => '', ], ] ], diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 014a1233d5..c890bf5395 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -606,7 +606,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro App::post('/v1/vcs/github/installations/:installationId/detections') ->alias('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection') - ->desc('Detect runtime and framework settings from source code') + ->desc('Create repository detection') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') ->label('sdk', new Method( @@ -617,11 +617,11 @@ App::post('/v1/vcs/github/installations/:installationId/detections') responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_RUNTIME_DETECTION, + model: Response::MODEL_DETECTION_RUNTIME, ), new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_FRAMEWORK_DETECTION, + model: Response::MODEL_DETECTION_FRAMEWORK, ) ] )) @@ -663,20 +663,20 @@ App::post('/v1/vcs/github/installations/:installationId/detections') ->addOption(new Yarn()) ->addOption(new PNPM()) ->addOption(new NPM()); - $detectedPackager = $detector->detect(); + $detection = $detector->detect(); - $packagerName = !\is_null($detectedPackager) ? $detectedPackager->getName() : 'npm'; + $packager = !\is_null($detection) ? $detection->getName() : 'npm'; if ($type === 'framework') { - $detection = new Document([ + $output = new Document([ 'framework' => '', 'installCommand' => '', 'buildCommand' => '', 'outputDirectory' => '', ]); - $frameworkDetector = new Framework($files, $packagerName); - $frameworkDetector + $detector = new Framework($files, $packager); + $detector ->addOption(new Flutter()) ->addOption(new Nuxt()) ->addOption(new Astro()) @@ -684,28 +684,27 @@ App::post('/v1/vcs/github/installations/:installationId/detections') ->addOption(new SvelteKit()) ->addOption(new NextJs()); - $detectedFramework = $frameworkDetector->detect(); + $framework = $detector->detect(); - if ($detectedFramework) { - $framework = $detectedFramework->getName(); - $detection->setAttribute('installCommand', $detectedFramework->getInstallCommand()); - $detection->setAttribute('buildCommand', $detectedFramework->getBuildCommand()); - $detection->setAttribute('outputDirectory', $detectedFramework->getOutputDirectory()); + if (!\is_null($framework)) { + $framework = $framework->getName(); + $output->setAttribute('installCommand', $framework->getInstallCommand()); + $output->setAttribute('buildCommand', $framework->getBuildCommand()); + $output->setAttribute('outputDirectory', $framework->getOutputDirectory()); } else { $framework = 'other'; - $detection->setAttribute('installCommand', ''); - $detection->setAttribute('buildCommand', ''); - $detection->setAttribute('outputDirectory', ''); + $output->setAttribute('installCommand', ''); + $output->setAttribute('buildCommand', ''); + $output->setAttribute('outputDirectory', ''); } $frameworks = Config::getParam('frameworks'); - $frameworkKey = 'other'; - if (\in_array($framework, array_keys($frameworks), true)) { - $frameworkKey = $framework; + if (!\in_array($framework, array_keys($frameworks), true)) { + $framework = 'other'; } - $detection->setAttribute('framework', $frameworkKey); + $output->setAttribute('framework', $framework); } else { - $detection = new Document([ + $output = new Document([ 'runtime' => '', 'commands' => '', 'entrypoint' => '', @@ -718,8 +717,8 @@ App::post('/v1/vcs/github/installations/:installationId/detections') ]; foreach ($strategies as $strategy) { - $runtimeDetector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packagerName); - $runtimeDetector + $detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager); + $detector ->addOption(new Node()) ->addOption(new Bun()) ->addOption(new Deno()) @@ -732,35 +731,35 @@ App::post('/v1/vcs/github/installations/:installationId/detections') ->addOption(new CPP()) ->addOption(new Dotnet()); - $detectedRuntime = $runtimeDetector->detect(); + $runtime = $detector->detect(); - if ($detectedRuntime) { - $detection->setAttribute('commands', $detectedRuntime->getCommands()); - $detection->setAttribute('entrypoint', $detectedRuntime->getEntrypoint()); - $runtime = $detectedRuntime->getName(); + if (!\is_null($runtime)) { + $output->setAttribute('commands', $runtime->getCommands()); + $output->setAttribute('entrypoint', $runtime->getEntrypoint()); + $runtime = $runtime->getName(); break; } } if (!empty($runtime)) { $runtimes = Config::getParam('runtimes'); - $versionedRuntime = ''; + $runtimeWithVersion = ''; foreach ($runtimes as $runtimeKey => $runtimeConfig) { if ($runtimeConfig['key'] === $runtime) { - $versionedRuntime = $runtimeKey; + $runtimeWithVersion = $runtimeKey; } } - if (empty($versionedRuntime)) { + if (empty($runtimeWithVersion)) { throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED); } - $detection->setAttribute('runtime', $versionedRuntime); + $output->setAttribute('runtime', $runtimeWithVersion); } else { throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED); } } - $response->dynamic($detection, $type === 'framework' ? Response::MODEL_FRAMEWORK_DETECTION : Response::MODEL_RUNTIME_DETECTION); + $response->dynamic($output, $type === 'framework' ? Response::MODEL_DETECTION_FRAMEWORK : Response::MODEL_DETECTION_RUNTIME); }); App::get('/v1/vcs/github/installations/:installationId/providerRepositories') @@ -775,11 +774,11 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_RUNTIME_PROVIDER_REPOSITORY_LIST, + model: Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST, ), new SDKResponse( code: Response::STATUS_CODE_OK, - model: Response::MODEL_FRAMEWORK_PROVIDER_REPOSITORY_LIST, + model: Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST, ) ] )) @@ -829,12 +828,12 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->addOption(new Yarn()) ->addOption(new PNPM()) ->addOption(new NPM()); - $detectedPackager = $detector->detect(); + $detection = $detector->detect(); - $packagerName = !\is_null($detectedPackager) ? $detectedPackager->getName() : 'npm'; + $packager = !\is_null($detection) ? $detection->getName() : 'npm'; if ($type === 'framework') { - $frameworkDetector = new Framework($files, $packagerName); + $frameworkDetector = new Framework($files, $packager); $frameworkDetector ->addOption(new Flutter()) ->addOption(new Nuxt()) @@ -845,18 +844,17 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') $detectedFramework = $frameworkDetector->detect(); - if ($detectedFramework) { + if (!\is_null($detectedFramework)) { $framework = $detectedFramework->getName(); } else { $framework = 'other'; } $frameworks = Config::getParam('frameworks'); - $frameworkKey = ''; - if (\in_array($framework, array_keys($frameworks), true)) { - $frameworkKey = $framework; + if (!\in_array($framework, array_keys($frameworks), true)) { + $framework = 'other'; } - $repo['framework'] = !empty($frameworkKey) ? $frameworkKey : 'other'; + $repo['framework'] = $framework; } else { $languages = $github->listRepositoryLanguages($repo['organization'], $repo['name']); @@ -867,8 +865,8 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ]; foreach ($strategies as $strategy) { - $runtimeDetector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packagerName); - $runtimeDetector + $redector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager); + $redector ->addOption(new Node()) ->addOption(new Bun()) ->addOption(new Deno()) @@ -881,24 +879,24 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->addOption(new CPP()) ->addOption(new Dotnet()); - $detectedRuntime = $runtimeDetector->detect(); + $runtime = $redector->detect(); - if ($detectedRuntime) { - $runtime = $detectedRuntime->getName(); + if (!\is_null($runtime)) { + $runtime = $runtime->getName(); break; } } if (!empty($runtime)) { $runtimes = Config::getParam('runtimes'); - $versionedRuntime = ''; + $runtimeWithVersion = ''; foreach ($runtimes as $runtimeKey => $runtimeConfig) { if ($runtimeConfig['key'] === $runtime) { - $versionedRuntime = $runtimeKey; + $runtimeWithVersion = $runtimeKey; } } - $repo['runtime'] = $versionedRuntime ?? ''; + $repo['runtime'] = $runtimeWithVersion ?? ''; } } return $repo; @@ -912,7 +910,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') $response->dynamic(new Document([ $type === 'framework' ? 'frameworkProviderRepositories' : 'runtimeProviderRepositories' => $repos, 'total' => \count($repos), - ]), ($type === 'framework') ? Response::MODEL_FRAMEWORK_PROVIDER_REPOSITORY_LIST : Response::MODEL_RUNTIME_PROVIDER_REPOSITORY_LIST); + ]), ($type === 'framework') ? Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST : Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST); }); App::post('/v1/vcs/github/installations/:installationId/providerRepositories') diff --git a/composer.lock b/composer.lock index a7f0992f99..e3a8633120 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "3b6171de8c624cfbcd723f1cc76a9560", + "content-hash": "34ca1e0386c2325732532c6978cd93fb", "packages": [ { "name": "adhocore/jwt", @@ -3758,6 +3758,69 @@ }, "time": "2025-02-12T08:08:29+00:00" }, + { + "name": "utopia-php/detector", + "version": "dev-feat-pseudocode-draft2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/detector.git", + "reference": "e843ff2c85ed55e2cbe7e29f11583903fe002774" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/e843ff2c85ed55e2cbe7e29f11583903fe002774", + "reference": "e843ff2c85ed55e2cbe7e29f11583903fe002774", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.8.*", + "phpunit/phpunit": "^9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Detector\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Utopia\\Tests\\": "tests/Detector/" + } + }, + "scripts": { + "lint": [ + "./vendor/bin/pint --test --config pint.json" + ], + "format": [ + "./vendor/bin/pint --config pint.json" + ], + "check": [ + "./vendor/bin/phpstan analyse --level 8 -c phpstan.neon src tests" + ], + "test": [ + "./vendor/bin/phpunit --configuration phpunit.xml --debug" + ] + }, + "license": [ + "MIT" + ], + "description": "A simple library for fast and reliable environment identification.", + "keywords": [ + "detector", + "framework", + "php", + "utopia" + ], + "support": { + "source": "https://github.com/utopia-php/detector/tree/feat-pseudocode-draft2", + "issues": "https://github.com/utopia-php/detector/issues" + }, + "time": "2025-03-08T15:32:38+00:00" + }, { "name": "utopia-php/domains", "version": "0.5.0", @@ -8793,9 +8856,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/detector", + "version": "dev-feat-pseudocode-draft2", + "alias": "0.1.99", + "alias_normalized": "0.1.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/detector": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docker-compose.yml b/docker-compose.yml index 1cf0af5078..c50c12f206 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -976,7 +976,7 @@ services: # It's not possible to share mount file between 2 containers without host mount (copying is too slow) - /tmp:/tmp:rw environment: - - OPR_EXECUTOR_IMAGE_PULL=enabled + - OPR_EXECUTOR_IMAGE_PULL=disabled - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL - OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index fb6688aec8..c5310378b9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -610,7 +610,7 @@ class Builds extends Action memory: $memory, timeout: $timeout, remove: false, - entrypoint: $deployment->getAttribute('entrypoint', 'package.json'), // TODO: change this later so that sites don't need to have an entrypoint + entrypoint: $deployment->getAttribute('entrypoint', ''), destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}", variables: $vars, command: $command, @@ -711,30 +711,32 @@ class Builds extends Action } if ($resource->getCollection() === 'sites' && isEmpty($resource->getAttribute('adapter'))) { - $listFilesCommand = "cd /usr/local/build/" . $resource->getAttribute('outputDirectory') . " && find . -name 'node_modules' -prune -o -type f -print"; - $commandExecutionResponse = $executor->executeCommand( + $listFilesCommand = "cd /usr/local/build && cd " . \escapeshellarg($resource->getAttribute('outputDirectory')) . " && find . -name 'node_modules' -prune -o -type f -print"; + $command = $executor->createCommand( deploymentId: $deployment->getId(), projectId: $project->getId(), command: $listFilesCommand, - timeout: 60 + timeout: 15 ); - $files = array_map('trim', array_filter(explode("\n", $commandExecutionResponse['output']))); + $files = \explode("\n", $command['output']); // Parse output + $files = \array_filter($files); // Remove empty + $files = \array_map(fn ($file) => \trim($file), $files); // Remove whitepsaces + $files = \array_map(fn ($file) => \str_starts_with($file, './') ? \substr($file, 2) : $file, $files); // Remove beginning ./ - $detector = new Rendering($files, $resource->getAttribute('framework')); + $detector = new Rendering($files, $resource->getAttribute('framework', '')); $detector ->addOption(new SSR()) ->addOption(new XStatic()); - $detectedRenderingStrategy = $detector->detect(); + $detection = $detector->detect(); - $renderingStrategy = $detectedRenderingStrategy->getName(); - $fallbackFile = $detectedRenderingStrategy->getFallbackFile() ?: ''; - - $resource->setAttribute('adapter', $renderingStrategy); - $resource->setAttribute('fallbackFile', $fallbackFile); + $resource->setAttribute('adapter', $detection->getName()); + $resource->setAttribute('fallbackFile', $detection->getFallbackFile() ?? ''); $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource); } + $executor->deleteRuntime($project->getId(), $deployment->getId(), '-build'); + /** Update the build document */ $build->setAttribute('startTime', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); $build->setAttribute('endTime', $endTime); @@ -1072,15 +1074,9 @@ class Builds extends Action $envCommand = ''; $bundleCommand = ''; - if (!is_null($framework)) { - $adapter = ($framework['adapters'] ?? [])[$resource->getAttribute('adapter', '')] ?? null; - if (!is_null($adapter) && isset($adapter['envCommand'])) { - $envCommand = $adapter['envCommand']; - } - if (!is_null($adapter) && isset($adapter['bundleCommand'])) { - $bundleCommand = $adapter['bundleCommand']; - } + $envCommand = $framework['envCommand'] ?? ''; + $bundleCommand = $framework['bundleCommand'] ?? ''; } $commands[] = $envCommand; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php index cad4ac33a3..b3c0c9fb47 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -91,7 +91,7 @@ class Create extends Base ->callback([$this, 'action']); } - public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, string $installationId, ?string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Database $dbForPlatform) + public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, string $installationId, string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Database $dbForPlatform) { if (!empty($adapter)) { $configFramework = Config::getParam('frameworks')[$framework] ?? []; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php index c28fd58bc5..35e4fb07e3 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php @@ -98,7 +98,7 @@ class Update extends Base ->callback([$this, 'action']); } - public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, ?string $fallbackFile, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) + public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, string $fallbackFile, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github) { if (!empty($adapter)) { $configFramework = Config::getParam('frameworks')[$framework] ?? []; diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 2863606106..384ef27f6d 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -38,6 +38,8 @@ use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; use Appwrite\Utopia\Response\Model\Database; use Appwrite\Utopia\Response\Model\Deployment; +use Appwrite\Utopia\Response\Model\DetectionFramework; +use Appwrite\Utopia\Response\Model\DetectionRuntime; use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; @@ -45,8 +47,6 @@ use Appwrite\Utopia\Response\Model\Execution; use Appwrite\Utopia\Response\Model\File; use Appwrite\Utopia\Response\Model\Framework; use Appwrite\Utopia\Response\Model\FrameworkAdapter; -use Appwrite\Utopia\Response\Model\FrameworkDetection; -use Appwrite\Utopia\Response\Model\FrameworkProviderRepository; use Appwrite\Utopia\Response\Model\Func; use Appwrite\Utopia\Response\Model\Headers; use Appwrite\Utopia\Response\Model\HealthAntivirus; @@ -84,10 +84,10 @@ use Appwrite\Utopia\Response\Model\Preferences; use Appwrite\Utopia\Response\Model\Project; use Appwrite\Utopia\Response\Model\Provider; use Appwrite\Utopia\Response\Model\ProviderRepository; +use Appwrite\Utopia\Response\Model\ProviderRepositoryFramework; +use Appwrite\Utopia\Response\Model\ProviderRepositoryRuntime; use Appwrite\Utopia\Response\Model\Rule; use Appwrite\Utopia\Response\Model\Runtime; -use Appwrite\Utopia\Response\Model\RuntimeDetection; -use Appwrite\Utopia\Response\Model\RuntimeProviderRepository; use Appwrite\Utopia\Response\Model\Session; use Appwrite\Utopia\Response\Model\Site; use Appwrite\Utopia\Response\Model\Specification; @@ -250,14 +250,14 @@ class Response extends SwooleResponse public const MODEL_INSTALLATION_LIST = 'installationList'; public const MODEL_PROVIDER_REPOSITORY = 'providerRepository'; public const MODEL_PROVIDER_REPOSITORY_LIST = 'providerRepositoryList'; - public const MODEL_FRAMEWORK_PROVIDER_REPOSITORY = 'frameworkProviderRepository'; - public const MODEL_FRAMEWORK_PROVIDER_REPOSITORY_LIST = 'frameworkProviderRepositoryList'; - public const MODEL_RUNTIME_PROVIDER_REPOSITORY = 'runtimeProviderRepository'; - public const MODEL_RUNTIME_PROVIDER_REPOSITORY_LIST = 'runtimeProviderRepositoryList'; + public const MODEL_PROVIDER_REPOSITORY_FRAMEWORK = 'providerRepositoryFramework'; + public const MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST = 'providerRepositoryFrameworkList'; + public const MODEL_PROVIDER_REPOSITORY_RUNTIME = 'providerRepositoryRuntime'; + public const MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST = 'providerRepositoryRuntimeList'; public const MODEL_BRANCH = 'branch'; public const MODEL_BRANCH_LIST = 'branchList'; - public const MODEL_FRAMEWORK_DETECTION = 'frameworkDetection'; - public const MODEL_RUNTIME_DETECTION = 'runtimeDetection'; + public const MODEL_DETECTION_FRAMEWORK = 'detectionFramework'; + public const MODEL_DETECTION_RUNTIME = 'detectionRuntime'; public const MODEL_VCS_CONTENT = 'vcsContent'; public const MODEL_VCS_CONTENT_LIST = 'vcsContentList'; @@ -383,8 +383,8 @@ class Response extends SwooleResponse ->setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION)) ->setModel(new BaseList('Function Templates List', self::MODEL_TEMPLATE_FUNCTION_LIST, 'templates', self::MODEL_TEMPLATE_FUNCTION)) ->setModel(new BaseList('Installations List', self::MODEL_INSTALLATION_LIST, 'installations', self::MODEL_INSTALLATION)) - ->setModel(new BaseList('Framework Provider Repositories List', self::MODEL_FRAMEWORK_PROVIDER_REPOSITORY_LIST, 'frameworkProviderRepositories', self::MODEL_FRAMEWORK_PROVIDER_REPOSITORY)) - ->setModel(new BaseList('Runtime Provider Repositories List', self::MODEL_RUNTIME_PROVIDER_REPOSITORY_LIST, 'runtimeProviderRepositories', self::MODEL_RUNTIME_PROVIDER_REPOSITORY)) + ->setModel(new BaseList('Framework Provider Repositories List', self::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST, 'frameworkProviderRepositories', self::MODEL_PROVIDER_REPOSITORY_FRAMEWORK)) + ->setModel(new BaseList('Runtime Provider Repositories List', self::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST, 'runtimeProviderRepositories', self::MODEL_PROVIDER_REPOSITORY_RUNTIME)) ->setModel(new BaseList('Branches List', self::MODEL_BRANCH_LIST, 'branches', self::MODEL_BRANCH)) ->setModel(new BaseList('Frameworks List', self::MODEL_FRAMEWORK_LIST, 'frameworks', self::MODEL_FRAMEWORK)) ->setModel(new BaseList('Runtimes List', self::MODEL_RUNTIME_LIST, 'runtimes', self::MODEL_RUNTIME)) @@ -462,10 +462,10 @@ class Response extends SwooleResponse ->setModel(new TemplateVariable()) ->setModel(new Installation()) ->setModel(new ProviderRepository()) - ->setModel(new FrameworkProviderRepository()) - ->setModel(new RuntimeProviderRepository()) - ->setModel(new FrameworkDetection()) - ->setModel(new RuntimeDetection()) + ->setModel(new ProviderRepositoryFramework()) + ->setModel(new ProviderRepositoryRuntime()) + ->setModel(new DetectionFramework()) + ->setModel(new DetectionRuntime()) ->setModel(new VcsContent()) ->setModel(new Branch()) ->setModel(new Runtime()) diff --git a/src/Appwrite/Utopia/Response/Model/FrameworkDetection.php b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php similarity index 91% rename from src/Appwrite/Utopia/Response/Model/FrameworkDetection.php rename to src/Appwrite/Utopia/Response/Model/DetectionFramework.php index d0c666ae91..9aeb885f76 100644 --- a/src/Appwrite/Utopia/Response/Model/FrameworkDetection.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class FrameworkDetection extends Model +class DetectionFramework extends Model { public function __construct() { @@ -43,7 +43,7 @@ class FrameworkDetection extends Model */ public function getName(): string { - return 'FrameworkDetection'; + return 'DetectionFramework'; } /** @@ -53,6 +53,6 @@ class FrameworkDetection extends Model */ public function getType(): string { - return Response::MODEL_FRAMEWORK_DETECTION; + return Response::MODEL_DETECTION_FRAMEWORK; } } diff --git a/src/Appwrite/Utopia/Response/Model/RuntimeDetection.php b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php similarity index 90% rename from src/Appwrite/Utopia/Response/Model/RuntimeDetection.php rename to src/Appwrite/Utopia/Response/Model/DetectionRuntime.php index b79dccff9d..1c7c0be16b 100644 --- a/src/Appwrite/Utopia/Response/Model/RuntimeDetection.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class RuntimeDetection extends Model +class DetectionRuntime extends Model { public function __construct() { @@ -37,7 +37,7 @@ class RuntimeDetection extends Model */ public function getName(): string { - return 'RuntimeDetection'; + return 'DetectionRuntime'; } /** @@ -47,6 +47,6 @@ class RuntimeDetection extends Model */ public function getType(): string { - return Response::MODEL_RUNTIME_DETECTION; + return Response::MODEL_DETECTION_RUNTIME; } } diff --git a/src/Appwrite/Utopia/Response/Model/FrameworkProviderRepository.php b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php similarity index 65% rename from src/Appwrite/Utopia/Response/Model/FrameworkProviderRepository.php rename to src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php index 2ec75badb6..24556f4453 100644 --- a/src/Appwrite/Utopia/Response/Model/FrameworkProviderRepository.php +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class FrameworkProviderRepository extends ProviderRepository +class ProviderRepositoryFramework extends ProviderRepository { public function __construct() { @@ -12,7 +12,7 @@ class FrameworkProviderRepository extends ProviderRepository $this->addRule('framework', [ 'type' => self::TYPE_STRING, - 'description' => 'Auto-detected framework suggestion. Empty if getting response of getFramework().', + 'description' => 'Auto-detected framework. Empty if type is not "framework".', 'default' => '', 'example' => 'nextjs', ]); @@ -25,7 +25,7 @@ class FrameworkProviderRepository extends ProviderRepository */ public function getName(): string { - return 'FrameworkProviderRepository'; + return 'ProviderRepositoryFramework'; } /** @@ -35,6 +35,6 @@ class FrameworkProviderRepository extends ProviderRepository */ public function getType(): string { - return Response::MODEL_FRAMEWORK_PROVIDER_REPOSITORY; + return Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK; } } diff --git a/src/Appwrite/Utopia/Response/Model/RuntimeProviderRepository.php b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php similarity index 62% rename from src/Appwrite/Utopia/Response/Model/RuntimeProviderRepository.php rename to src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php index 5e0067d23f..ea20eeea47 100644 --- a/src/Appwrite/Utopia/Response/Model/RuntimeProviderRepository.php +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -class RuntimeProviderRepository extends ProviderRepository +class ProviderRepositoryRuntime extends ProviderRepository { public function __construct() { @@ -12,9 +12,9 @@ class RuntimeProviderRepository extends ProviderRepository $this->addRule('runtime', [ 'type' => self::TYPE_STRING, - 'description' => 'Auto-detected runtime suggestion. Empty if getting response of getRuntime().', + 'description' => 'Auto-detected runtime. Empty if type is not "runtime".', 'default' => '', - 'example' => 'node', + 'example' => 'node-22', ]); } @@ -25,7 +25,7 @@ class RuntimeProviderRepository extends ProviderRepository */ public function getName(): string { - return 'RuntimeProviderRepository'; + return 'ProviderRepositoryRuntime'; } /** @@ -35,6 +35,6 @@ class RuntimeProviderRepository extends ProviderRepository */ public function getType(): string { - return Response::MODEL_RUNTIME_PROVIDER_REPOSITORY; + return Response::MODEL_PROVIDER_REPOSITORY_RUNTIME; } } diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index a105503088..9702db43de 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -135,9 +135,9 @@ class Executor * @param string $projectId * @param string $deploymentId */ - public function deleteRuntime(string $projectId, string $deploymentId) + public function deleteRuntime(string $projectId, string $deploymentId, string $suffix = '') { - $runtimeId = "$projectId-$deploymentId"; + $runtimeId = "$projectId-$deploymentId" . $suffix; $route = "/runtimes/$runtimeId"; $response = $this->call(self::METHOD_DELETE, $route, [ @@ -249,7 +249,7 @@ class Executor return $response['body']; } - public function executeCommand( + public function createCommand( string $deploymentId, string $projectId, string $command, diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 162ad9c091..fd5f9e7e66 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -362,40 +362,168 @@ class SitesCustomServerTest extends Scope $this->cleanupSite($siteId); } - public function testRenderingDetectionSSR(): void + public function testAdapterDetectionAstroSSR(): void { $siteId = $this->setupSite([ 'siteId' => ID::unique(), - 'name' => 'Astro site', + 'name' => 'Astro SSR site', 'framework' => 'astro', - 'buildRuntime' => 'ssr-22', + 'buildRuntime' => 'node-22', 'outputDirectory' => './dist', 'buildCommand' => 'npm run build', 'installCommand' => 'npm install', ]); - $this->assertNotEmpty($siteId); + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); $deploymentId = $this->setupDeployment($siteId, [ 'code' => $this->packageSite('astro'), 'activate' => 'true' ]); - $this->assertNotEmpty($deploymentId); - $domain = $this->getSiteDomain($siteId); + $site = $this->getSite($siteId); + $this->assertEquals('ssr', $site['body']['adapter']); + $proxyClient = new Client(); $proxyClient->setEndpoint('http://' . $domain); - $response = $proxyClient->call(Client::METHOD_GET, '/'); - $this->assertEquals(200, $response['headers']['status-code']); $this->cleanupSite($siteId); } + public function testAdapterDetectionAstroStatic(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro static site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro-static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionStatic(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => '', + 'buildCommand' => '', + 'installCommand' => '', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionStaticSPA(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => '', + 'buildCommand' => '', + 'installCommand' => '', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertArrayHasKey('fallbackFile', $site['body']); + $this->assertEmpty($site['body']['adapter']); + $this->assertEmpty($site['body']['fallbackFile']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-single-file'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + $this->assertEquals('main.html', $site['body']['fallbackFile']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Main page', $response['body']); + $response = $proxyClient->call(Client::METHOD_GET, '/something'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Main page', $response['body']); + + $this->cleanupSite($siteId); + } + public function testListSites(): void { /** diff --git a/tests/e2e/Services/VCS/VCSConsoleClientTest.php b/tests/e2e/Services/VCS/VCSConsoleClientTest.php index f60b91c27f..13c3ddb251 100644 --- a/tests/e2e/Services/VCS/VCSConsoleClientTest.php +++ b/tests/e2e/Services/VCS/VCSConsoleClientTest.php @@ -154,7 +154,7 @@ class VCSConsoleClientTest extends Scope * Test for FAILURE */ - $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/randomRepositoryId/frameworks', array_merge([ + $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], 'content-type' => 'application/json', ], $this->getHeaders()), [ @@ -165,8 +165,6 @@ class VCSConsoleClientTest extends Scope $this->assertEquals(404, $framework['headers']['status-code']); } - // TODO: Change search to provideScenarios - /** * @depends testGitHubAuthorize */ @@ -248,7 +246,6 @@ class VCSConsoleClientTest extends Scope * Test for SUCCESS */ - //runtimes $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -262,28 +259,39 @@ class VCSConsoleClientTest extends Scope $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['provider'], 'github'); $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['runtime'], 'node-22'); - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][1]['name'], 'templates-for-functions'); - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][1]['runtime'], ''); - - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][2]['name'], 'function1.4'); - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][2]['runtime'], 'node-22'); - - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][3]['name'], 'appwrite'); - $this->assertEquals($repositories['body']['runtimeProviderRepositories'][3]['runtime'], 'php-8.3'); + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'function1.4', + 'type' => 'runtime' + ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'function1.4'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'node-2'); $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'rub', + 'search' => 'appwrite', 'type' => 'runtime' ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'appwrite'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'php-8.3'); + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'ruby-starter', + 'type' => 'runtime' + ]); $this->assertEquals(200, $searchedRepositories['headers']['status-code']); $this->assertEquals($searchedRepositories['body']['total'], 1); $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'ruby-starter'); $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'ruby-3.3'); - // frameworks $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -292,20 +300,23 @@ class VCSConsoleClientTest extends Scope $this->assertEquals(200, $repositories['headers']['status-code']); $this->assertEquals($repositories['body']['total'], 4); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['name'], 'starter-for-svelte'); $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['organization'], 'appwrite-test'); $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['provider'], 'github'); $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['framework'], 'sveltekit'); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][1]['name'], 'templates-for-functions'); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][1]['framework'], 'other'); + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'appwrite', + 'type' => 'runtime' + ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'appwrite'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'other'); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][2]['name'], 'function1.4'); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][2]['framework'], 'other'); - - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][3]['name'], 'appwrite'); - $this->assertEquals($repositories['body']['frameworkProviderRepositories'][3]['framework'], 'other'); + // TODO: If you are about to add another check, rewrite this to @provideScenarios /** * Test for FAILURE diff --git a/tests/resources/sites/astro-static/astro.config.mjs b/tests/resources/sites/astro-static/astro.config.mjs new file mode 100644 index 0000000000..20b0b8e2ba --- /dev/null +++ b/tests/resources/sites/astro-static/astro.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'astro/config'; + +export default defineConfig({ +}); diff --git a/tests/resources/sites/astro-static/package.json b/tests/resources/sites/astro-static/package.json new file mode 100644 index 0000000000..147dcf1f07 --- /dev/null +++ b/tests/resources/sites/astro-static/package.json @@ -0,0 +1,14 @@ +{ + "name": "my-astro-app", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "astro": "^5.2.5" + } +} diff --git a/tests/resources/sites/astro-static/src/pages/index.astro b/tests/resources/sites/astro-static/src/pages/index.astro new file mode 100644 index 0000000000..0b4f43c3d6 --- /dev/null +++ b/tests/resources/sites/astro-static/src/pages/index.astro @@ -0,0 +1,10 @@ + + + + + + Astro static + + + + diff --git a/tests/resources/sites/static-single-file/main.html b/tests/resources/sites/static-single-file/main.html new file mode 100644 index 0000000000..2615f0c820 --- /dev/null +++ b/tests/resources/sites/static-single-file/main.html @@ -0,0 +1,10 @@ + + + + + + Main page + + + + \ No newline at end of file