Refactor command execution to use Utopia\Command

This commit is contained in:
Torsten Dittmann
2026-04-17 18:31:48 +04:00
parent eddd159af8
commit 03be7ade3d
15 changed files with 308 additions and 81 deletions
+24 -1
View File
@@ -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.*",
Generated
+17 -37
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": "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": {
+17 -11
View File
@@ -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) {
@@ -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);
@@ -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.');
@@ -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) {
@@ -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");
+9 -1
View File
@@ -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.');
@@ -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));
}
+9 -1
View File
@@ -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.');
@@ -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',
+17 -2
View File
@@ -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.');
+19 -3
View File
@@ -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.');
@@ -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) {
@@ -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'),