From f164676b4427c5ae605666f38afffb0474000b65 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:15:31 -0700 Subject: [PATCH 1/5] Fix install template paths --- src/Appwrite/Platform/Tasks/Install.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 219a03129d..c15dddeccd 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -198,8 +198,8 @@ class Install extends Action } } - $templateForCompose = new View(__DIR__ . '/../views/install/compose.phtml'); - $templateForEnv = new View(__DIR__ . '/../views/install/env.phtml'); + $templateForCompose = new View(__DIR__ . '/../../../../app/views/install/compose.phtml'); + $templateForEnv = new View(__DIR__ . '/../../../../app/views/install/env.phtml'); $templateForCompose ->setParam('httpPort', $httpPort) From 1989ff873ec80dc2b7de05fc2bc1ad541b7be99f Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:16:36 -0700 Subject: [PATCH 2/5] Fix install analytics --- src/Appwrite/Platform/Tasks/Install.php | 27 ++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index c15dddeccd..4af3cc9d4f 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -6,7 +6,8 @@ use Appwrite\Auth\Auth; use Appwrite\Docker\Compose; use Appwrite\Docker\Env; use Appwrite\Utopia\View; -use Utopia\Analytics\GoogleAnalytics; +use Utopia\Analytics\Adapter\GoogleAnalytics; +use Utopia\Analytics\Event; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Validator\Text; @@ -215,14 +216,22 @@ class Install extends Action if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::exit(1); } if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::exit(1); } @@ -243,13 +252,21 @@ class Install extends Action if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::error($message); Console::error($stderr); Console::exit($exit); } else { $message = 'Appwrite installed successfully'; - $analytics->createEvent('install/server', 'install', APP_VERSION_STABLE . ' - ' . $message); + $event = new Event(); + $event->setName(APP_VERSION_STABLE . ' - ' . $message) + ->addProp('category', 'install/server') + ->addProp('action', 'install'); + $analytics->createEvent($event); Console::success($message); } } From c32f8e49e265fb69455045fbc8977061b506ed5e Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:21:34 -0700 Subject: [PATCH 3/5] Make the install path a class property This makes it so the property can be used by subclasses. --- src/Appwrite/Platform/Tasks/Install.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 4af3cc9d4f..f8509799b9 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -15,6 +15,8 @@ use Utopia\Platform\Action; class Install extends Action { + protected string $path = '/usr/src/code/appwrite'; + public static function getName(): string { return 'install'; @@ -51,7 +53,6 @@ class Install extends Action * 6. Run data migration */ $config = Config::getParam('variables'); - $path = '/usr/src/code/appwrite'; $defaultHTTPPort = '80'; $defaultHTTPSPort = '443'; $vars = []; @@ -71,19 +72,19 @@ class Install extends Action Console::success('Starting Appwrite installation...'); // Create directory with write permissions - if (null !== $path && !\file_exists(\dirname($path))) { - if (!@\mkdir(\dirname($path), 0755, true)) { - Console::error('Can\'t create directory ' . \dirname($path)); + if (null !== $this->path && !\file_exists(\dirname($this->path))) { + if (!@\mkdir(\dirname($this->path), 0755, true)) { + Console::error('Can\'t create directory ' . \dirname($this->path)); Console::exit(1); } } - $data = @file_get_contents($path . '/docker-compose.yml'); + $data = @file_get_contents($this->path . '/docker-compose.yml'); if ($data !== false) { $time = \time(); Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); - file_put_contents($path . '/docker-compose.yml.' . $time . '.backup', $data); + file_put_contents($this->path . '/docker-compose.yml.' . $time . '.backup', $data); $compose = new Compose($data); $appwrite = $compose->getService('appwrite'); $oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null; @@ -117,11 +118,11 @@ class Install extends Action } } - $data = @file_get_contents($path . '/.env'); + $data = @file_get_contents($this->path . '/.env'); if ($data !== false) { // Fetch all env vars from previous .env file Console::info('Env file found, creating backup: .env.' . $time . '.backup'); - file_put_contents($path . '/.env.' . $time . '.backup', $data); + file_put_contents($this->path . '/.env.' . $time . '.backup', $data); $env = new Env($data); foreach ($env->list() as $key => $value) { @@ -214,7 +215,7 @@ class Install extends Action ->setParam('vars', $input) ; - if (!file_put_contents($path . '/docker-compose.yml', $templateForCompose->render(false))) { + if (!file_put_contents($this->path . '/docker-compose.yml', $templateForCompose->render(false))) { $message = 'Failed to save Docker Compose file'; $event = new Event(); $event->setName(APP_VERSION_STABLE . ' - ' . $message) @@ -225,7 +226,7 @@ class Install extends Action Console::exit(1); } - if (!file_put_contents($path . '/.env', $templateForEnv->render(false))) { + if (!file_put_contents($this->path . '/.env', $templateForEnv->render(false))) { $message = 'Failed to save environment variables file'; $event = new Event(); $event->setName(APP_VERSION_STABLE . ' - ' . $message) @@ -246,9 +247,9 @@ class Install extends Action } } - Console::log("Running \"docker compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes\""); + Console::log("Running \"docker compose -f {$this->path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes\""); - $exit = Console::execute("${env} docker compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); + $exit = Console::execute("${env} docker compose -f {$this->path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr); if ($exit !== 0) { $message = 'Failed to install Appwrite dockers'; From d8ea72b49eb865ef5ded9a6c17655ea8bc9d6783 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 24 Jul 2023 15:34:04 -0700 Subject: [PATCH 4/5] Create a dedicated upgrade task Before, we used the same command for both installation and upgrades. This lead to problems because developers would try to upgrade in the wrong folder and end up creating a new installation. This new upgrade command validates the existence of an existing installation before proceeding with the upgrade to ensure no new installation is created when upgrading. --- bin/upgrade | 3 ++ src/Appwrite/Platform/Services/Tasks.php | 2 ++ src/Appwrite/Platform/Tasks/Upgrade.php | 42 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100755 bin/upgrade create mode 100644 src/Appwrite/Platform/Tasks/Upgrade.php diff --git a/bin/upgrade b/bin/upgrade new file mode 100755 index 0000000000..ce32b9ca30 --- /dev/null +++ b/bin/upgrade @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/cli.php upgrade $@ \ No newline at end of file diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 10c573da42..bc8d1bbc72 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -22,6 +22,7 @@ use Appwrite\Platform\Tasks\VolumeSync; use Appwrite\Platform\Tasks\CalcUsersStats; use Appwrite\Platform\Tasks\CalcTierStats; use Appwrite\Platform\Tasks\PatchDeleteProjectCollections; +use Appwrite\Platform\Tasks\Upgrade; class Tasks extends Service { @@ -36,6 +37,7 @@ class Tasks extends Service ->addAction(Hamster::getName(), new Hamster()) ->addAction(Doctor::getName(), new Doctor()) ->addAction(Install::getName(), new Install()) + ->addAction(Upgrade::getName(), new Upgrade()) ->addAction(Maintenance::getName(), new Maintenance()) ->addAction(PatchCreateMissingSchedules::getName(), new PatchCreateMissingSchedules()) ->addAction(ClearCardCache::getName(), new ClearCardCache()) diff --git a/src/Appwrite/Platform/Tasks/Upgrade.php b/src/Appwrite/Platform/Tasks/Upgrade.php new file mode 100644 index 0000000000..e3f0458394 --- /dev/null +++ b/src/Appwrite/Platform/Tasks/Upgrade.php @@ -0,0 +1,42 @@ +desc('Upgrade Appwrite') + ->param('httpPort', '', new Text(4), 'Server HTTP port', true) + ->param('httpsPort', '', new Text(4), 'Server HTTPS port', true) + ->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true) + ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) + ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) + ->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive)); + } + + public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void + { + // Check for previous installation + $data = @file_get_contents($this->path . '/docker-compose.yml'); + if (empty($data)) { + Console::error('Appwrite installation not found.'); + Console::log('The command was not run in the parent folder of your appwrite installation.'); + Console::log('Please navigate to the parent directory of the Appwrite installation and try again.'); + Console::log(' parent_directory <= you run the command in this directory'); + Console::log(' └── appwrite'); + Console::log(' └── docker-compose.yml'); + Console::exit(1); + } + parent::action($httpPort, $httpsPort, $organization, $image, $interactive); + } +} From 128b9d1b1bbc2b2fd3b7f71f4b43236fa5d46357 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 25 Jul 2023 13:50:43 -0700 Subject: [PATCH 5/5] Prompt developer to confirm installing over existing install --- src/Appwrite/Platform/Tasks/Install.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index f8509799b9..051d512ec4 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -82,6 +82,15 @@ class Install extends Action $data = @file_get_contents($this->path . '/docker-compose.yml'); if ($data !== false) { + if ($interactive == 'Y' && Console::isInteractive()) { + $answer = Console::confirm('Previous installation found, do you want to overwrite it? (Y/n)'); + + if ($answer !== 'Y') { + Console::info('No action taken.'); + return; + } + } + $time = \time(); Console::info('Compose file found, creating backup: docker-compose.yml.' . $time . '.backup'); file_put_contents($this->path . '/docker-compose.yml.' . $time . '.backup', $data);