diff --git a/composer.json b/composer.json index 6312243e32..d82f8dd7a8 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,29 @@ "Appwrite\\Tests\\": "tests/extensions" } }, + "repositories": [ + { + "type": "package", + "package": { + "name": "utopia-php/console", + "version": "dev-feat/command-validation", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/console.git", + "reference": "feat/command-validation" + }, + "require": { + "php": ">=8.0", + "utopia-php/validators": "^0.2.0" + }, + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + } + } + } + ], "minimum-stability": "dev", "prefer-stable": true, "require": { @@ -60,7 +83,7 @@ "utopia-php/cli": "0.23.*", "utopia-php/compression": "0.1.*", "utopia-php/config": "1.*", - "utopia-php/console": "0.1.*", + "utopia-php/console": "dev-feat/command-validation as 0.1.999", "utopia-php/database": "5.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "1.*", diff --git a/composer.lock b/composer.lock index b1d559f87d..91a00bd140 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": "c5ae97637fd0ec0a950044d1c33677ea", + "content-hash": "18aa5eb79915f6d9d8be65ac0a5f8e73", "packages": [ { "name": "adhocore/jwt", @@ -3802,51 +3802,22 @@ }, { "name": "utopia-php/console", - "version": "0.1.1", + "version": "dev-feat/command-validation", "source": { "type": "git", "url": "https://github.com/utopia-php/console.git", - "reference": "d298e43960780e6d76e66de1228c75dc81220e3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/console/zipball/d298e43960780e6d76e66de1228c75dc81220e3e", - "reference": "d298e43960780e6d76e66de1228c75dc81220e3e", - "shasum": "" + "reference": "feat/command-validation" }, "require": { - "php": ">=8.0" - }, - "require-dev": { - "laravel/pint": "1.2.*", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.3", - "squizlabs/php_codesniffer": "^3.6", - "swoole/ide-helper": "4.8.8" + "php": ">=8.0", + "utopia-php/validators": "^0.2.0" }, "type": "library", "autoload": { "psr-4": { "Utopia\\": "src/" } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Console helpers for logging, prompting, and executing commands", - "keywords": [ - "cli", - "console", - "php", - "terminal", - "utopia" - ], - "support": { - "issues": "https://github.com/utopia-php/console/issues", - "source": "https://github.com/utopia-php/console/tree/0.1.1" - }, - "time": "2026-02-10T10:20:29+00:00" + } }, { "name": "utopia-php/database", @@ -8440,9 +8411,18 @@ "time": "2024-11-07T12:36:22+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/console", + "version": "dev-feat/command-validation", + "alias": "0.1.999", + "alias_normalized": "0.1.999.0" + } + ], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "utopia-php/console": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/src/Appwrite/Certificates/LetsEncrypt.php b/src/Appwrite/Certificates/LetsEncrypt.php index 001d04941e..900f08a819 100644 --- a/src/Appwrite/Certificates/LetsEncrypt.php +++ b/src/Appwrite/Certificates/LetsEncrypt.php @@ -4,6 +4,7 @@ namespace Appwrite\Certificates; use Appwrite\Certificates\Exception\CertificateStatus as CertificateStatusException; use Exception; +use Utopia\Command; use Utopia\Console; use Utopia\Database\DateTime; use Utopia\Http\Http; @@ -24,17 +25,22 @@ class LetsEncrypt implements Adapter $stdout = ''; $stderr = ''; - $staging = (Http::isProduction()) ? '' : ' --dry-run'; - $exit = Console::execute( - "certbot certonly -v --webroot --noninteractive --agree-tos{$staging}" - . " --email " . $this->email - . " --cert-name " . $certName - . " -w " . APP_STORAGE_CERTIFICATES - . " -d {$domain}", - '', - $stdout, - $stderr - ); + $issueCommand = (new Command('certbot')) + ->argument('certonly') + ->flag('-v') + ->flag('--webroot') + ->flag('--noninteractive') + ->flag('--agree-tos') + ->option('--email', $this->email) + ->option('--cert-name', $certName) + ->option('-w', APP_STORAGE_CERTIFICATES) + ->option('-d', $domain); + + if (! Http::isProduction()) { + $issueCommand->flag('--dry-run'); + } + + $exit = Console::execute($issueCommand, '', $stdout, $stderr); // Unexpected error, usually 5XX, API limits, ... if ($exit !== 0) { diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 0071b03d2d..0668e5ceb0 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -18,6 +18,7 @@ use Exception; use Executor\Executor; use Swoole\Coroutine as Co; use Utopia\Cache\Cache; +use Utopia\Command; use Utopia\Config\Config; use Utopia\Console; use Utopia\Database\Database; @@ -307,10 +308,24 @@ class Builds extends Action throw new \Exception('Unable to clone code repository: ' . $stderr); } - Console::execute('find ' . \escapeshellarg($tmpTemplateDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); + $cleanupGitDirectoryCommand = (new Command('find')) + ->argument($tmpTemplateDirectory) + ->argument('-type') + ->argument('d') + ->argument('-name') + ->argument('.git') + ->argument('-exec') + ->argument('rm') + ->argument('-rf') + ->argument('{}') + ->argument('+'); + Console::execute($cleanupGitDirectoryCommand, '', $stdout, $stderr); // Ensure directories - Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); + $ensureTemplateDirectoryCommand = (new Command('mkdir')) + ->flag('-p') + ->argument($tmpTemplateDirectory . '/' . $templateRootDirectory); + Console::execute($ensureTemplateDirectoryCommand, '', $stdout, $stderr); $tmpPathFile = $tmpTemplateDirectory . '/code.tar.gz'; @@ -320,8 +335,14 @@ class Builds extends Action $tmpTemplateDirectory .= '/'; } - $tarParamDirectory = \escapeshellarg($tmpTemplateDirectory . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory)); - Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax + $tarParamDirectory = $tmpTemplateDirectory . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory); + $archiveCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->flag('-czf') + ->argument($tmpPathFile) + ->option('-C', $tarParamDirectory) + ->argument('.'); + Console::execute($archiveCommand, '', $stdout, $stderr); $source = $device->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $result = $localDevice->transfer($tmpPathFile, $source, $device); @@ -330,7 +351,10 @@ class Builds extends Action throw new \Exception('Unable to move file'); } - Console::execute('rm -rf ' . \escapeshellarg($tmpTemplateDirectory), '', $stdout, $stderr); + $removeTemplateDirectoryCommand = (new Command('rm')) + ->flag('-rf') + ->argument($tmpTemplateDirectory); + Console::execute($removeTemplateDirectoryCommand, '', $stdout, $stderr); $directorySize = $device->getFileSize($source); $deployment @@ -377,7 +401,10 @@ class Builds extends Action $stdout = ''; $stderr = ''; - Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds/' . $deploymentId), '', $stdout, $stderr); + $ensureBuildDirectoryCommand = (new Command('mkdir')) + ->flag('-p') + ->argument('/tmp/builds/' . $deploymentId); + Console::execute($ensureBuildDirectoryCommand, '', $stdout, $stderr); if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { $this->cancelDeployment($deployment->getId(), $dbForProject, $queueForRealtime); @@ -398,7 +425,10 @@ class Builds extends Action $rootDirectoryWithoutSpaces = str_replace(' ', '', $rootDirectory); $from = $tmpDirectory . '/' . $rootDirectory; $to = $tmpDirectory . '/' . $rootDirectoryWithoutSpaces; - $exit = Console::execute('mv ' . \escapeshellarg($from) . ' ' . \escapeshellarg($to), '', $stdout, $stderr); + $moveRootDirectoryCommand = (new Command('mv')) + ->argument($from) + ->argument($to); + $exit = Console::execute($moveRootDirectoryCommand, '', $stdout, $stderr); if ($exit !== 0) { throw new \Exception('Unable to move function with spaces' . $stderr); @@ -429,20 +459,67 @@ class Builds extends Action } // Ensure directories - Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); - Console::execute('mkdir -p ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); + $ensureTemplateDirectoryCommand = (new Command('mkdir')) + ->flag('-p') + ->argument($tmpTemplateDirectory . '/' . $templateRootDirectory); + Console::execute($ensureTemplateDirectoryCommand, '', $stdout, $stderr); + + $ensureRootDirectoryCommand = (new Command('mkdir')) + ->flag('-p') + ->argument($tmpDirectory . '/' . $rootDirectory); + Console::execute($ensureRootDirectoryCommand, '', $stdout, $stderr); // Merge template into user repo - Console::execute('rsync -av --exclude \'.git\' ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory . '/') . ' ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); + $syncTemplateCommand = (new Command('rsync')) + ->flag('-av') + ->option('--exclude', '.git') + ->argument($tmpTemplateDirectory . '/' . $templateRootDirectory . '/') + ->argument($tmpDirectory . '/' . $rootDirectory); + Console::execute($syncTemplateCommand, '', $stdout, $stderr); // Commit and push - $exit = Console::execute('git config --global user.email ' . \escapeshellarg(APP_VCS_GITHUB_EMAIL) . ' && git config --global user.name ' . \escapeshellarg(APP_VCS_GITHUB_USERNAME) . ' && cd ' . \escapeshellarg($tmpDirectory) . ' && git checkout -b ' . \escapeshellarg($branchName) . ' && git add . && git commit -m "Create ' . \escapeshellarg($resource->getAttribute('name', '')) . ' function" && git push origin ' . \escapeshellarg($branchName), '', $stdout, $stderr); + $commitMessage = "Create '" . $resource->getAttribute('name', '') . "' function"; + $pushTemplateCommand = Command::and( + (new Command('git')) + ->argument('config') + ->flag('--global') + ->argument('user.email') + ->argument(APP_VCS_GITHUB_EMAIL), + (new Command('git')) + ->argument('config') + ->flag('--global') + ->argument('user.name') + ->argument(APP_VCS_GITHUB_USERNAME), + (new Command('git')) + ->option('-C', $tmpDirectory) + ->argument('checkout') + ->flag('-b') + ->argument($branchName), + (new Command('git')) + ->option('-C', $tmpDirectory) + ->argument('add') + ->argument('.'), + (new Command('git')) + ->option('-C', $tmpDirectory) + ->argument('commit') + ->option('-m', $commitMessage), + (new Command('git')) + ->option('-C', $tmpDirectory) + ->argument('push') + ->argument('origin') + ->argument($branchName) + ); + $exit = Console::execute($pushTemplateCommand, '', $stdout, $stderr); if ($exit !== 0) { throw new \Exception('Unable to push code repository: ' . $stderr); } - $exit = Console::execute('cd ' . \escapeshellarg($tmpDirectory) . ' && git rev-parse HEAD', '', $stdout, $stderr); + $providerCommitHashCommand = (new Command('git')) + ->option('-C', $tmpDirectory) + ->argument('rev-parse') + ->argument('HEAD'); + $exit = Console::execute($providerCommitHashCommand, '', $stdout, $stderr); if ($exit !== 0) { throw new \Exception('Unable to get vcs commit SHA: ' . $stderr); @@ -489,10 +566,27 @@ class Builds extends Action throw new \Exception('Repository directory size should be less than ' . number_format($sizeLimit / (1000 * 1000), 2) . ' MBs.'); } - Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); + $cleanupGitDirectoryCommand = (new Command('find')) + ->argument($tmpDirectory) + ->argument('-type') + ->argument('d') + ->argument('-name') + ->argument('.git') + ->argument('-exec') + ->argument('rm') + ->argument('-rf') + ->argument('{}') + ->argument('+'); + Console::execute($cleanupGitDirectoryCommand, '', $stdout, $stderr); $tarParamDirectory = '/tmp/builds/' . $deploymentId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); - Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax + $archiveCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->flag('-czf') + ->argument($tmpPathFile) + ->option('-C', $tarParamDirectory) + ->argument('.'); + Console::execute($archiveCommand, '', $stdout, $stderr); $source = $device->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $result = $localDevice->transfer($tmpPathFile, $source, $device); @@ -501,7 +595,10 @@ class Builds extends Action throw new \Exception('Unable to move file'); } - Console::execute('rm -rf ' . \escapeshellarg($tmpPath), '', $stdout, $stderr); + $removeBuildDirectoryCommand = (new Command('rm')) + ->flag('-rf') + ->argument($tmpPath); + Console::execute($removeBuildDirectoryCommand, '', $stdout, $stderr); $directorySize = $device->getFileSize($source); diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index 42976cda84..99eef3b872 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -6,6 +6,7 @@ use Appwrite\Tests\Async; use Appwrite\Tests\Async\Exceptions\Critical; use CURLFile; use Tests\E2E\Client; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -282,7 +283,14 @@ trait FunctionsBase $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/$function"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $this->stdout, $this->stderr); + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $this->stdout, $this->stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index 06044d9984..3dc12274ac 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -6,6 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -686,12 +687,25 @@ class FunctionsConsoleClientTest extends Scope $stdout = ''; $stderr = ''; - $code = Console::execute("docker exec appwrite task-time-travel --projectId={$this->getProject()['$id']} --resourceType=deployment --resourceId={$deploymentIdInactiveOld} --createdAt=2020-01-01T00:00:00Z", '', $stdout, $stderr); + $timeTravelCommand = (new Command('docker')) + ->argument('exec') + ->argument('appwrite') + ->argument('task-time-travel') + ->argument("--projectId={$this->getProject()['$id']}") + ->argument('--resourceType=deployment') + ->argument("--resourceId={$deploymentIdInactiveOld}") + ->argument('--createdAt=2020-01-01T00:00:00Z'); + $code = Console::execute($timeTravelCommand, '', $stdout, $stderr); $this->assertSame(0, $code, "Time-travel command failed with code $code: $stderr ($stdout)"); $stdout = ''; $stderr = ''; - $code = Console::execute("docker exec appwrite maintenance --type=trigger", '', $stdout, $stderr); + $maintenanceCommand = (new Command('docker')) + ->argument('exec') + ->argument('appwrite') + ->argument('maintenance') + ->argument('--type=trigger'); + $code = Console::execute($maintenanceCommand, '', $stdout, $stderr); $this->assertSame(0, $code, "Maintenance command failed with code $code: $stderr ($stdout)"); $this->assertEventually(function () use ($functionId) { diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index ba518ee0b6..50a7c9b005 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -9,6 +9,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -991,7 +992,15 @@ class FunctionsCustomServerTest extends Scope */ $folder = 'large'; $code = realpath(__DIR__ . '/../../../resources/functions') . "/$folder/code.tar.gz"; - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $this->stdout, $this->stderr); + $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/$folder"; + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($code) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $this->stdout, $this->stderr); $chunkSize = 5 * 1024 * 1024; $handle = @fopen($code, "rb"); diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index c42679018e..eacfd22814 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -3,6 +3,7 @@ namespace Tests\E2E\Services\GraphQL; use CURLFile; +use Utopia\Command; use Utopia\Console; trait Base @@ -3464,7 +3465,14 @@ trait Base $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/$function"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $this->stdout, $this->stderr); + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $this->stdout, $this->stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index 9e9ce2fbcd..37febbf680 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -9,6 +9,7 @@ use Tests\E2E\Client; use Tests\E2E\General\UsageTest; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Services\Functions\FunctionsBase; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Database; use Utopia\Database\Helpers\ID; @@ -1188,7 +1189,14 @@ trait MigrationsBase $folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $stdout, $stderr); + $packageSiteCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageSiteCommand, '', $stdout, $stderr); return new CURLFile($tarPath, 'application/x-gzip', \basename($tarPath)); } diff --git a/tests/e2e/Services/Project/VariablesBase.php b/tests/e2e/Services/Project/VariablesBase.php index b1f8ed61b9..8dc09c86f1 100644 --- a/tests/e2e/Services/Project/VariablesBase.php +++ b/tests/e2e/Services/Project/VariablesBase.php @@ -6,6 +6,7 @@ use Appwrite\Tests\Async; use Appwrite\Tests\Async\Exceptions\Critical; use CURLFile; use Tests\E2E\Client; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -1091,7 +1092,14 @@ trait VariablesBase $folderPath = realpath(__DIR__ . '/../../../resources/' . $type) . "/$name"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $this->stdout, $this->stderr); + $packageCodeCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageCodeCommand, '', $this->stdout, $this->stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); diff --git a/tests/e2e/Services/ProjectWebhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/ProjectWebhooks/WebhooksCustomServerTest.php index 9085733b70..07beb97128 100644 --- a/tests/e2e/Services/ProjectWebhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/ProjectWebhooks/WebhooksCustomServerTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -83,7 +84,15 @@ class WebhooksCustomServerTest extends Scope $stdout = ''; $folder = 'timeout'; $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $stdout, $stderr); + $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}"; + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($code) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $stdout, $stderr); // Create variable first $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ @@ -734,7 +743,15 @@ class WebhooksCustomServerTest extends Scope $stdout = ''; $folder = 'timeout'; $code = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}/code.tar.gz"; - Console::execute('cd ' . realpath(__DIR__ . "/../../../resources/functions") . "/{$folder} && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $stdout, $stderr); + $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/{$folder}"; + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($code) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $stdout, $stderr); $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ 'content-type' => 'multipart/form-data', diff --git a/tests/e2e/Services/Proxy/ProxyBase.php b/tests/e2e/Services/Proxy/ProxyBase.php index 59a853bfc8..809c9f9dec 100644 --- a/tests/e2e/Services/Proxy/ProxyBase.php +++ b/tests/e2e/Services/Proxy/ProxyBase.php @@ -6,6 +6,7 @@ use Appwrite\ID; use Appwrite\Tests\Async; use CURLFile; use Tests\E2E\Client; +use Utopia\Command; use Utopia\Console; trait ProxyBase @@ -271,7 +272,14 @@ trait ProxyBase $folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $stdout, $stderr); + $packageSiteCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageSiteCommand, '', $stdout, $stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); @@ -288,7 +296,14 @@ trait ProxyBase $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/$function"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $stdout, $stderr); + $packageFunctionCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageFunctionCommand, '', $stdout, $stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); diff --git a/tests/e2e/Services/Sites/SitesBase.php b/tests/e2e/Services/Sites/SitesBase.php index c3377faad8..23d0b608f4 100644 --- a/tests/e2e/Services/Sites/SitesBase.php +++ b/tests/e2e/Services/Sites/SitesBase.php @@ -6,6 +6,7 @@ use Appwrite\Tests\Async; use Appwrite\Tests\Async\Exceptions\Critical; use CURLFile; use Tests\E2E\Client; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; @@ -54,11 +55,19 @@ trait SitesBase throw new Critical('Deployment failed: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); } - Console::execute("docker inspect openruntimes-executor --format='{{.State.ExitCode}}'", '', $this->stdout, $this->stderr); + $inspectExecutorCommand = (new Command('docker')) + ->argument('inspect') + ->argument('openruntimes-executor') + ->option('--format', '{{.State.ExitCode}}'); + Console::execute($inspectExecutorCommand, '', $this->stdout, $this->stderr); if (\trim($this->stdout) !== '0') { $msg = 'Executor has a problem: ' . $this->stderr . ' (' . $this->stdout . '), current status: '; - Console::execute("docker compose logs openruntimes-executor", '', $this->stdout, $this->stderr); + $executorLogsCommand = (new Command('docker')) + ->argument('compose') + ->argument('logs') + ->argument('openruntimes-executor'); + Console::execute($executorLogsCommand, '', $this->stdout, $this->stderr); $msg .= $this->stdout . ' (' . $this->stderr . ')'; throw new Critical($msg . json_encode($deployment['body'], JSON_PRETTY_PRINT)); @@ -241,7 +250,14 @@ trait SitesBase $folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site"; $tarPath = "$folderPath/code.tar.gz"; - Console::execute("cd $folderPath && tar --exclude code.tar.gz --exclude node_modules -czf code.tar.gz .", '', $this->stdout, $this->stderr); + $packageSiteCommand = (new Command('tar')) + ->option('--exclude', 'code.tar.gz') + ->option('--exclude', 'node_modules') + ->flag('-czf') + ->argument($tarPath) + ->option('-C', $folderPath) + ->argument('.'); + Console::execute($packageSiteCommand, '', $this->stdout, $this->stderr); if (filesize($tarPath) > 1024 * 1024 * 5) { throw new \Exception('Code package is too large. Use the chunked upload method instead.'); diff --git a/tests/e2e/Services/Sites/SitesConsoleClientTest.php b/tests/e2e/Services/Sites/SitesConsoleClientTest.php index 2e0e1a892d..d6cab6a8a3 100644 --- a/tests/e2e/Services/Sites/SitesConsoleClientTest.php +++ b/tests/e2e/Services/Sites/SitesConsoleClientTest.php @@ -7,6 +7,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideConsole; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Helpers\ID; @@ -180,12 +181,25 @@ class SitesConsoleClientTest extends Scope $stdout = ''; $stderr = ''; - $code = Console::execute("docker exec appwrite task-time-travel --projectId={$this->getProject()['$id']} --resourceType=deployment --resourceId={$deploymentIdInactiveOld} --createdAt=2020-01-01T00:00:00Z", '', $stdout, $stderr); + $timeTravelCommand = (new Command('docker')) + ->argument('exec') + ->argument('appwrite') + ->argument('task-time-travel') + ->argument("--projectId={$this->getProject()['$id']}") + ->argument('--resourceType=deployment') + ->argument("--resourceId={$deploymentIdInactiveOld}") + ->argument('--createdAt=2020-01-01T00:00:00Z'); + $code = Console::execute($timeTravelCommand, '', $stdout, $stderr); $this->assertSame(0, $code, "Time-travel command failed with code $code: $stderr ($stdout)"); $stdout = ''; $stderr = ''; - $code = Console::execute("docker exec appwrite maintenance --type=trigger", '', $stdout, $stderr); + $maintenanceCommand = (new Command('docker')) + ->argument('exec') + ->argument('appwrite') + ->argument('maintenance') + ->argument('--type=trigger'); + $code = Console::execute($maintenanceCommand, '', $stdout, $stderr); $this->assertSame(0, $code, "Maintenance command failed with code $code: $stderr ($stdout)"); $this->assertEventually(function () use ($siteId) { diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 69dbd7fdf0..b9e1fa1510 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -9,6 +9,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; +use Utopia\Command; use Utopia\Console; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -2942,7 +2943,10 @@ class SitesCustomServerTest extends Scope $stdout = ''; $stderr = ''; $folderPath = realpath(__DIR__ . '/../../../resources/sites') . '/empty'; - Console::execute("mkdir -p $folderPath", '', $stdout, $stderr); + $createEmptySiteDirectoryCommand = (new Command('mkdir')) + ->flag('-p') + ->argument($folderPath); + Console::execute($createEmptySiteDirectoryCommand, '', $stdout, $stderr); $deployment = $this->createDeployment($siteId, [ 'code' => $this->packageSite('empty'),