Compare commits

..

8 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
3d09806422 Proper rebase: sync all files from base branch, apply only SystemPrune streaming changes
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
2026-03-20 15:47:04 +00:00
copilot-swe-agent[bot]
099298d695 Rebase onto base branch, use startStreamingResponse from base
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
2026-03-20 15:39:34 +00:00
copilot-swe-agent[bot]
12a85f81ac Match base branch startStreamingResponse signature (return Response, not array)
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
2026-03-20 15:33:47 +00:00
copilot-swe-agent[bot]
8b63032955 Address review: add startStreamingResponse helper, stream prune output, restore button location
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
2026-03-20 15:24:24 +00:00
copilot-swe-agent[bot]
95f23defeb Use streaming overlay-log for system prune, move button to stopped-containers section
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
2026-03-20 15:15:21 +00:00
copilot-swe-agent[bot]
915a5a8321 Initial plan 2026-03-20 15:07:56 +00:00
Simon L.
04c08b586f wip
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-02-27 14:55:16 +01:00
Simon L.
4f7ccdedb5 aio-interface: offer system prune button
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-02-27 14:48:21 +01:00
11 changed files with 546 additions and 326 deletions

View File

@@ -15,7 +15,7 @@
}
https://{$ADDITIONAL_TRUSTED_DOMAIN}:443,
http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see containers.json
http://{$APACHE_HOST}.nextcloud-aio:23973, # For Collabora callback and WOPI requests, see containers.json
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
header -Server
header -X-Powered-By

View File

@@ -17,7 +17,8 @@
}
servers {
protocols h1 h2 h2c
# Only h1 is allowed as we prevent `ERR_NETWORK_CHANGED` from happening
protocols h1
}
on_demand_tls {
@@ -39,7 +40,6 @@ https://:8443 {
abort @denied
root * /var/www/docker-aio/php/public
encode
php_fastcgi unix//run/php.sock
file_server

View File

@@ -13,7 +13,8 @@
}
servers {
protocols h1 h2
# Only h1 is allowed as we prevent `ERR_NETWORK_CHANGED` from happening
protocols h1
}
skip_install_trust
@@ -27,7 +28,6 @@ https://:8080 {
abort @denied
root * /var/www/docker-aio/php/public
encode
php_fastcgi unix//run/php.sock
file_server

View File

@@ -379,7 +379,7 @@
],
"internal_port": "9980",
"environment": [
"aliasgroup1=https://%NC_DOMAIN%:443,http://nextcloud-aio-apache:23973",
"aliasgroup1=https://%NC_DOMAIN%:443,http://nextcloud-aio-apache.nextcloud-aio:23973",
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.disable_server_audit=true --o:logging.level=warning --o:logging.level_startup=warning --o:welcome.enable=false --o:fetch_update_check=0 --o:allow_update_popup=false %COLLABORA_SECCOMP_POLICY% --o:remote_font_config.url=https://%NC_DOMAIN%/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+",
"dictionaries=%COLLABORA_DICTIONARIES%",
"TZ=%TIMEZONE%",
@@ -389,7 +389,7 @@
"restart": "unless-stopped",
"nextcloud_exec_commands": [
"echo 'Activating Collabora config...'",
"php /var/www/html/occ richdocuments:activate-config --wopi-url='http://nextcloud-aio-apache:23973' --callback-url='http://nextcloud-aio-apache:23973'"
"php /var/www/html/occ richdocuments:activate-config --wopi-url='http://nextcloud-aio-apache.nextcloud-aio:23973' --callback-url='http://nextcloud-aio-apache.nextcloud-aio:23973'"
],
"profiles": [
"collabora"

View File

@@ -66,6 +66,7 @@ $app->post('/api/docker/backup-check-repair', AIO\Controller\DockerController::c
$app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . ':StartBackupContainerTest');
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
$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');
$app->get('/api/auth/getlogin', AIO\Controller\LoginController::class . ':GetTryLogin');

View File

@@ -328,6 +328,19 @@ readonly class DockerController {
return $nonbufResp;
}
public function SystemPrune(Request $request, Response $response, array $args) : Response {
$nonbufResp = $this->startStreamingResponse($response);
$addToStreamingResponseBody = function (string $message) use ($nonbufResp) : void {
$nonbufResp->getBody()->write("<div>{$message}</div>");
};
$this->dockerActionManager->SystemPrune($addToStreamingResponseBody);
$this->finalizeStreamingResponse($nonbufResp);
return $nonbufResp;
}
public function stopTopContainer() : void {
$id = self::TOP_CONTAINER;
$this->PerformRecursiveContainerStop($id);

View File

@@ -983,4 +983,45 @@ readonly class DockerActionManager {
return $this->dockerHubManager->GetLatestDigestOfTag($imageName, $tag);
}
}
}
public function SystemPrune(?\Closure $addToStreamingResponseBody = null): void {
$steps = [
'containers/prune' => 'Pruning stopped containers...',
'images/prune' => 'Pruning unused images...',
'volumes/prune' => 'Pruning unused volumes...',
'networks/prune' => 'Pruning unused networks...',
'build/prune' => 'Pruning build cache...',
];
foreach ($steps as $endpoint => $label) {
if ($addToStreamingResponseBody !== null) {
$addToStreamingResponseBody($label);
}
// Special-case images prune to include the dangling filter as requested
if ($endpoint === 'images/prune') {
$filters = json_encode(['dangling' => ['false']]);
$url = $this->BuildApiUrl($endpoint . '?filters=' . urlencode($filters));
} else {
$url = $this->BuildApiUrl($endpoint);
}
try {
$resp = $this->guzzleClient->post($url);
$body = (string) $resp->getBody();
if ($addToStreamingResponseBody !== null && $body !== '') {
$addToStreamingResponseBody($body);
}
} catch (RequestException $e) {
error_log(sprintf('Docker prune (%s) failed: %s', $endpoint, $e->getMessage()));
if ($addToStreamingResponseBody !== null) {
$addToStreamingResponseBody(sprintf('Warning: %s failed: %s', $endpoint, $e->getMessage()));
}
// continue with next prune step
}
}
if ($addToStreamingResponseBody !== null) {
$addToStreamingResponseBody('Docker system prune done.');
}
}

View File

@@ -322,6 +322,11 @@
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Stop containers" />
</form>
<form method="POST" action="api/docker/prune" 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="Run docker system prune" onclick="return confirm('Run docker system prune? This will remove unused images, containers and volumes. Continue?')" />
</form>
{% endif %}
{% else %}
{% if isBackupOrRestoreRunning == true %}
@@ -353,6 +358,9 @@
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input id="base_path" type="hidden" name="base_path" value="">
{% if bypass_container_update == true %}
<input type="hidden" name="bypass_container_update" value="true">
{% endif %}
<input type="submit" value="Start containers" />
</form>
{% else %}
@@ -361,7 +369,7 @@
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input id="base_path" type="hidden" name="base_path" value="">
{% if bypass_container_update == true %}
<input type="hidden" name="bypass_container_update" value="{{bypass_container_update}}">
<input type="hidden" name="bypass_container_update" value="true">
{% endif %}
<input class="button " type="submit" value="Start and update containers" onclick="return confirm('Start and update containers? You should consider creating a backup first.')" />
</form>

0
php/tests/tests/initial-setup.spec.js Normal file → Executable file
View File

0
php/tests/tests/restore-instance.spec.js Normal file → Executable file
View File

File diff suppressed because it is too large Load Diff