Compare commits

...
Author SHA1 Message Date
Atharva Deosthale 3bf7af3387 fix installer wizard for dev images 2026-03-22 20:56:22 +05:30
3 changed files with 153 additions and 28 deletions
+25 -20
View File
@@ -11,6 +11,8 @@ $httpsPort = $this->getParam('httpsPort', '');
$version = $this->getParam('version', '');
$organization = $this->getParam('organization', '');
$image = $this->getParam('image', '');
$appwriteImage = $this->getParam('appwriteImage', '');
$useHostSourceMount = $this->getParam('useHostSourceMount', false);
$enableAssistant = $this->getParam('enableAssistant', false);
$dbService = $this->getParam('database', 'mongodb');
$allowedDbServices = ['mariadb', 'mongodb', 'postgresql'];
@@ -18,6 +20,9 @@ if (!\in_array($dbService, $allowedDbServices, true)) {
$dbService = 'mongodb';
}
$hostPath = rtrim($this->getParam('hostPath', ''), '/');
if ($appwriteImage === '') {
$appwriteImage = $organization . '/' . $image . ':' . $version;
}
?>services:
traefik:
image: traefik:3.6
@@ -46,7 +51,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- appwrite
appwrite:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
container_name: appwrite
<<: *x-logging
restart: unless-stopped
@@ -67,7 +72,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- traefik.http.routers.appwrite_api_https.service=appwrite_api
- traefik.http.routers.appwrite_api_https.tls=true
volumes:
<?php if ($version === 'local' && !empty($hostPath)): ?>
<?php if ($useHostSourceMount && !empty($hostPath)): ?>
- "<?php echo $hostPath; ?>:/usr/src/code:rw"
<?php endif; ?>
- appwrite-uploads:/storage/uploads:rw
@@ -214,7 +219,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- traefik.http.routers.appwrite_console_https.tls=true
appwrite-realtime:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: realtime
container_name: appwrite-realtime
<<: *x-logging
@@ -261,7 +266,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-audits:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-audits
<<: *x-logging
container_name: appwrite-worker-audits
@@ -291,7 +296,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-webhooks:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-webhooks
<<: *x-logging
container_name: appwrite-worker-webhooks
@@ -323,7 +328,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-deletes:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-deletes
<<: *x-logging
container_name: appwrite-worker-deletes
@@ -390,7 +395,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_EMAIL_CERTIFICATES
appwrite-worker-databases:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-databases
<<: *x-logging
container_name: appwrite-worker-databases
@@ -420,7 +425,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-builds:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-builds
<<: *x-logging
container_name: appwrite-worker-builds
@@ -492,7 +497,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_DOMAIN_SITES
appwrite-worker-certificates:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-certificates
<<: *x-logging
container_name: appwrite-worker-certificates
@@ -533,7 +538,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-functions:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-functions
<<: *x-logging
container_name: appwrite-worker-functions
@@ -577,7 +582,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_LOGGING_CONFIG
appwrite-worker-mails:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-mails
<<: *x-logging
container_name: appwrite-worker-mails
@@ -616,7 +621,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_OPTIONS_FORCE_HTTPS
appwrite-worker-messaging:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-messaging
<<: *x-logging
container_name: appwrite-worker-messaging
@@ -672,7 +677,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_STORAGE_WASABI_BUCKET
appwrite-worker-migrations:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-migrations
<<: *x-logging
container_name: appwrite-worker-migrations
@@ -711,7 +716,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
appwrite-task-maintenance:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: maintenance
<<: *x-logging
container_name: appwrite-task-maintenance
@@ -755,7 +760,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_MAINTENANCE_RETENTION_SCHEDULES
appwrite-task-stats-resources:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
container_name: appwrite-task-stats-resources
entrypoint: stats-resources
<<: *x-logging
@@ -788,7 +793,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_STATS_RESOURCES_INTERVAL
appwrite-worker-stats-resources:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-stats-resources
container_name: appwrite-worker-stats-resources
<<: *x-logging
@@ -820,7 +825,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_STATS_RESOURCES_INTERVAL
appwrite-worker-stats-usage:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: worker-stats-usage
container_name: appwrite-worker-stats-usage
<<: *x-logging
@@ -852,7 +857,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-task-scheduler-functions:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: schedule-functions
container_name: appwrite-task-scheduler-functions
<<: *x-logging
@@ -881,7 +886,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_DB_ADAPTER
appwrite-task-scheduler-executions:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: schedule-executions
container_name: appwrite-task-scheduler-executions
<<: *x-logging
@@ -910,7 +915,7 @@ $hostPath = rtrim($this->getParam('hostPath', ''), '/');
- _APP_DB_ADAPTER
appwrite-task-scheduler-messages:
image: <?php echo $organization; ?>/<?php echo $image; ?>:<?php echo $version."\n"; ?>
image: <?php echo $appwriteImage."\n"; ?>
entrypoint: schedule-messages
container_name: appwrite-task-scheduler-messages
<<: *x-logging
+71 -8
View File
@@ -106,7 +106,7 @@ class Install extends Action
file_put_contents($this->path . '/' . $composeFileName . '.' . $time . '.backup', $data);
$compose = new Compose($data);
$appwrite = $compose->getService('appwrite');
$oldVersion = $appwrite?->getImageVersion();
$oldImage = $appwrite?->getImage() ?? null;
try {
$ports = $compose->getService('traefik')->getPorts();
} catch (\Throwable $th) {
@@ -117,7 +117,7 @@ class Install extends Action
Console::warning('Traefik not found. Falling back to default ports.');
}
if ($oldVersion) {
if (!empty($oldImage)) {
foreach ($compose->getServices() as $service) {
if (!$service) {
continue;
@@ -509,12 +509,14 @@ class Install extends Action
$this->applyLocalPaths($isLocalInstall, false);
$isCLI = php_sapi_name() === 'cli';
if ($isLocalInstall || $isUpgrade) {
$useExistingConfig = false;
} else {
$useExistingConfig = file_exists($this->path . '/' . $this->getComposeFileName())
&& file_exists($this->path . '/' . $this->getEnvFileName());
}
$existingComposePath = $this->path . '/' . $this->getComposeFileName();
$existingEnvPath = $this->path . '/' . $this->getEnvFileName();
$useExistingConfig = $this->shouldReuseExistingConfig(
$isLocalInstall,
$isUpgrade,
file_exists($existingComposePath) && file_exists($existingEnvPath),
$this->readExistingComposeImage()
);
if ($isLocalInstall) {
$image = 'appwrite';
@@ -531,6 +533,8 @@ class Install extends Action
$version = 'local';
}
$appwriteImage = $this->resolveComposeAppwriteImage($isLocalInstall, $organization, $image, $version);
$assistantKey = (string) ($input['_APP_ASSISTANT_OPENAI_API_KEY'] ?? '');
$enableAssistant = trim($assistantKey) !== '';
@@ -540,8 +544,10 @@ class Install extends Action
->setParam('version', $version)
->setParam('organization', $organization)
->setParam('image', $image)
->setParam('appwriteImage', $appwriteImage)
->setParam('database', $database)
->setParam('hostPath', $this->hostPath)
->setParam('useHostSourceMount', $isLocalInstall)
->setParam('enableAssistant', $enableAssistant);
$templateForEnv->setParam('vars', $input);
@@ -1096,6 +1102,63 @@ class Install extends Action
return !empty($data) ? $data : '';
}
protected function readExistingComposeImage(): ?string
{
$data = $this->readExistingCompose();
if ($data === '') {
return null;
}
try {
$compose = new Compose($data);
return $compose->getService('appwrite')?->getImage();
} catch (\Throwable) {
return null;
}
}
protected function shouldUseLocalAppwriteImage(): bool
{
return \trim((string) \getenv('_APP_VERSION')) === 'dev' && $this->dockerImageExists('appwrite-dev');
}
protected function resolveComposeAppwriteImage(bool $isLocalInstall, string $organization, string $image, string $version): string
{
if ($isLocalInstall || $this->shouldUseLocalAppwriteImage()) {
return 'appwrite-dev';
}
return $organization . '/' . $image . ':' . $version;
}
protected function shouldReuseExistingConfig(bool $isLocalInstall, bool $isUpgrade, bool $configFilesExist, ?string $existingImage = null): bool
{
if ($isLocalInstall || $isUpgrade || !$configFilesExist) {
return false;
}
// Avoid sticky mutable or legacy dev tags from previous failed installer runs.
if ($existingImage !== null && $this->isStaleMutableAppwriteImageReference($existingImage)) {
return false;
}
return true;
}
protected function isStaleMutableAppwriteImageReference(string $image): bool
{
return \in_array(\strtolower(\trim($image)), ['appwrite/appwrite:dev', 'appwrite/appwrite:unknown'], true);
}
protected function dockerImageExists(string $image): bool
{
$result = 1;
$output = [];
\exec('docker image inspect ' . \escapeshellarg($image) . ' >/dev/null 2>&1', $output, $result);
return $result === 0;
}
protected function generatePasswordValue(string $varName, Password $password): string
{
$value = $password->generate();
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace Tests\Unit\Platform\Tasks;
use Appwrite\Platform\Tasks\Install;
use PHPUnit\Framework\TestCase;
class InstallTest extends TestCase
{
public function testResolveComposeAppwriteImageUsesLocalImageForDevBuilds(): void
{
$this->assertSame('appwrite-dev', $this->resolveComposeAppwriteImageForTest(false, 'appwrite', 'appwrite', 'dev', true));
}
public function testShouldNotReuseExistingConfigForDevTaggedCompose(): void
{
$this->assertFalse($this->shouldReuseExistingConfigForTest(false, false, true, 'appwrite/appwrite:dev'));
}
public function testShouldReuseExistingConfigForLocalAppwriteImageReference(): void
{
$this->assertTrue($this->shouldReuseExistingConfigForTest(false, false, true, 'appwrite-dev'));
}
private function resolveComposeAppwriteImageForTest(bool $isLocalInstall, string $organization, string $image, string $version, bool $useLocalAppwriteImage): string
{
$install = new class ($useLocalAppwriteImage) extends Install {
public function __construct(private bool $useLocalAppwriteImage)
{
}
public function resolveComposeAppwriteImageForTest(bool $isLocalInstall, string $organization, string $image, string $version): string
{
return $this->resolveComposeAppwriteImage($isLocalInstall, $organization, $image, $version);
}
protected function shouldUseLocalAppwriteImage(): bool
{
return $this->useLocalAppwriteImage;
}
};
return $install->resolveComposeAppwriteImageForTest($isLocalInstall, $organization, $image, $version);
}
private function shouldReuseExistingConfigForTest(bool $isLocalInstall, bool $isUpgrade, bool $configFilesExist, ?string $existingImage = null): bool
{
$install = new class () extends Install {
public function shouldReuseExistingConfigForTest(bool $isLocalInstall, bool $isUpgrade, bool $configFilesExist, ?string $existingImage = null): bool
{
return $this->shouldReuseExistingConfig($isLocalInstall, $isUpgrade, $configFilesExist, $existingImage);
}
};
return $install->shouldReuseExistingConfigForTest($isLocalInstall, $isUpgrade, $configFilesExist, $existingImage);
}
}