Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/http.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function dispatch(Server $server, int $fd, int $type, $data = null): int
$lines = explode("\n", $data, 3);
$request = $lines[0];
if (count($lines) > 1) {
$domain = trim(explode('Host: ', $lines[1])[1]);
$domain = trim(explode('Host: ', $lines[1])[1] ?? '');
}
Comment thread
abnegate marked this conversation as resolved.

// Sync executions are considered risky
Expand Down
2 changes: 1 addition & 1 deletion app/views/install/installer.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ $enabledDatabases = $enabledDatabases ?? ['mongodb', 'mariadb', 'postgresql'];
$isLocalInstall = $isLocalInstall ?? false;


$cardStep = min(4, $step);
$cardStep = ($step === 5) ? 4 : $step;
$stepFile = __DIR__ . "/installer/templates/steps/step-{$cardStep}.phtml";
if (!is_file($stepFile)) {
$stepFile = __DIR__ . "/installer/templates/steps/step-1.phtml";
Expand Down
89 changes: 89 additions & 0 deletions app/views/install/installer/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -1812,3 +1812,92 @@ body {
gap: var(--gap-s);
}
}

.migration-option {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--gap-l);
padding: var(--space-6);
background: var(--bgcolor-neutral-default);
border-radius: var(--border-radius-m);
outline: var(--border-width-s) solid var(--border-neutral);
outline-offset: calc(var(--border-width-s) * -1);
cursor: pointer;
transition: outline-color 0.15s ease-in-out;
}

.migration-option:hover {
outline-color: var(--border-neutral-stronger);
}

.migration-option-content {
display: flex;
flex-direction: column;
gap: 2px;
}

.migration-switch {
flex-shrink: 0;
}

.migration-switch-track {
position: relative;
display: block;
width: 32px;
height: 20px;
border-radius: 10px;
background: var(--bgcolor-neutral-invert-weaker);
transition: background 0.15s ease-in-out;
}

.migration-switch-thumb {
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--bgcolor-neutral-primary);
transition: transform 0.15s ease-in-out;
}

#run-migration:checked ~ .migration-switch-track {
background: var(--bgcolor-neutral-invert-weak);
}

#run-migration:checked ~ .migration-switch-track .migration-switch-thumb {
transform: translateX(12px);
}

#run-migration:focus-visible ~ .migration-switch-track {
box-shadow: 0 0 0 var(--border-width-l) var(--border-focus);
}

.migration-hint {
display: flex;
align-items: flex-start;
gap: var(--gap-s);
padding: 0 var(--space-2);
}

.migration-hint-icon {
flex-shrink: 0;
width: 16px;
height: 16px;
color: var(--fgcolor-neutral-tertiary);
margin-top: 1px;
}

.migration-hint-icon svg {
width: 100%;
height: 100%;
}

.migration-code {
padding: 1px 4px;
border-radius: var(--border-radius-xs, 4px);
background: var(--bgcolor-neutral-secondary);
font-family: monospace;
font-size: inherit;
}
4 changes: 2 additions & 2 deletions app/views/install/installer/js/installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
const { validateInstallRequest } = window.InstallerStepsProgress || {};

const isUpgrade = document.body?.dataset.upgrade === 'true';
const stepFlow = isUpgrade ? [1, 4, 5] : [1, 2, 3, 4, 5];
const stepFlow = isUpgrade ? [1, 6, 4, 5] : [1, 2, 3, 4, 5];
const cardSteps = stepFlow.filter((step) => step !== 5);

const normalizeStep = (step) => {
Expand Down Expand Up @@ -53,7 +53,7 @@
let pendingStep = null;
let pendingPushState = false;

const clampStep = (step) => Math.max(1, Math.min(5, step));
const clampStep = (step) => Math.max(1, Math.min(6, step));
const isInstallLocked = () => Boolean(window.InstallerSteps?.isInstallLocked?.());

const scrollToFirstError = (panel) => {
Expand Down
8 changes: 7 additions & 1 deletion app/views/install/installer/js/modules/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ENV_VARS: 'env-vars',
DOCKER_CONTAINERS: 'docker-containers',
ACCOUNT_SETUP: 'account-setup',
MIGRATION: 'migration',
SSL_CERTIFICATE: 'ssl-certificate',
REDIRECT: 'redirect'
});
Expand Down Expand Up @@ -52,6 +53,11 @@
id: STEP_IDS.DOCKER_CONTAINERS,
inProgress: 'Restarting Docker containers...',
done: 'Docker containers restarted'
},
{
id: STEP_IDS.MIGRATION,
inProgress: 'Running database migration...',
done: 'Database migration completed'
}
] : [
{
Expand Down Expand Up @@ -95,7 +101,7 @@
const clampStep = (step) => {
const numeric = Number(step);
if (Number.isNaN(numeric)) return 1;
return Math.max(1, Math.min(5, numeric));
return Math.max(1, Math.min(6, numeric));
};

window.InstallerStepsContext = Object.freeze({
Expand Down
20 changes: 16 additions & 4 deletions app/views/install/installer/js/modules/progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@
opensslKey: (formState?.opensslKey || '').trim(),
assistantOpenAIKey: normalizedAssistantKey,
accountEmail: normalizedAccountEmail,
accountPassword: normalizedAccountPassword
accountPassword: normalizedAccountPassword,
migrate: formState?.migrate ?? false
};
};

Expand Down Expand Up @@ -1069,14 +1070,25 @@
startInstallStream(newInstallId);
};

const recoverToLastStep = () => {
clearInstallId?.();
clearInstallLock?.();
const url = new URL(window.location.href);
const lastStep = url.searchParams.get('step');
// Stay on the current URL so the user keeps their place;
// only navigate away if we're already on step 5 (the
// progress screen) since there's nothing to show.
if (!lastStep || String(lastStep) === '5') {
window.location.href = '/?step=1';
}
};

const lock = getInstallLock?.();
const existingInstallId = lock?.installId || getStoredInstallId?.();
if (existingInstallId) {
resumeInstall(existingInstallId).then((resumed) => {
if (!resumed) {
clearInstallId?.();
clearInstallLock?.();
window.location.href = '/?step=1';
recoverToLastStep();
}
});
} else {
Expand Down
25 changes: 25 additions & 0 deletions app/views/install/installer/js/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,30 @@
}
};

const initStep6 = (root) => {
if (!root) return;
syncInstallLockFlag?.();
applyLockPayload?.();
applyBodyDefaults?.();

const checkbox = root.querySelector('#run-migration');
if (checkbox) {
if (formState.migrate !== undefined) {
checkbox.checked = formState.migrate;
} else {
formState.migrate = checkbox.checked;
}
checkbox.addEventListener('change', () => {
formState.migrate = checkbox.checked;
dispatchStateChange?.('migrate');
});
}

if (isInstallLocked?.()) {
disableControls?.(root);
}
};

const initStep = (step, container) => {
if (!container) return;
const root = container.querySelector('.step-layout') || container;
Expand All @@ -346,6 +370,7 @@
if (normalized === 3) initStep3(root);
if (normalized === 4) initStep4(root);
if (normalized === 5) Progress.initStep5?.(root);
if (normalized === 6) initStep6(root);
};

window.InstallerSteps = {
Expand Down
37 changes: 37 additions & 0 deletions app/views/install/installer/templates/steps/step-6.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
$isUpgrade = $isUpgrade ?? false;
?>
<div class="step-layout" data-step="6">
<div class="stack-xl">
<div class="stack-xxxs">
<h1 class="typography-title-s text-neutral-primary">Database migration</h1>
<p class="typography-text-m-400 text-neutral-secondary">
Run database migration after the update to apply schema changes.
</p>
</div>

<div class="stack-xl">
<label class="migration-option" for="run-migration">
<span class="migration-option-content">
<span class="typography-text-m-500 text-neutral-primary">Run migration automatically</span>
<span class="typography-text-xs-400 text-neutral-tertiary">Recommended when upgrading to a new version</span>
</span>
<span class="migration-switch">
<input type="checkbox" id="run-migration" name="migrate" class="sr-only" checked>
<span class="migration-switch-track" aria-hidden="true">
<span class="migration-switch-thumb"></span>
</span>
</span>
</label>

<div class="migration-hint">
<span class="migration-hint-icon">
<?php include __DIR__ . '/../../icons/info.svg'; ?>
</span>
<span class="typography-text-xs-400 text-neutral-tertiary">
To run manually later: <code class="migration-code">docker compose exec appwrite migrate</code>
</span>
</div>
</div>
</div>
</div>
3 changes: 3 additions & 0 deletions src/Appwrite/Platform/Installer/Http/Installer/Install.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function __construct()
->param('database', '', new WhiteList(['mongodb', 'mariadb', 'postgresql']), 'Database adapter', true)
->param('installId', '', new Text(64, 0), 'Installation ID', true)
->param('retryStep', null, new Nullable(new WhiteList([Server::STEP_DOCKER_COMPOSE, Server::STEP_ENV_VARS, Server::STEP_DOCKER_CONTAINERS], true)), 'Retry from step', true)
->param('migrate', false, new \Utopia\Validator\Boolean(true), 'Run database migration after upgrade', true)
->inject('request')
->inject('response')
->inject('swooleResponse')
Expand All @@ -64,6 +65,7 @@ public function action(
string $database,
string $installId,
?string $retryStep,
bool $migrate,
Request $request,
Response $response,
SwooleResponse $swooleResponse,
Expand Down Expand Up @@ -355,6 +357,7 @@ public function action(
$config->isUpgrade(),
$account,
$onComplete,
$migrate,
);

$onComplete();
Expand Down
7 changes: 5 additions & 2 deletions src/Appwrite/Platform/Installer/Http/Installer/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function __construct()
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
->setHttpPath('/')
->desc('Serve installer UI')
->param('step', 1, new Integer(true), 'Step number (1-5)', true)
->param('step', 1, new Integer(true), 'Step number (1-6)', true)
->param('partial', null, new Nullable(new Text(1, 0)), 'Render partial step only', true)
->inject('request')
->inject('response')
Expand Down Expand Up @@ -52,10 +52,13 @@ public function action(int $step, ?string $partial, Request $request, Response $
$defaultEmailCertificates = '[email protected]';
}

$step = max(1, min(5, $step));
$step = max(1, min(6, $step));
if ($isUpgrade && ($step === 2 || $step === 3)) {
$step = 4;
}
if (!$isUpgrade && $step === 6) {
$step = 4;
}

$partialFile = $paths['views'] . "/installer/templates/steps/step-{$step}.phtml";
if (!is_file($partialFile)) {
Expand Down
1 change: 1 addition & 0 deletions src/Appwrite/Platform/Installer/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Server
public const string STEP_DOCKER_COMPOSE = 'docker-compose';
public const string STEP_DOCKER_CONTAINERS = 'docker-containers';
public const string STEP_ACCOUNT_SETUP = 'account-setup';
public const string STEP_MIGRATION = 'migration';
public const string STEP_SSL_CERTIFICATE = 'ssl-certificate';

public const string STATUS_IN_PROGRESS = 'in-progress';
Expand Down
Loading
Loading