Extract Nextcloud major upgrade logic to script and add UI button

Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/8cd11b09-5073-4e27-8e59-9afffaf96c1f

Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-04-23 19:21:21 +00:00
committed by Simon L.
parent cbea0730d3
commit cc8f1e4f57
6 changed files with 124 additions and 33 deletions

View File

@@ -104,6 +104,7 @@ $app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . '
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
$app->post('/api/docker/backup-reset-location', AIO\Controller\DockerController::class . ':DeleteBorgBackupConfig');
$app->post('/api/docker/nextcloud-upgrade-to-latest-major', AIO\Controller\DockerController::class . ':RunNextcloudUpgradeToLatestMajor');
$app->post('/api/docker/prune', AIO\Controller\DockerController::class . ':SystemPrune');
$app->get('/api/docker/logs', AIO\Controller\DockerController::class . ':GetLogs');
$app->post('/api/auth/login', AIO\Controller\LoginController::class . ':TryLogin');

View File

@@ -333,6 +333,21 @@ readonly class DockerController {
return $response->withStatus(201)->withHeader('Location', '.');
}
public function RunNextcloudUpgradeToLatestMajor(Request $request, Response $response, array $args) : Response {
// Get streaming response start and closure
$nonbufResp = $this->startStreamingResponse($response);
$body = $nonbufResp->getBody();
$addToStreamingResponseBody = function (string $message) use ($body) : void {
$body->write("<div>" . htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . "</div>");
};
$this->dockerActionManager->RunNextcloudUpgradeToLatestMajor($addToStreamingResponseBody);
// End streaming response
$this->finalizeStreamingResponse($nonbufResp);
return $nonbufResp;
}
public function SystemPrune(Request $request, Response $response, array $args) : Response {
// Get streaming response start and closure
$nonbufResp = $this->startStreamingResponse($response);

View File

@@ -1027,6 +1027,66 @@ readonly class DockerActionManager {
}
}
public function RunNextcloudUpgradeToLatestMajor(\Closure $addToStreamingResponseBody): void {
$containerName = 'nextcloud-aio-nextcloud';
// Create exec instance
$url = $this->BuildApiUrl(sprintf('containers/%s/exec', urlencode($containerName)));
$response = json_decode(
$this->guzzleClient->request(
'POST',
$url,
[
'json' => [
'AttachStdout' => true,
'AttachStderr' => true,
'Tty' => true,
'Cmd' => ['bash', '/upgrade-latest-major.sh'],
],
]
)->getBody()->getContents(),
true,
512,
JSON_THROW_ON_ERROR,
);
$execId = $response['Id'];
// Start exec and stream output
$url = $this->BuildApiUrl(sprintf('exec/%s/start', $execId));
$streamResponse = $this->guzzleClient->request(
'POST',
$url,
[
'stream' => true,
'json' => [
'Detach' => false,
'Tty' => true,
],
]
);
$body = $streamResponse->getBody();
$buffer = '';
while (!$body->eof()) {
$chunk = $body->read(1024);
$buffer .= $chunk;
// Flush complete lines
while (($pos = strpos($buffer, "\n")) !== false) {
$line = substr($buffer, 0, $pos);
$buffer = substr($buffer, $pos + 1);
$line = rtrim($line, "\r");
if ($line !== '') {
$addToStreamingResponseBody($line);
}
}
}
// Flush any remaining output
if (trim($buffer) !== '') {
$addToStreamingResponseBody(trim($buffer));
}
}
public function SystemPrune(?\Closure $addToStreamingResponseBody = null): void {
$endpoints = [
// Remove stopped containers

View File

@@ -299,6 +299,12 @@
<details>
<summary>Note about <strong>Nextcloud Hub {{ newMajorVersionString }}</strong></summary>
<p>If you haven't upgraded to Nextcloud Hub {{ newMajorVersionString }} yet and want to do that now, feel free to follow <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/7523">this documentation</a></strong></p>
<p>Alternatively, you can trigger the upgrade directly from here:</p>
<form method="POST" action="api/docker/nextcloud-upgrade-to-latest-major" target="overlay-log">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Upgrade to Nextcloud Hub {{ newMajorVersionString }}" data-confirm="Upgrade to Nextcloud Hub {{ newMajorVersionString }}? You should consider creating a backup first." />
</form>
</details>
{% endif %}
{% endif %}