change snapshot storage

This commit is contained in:
Andy Miller
2025-10-17 16:49:42 -06:00
parent d97b2d70bd
commit 2999c06a3a
7 changed files with 24 additions and 37 deletions

View File

@@ -1614,14 +1614,6 @@ form:
validate:
type: bool
updates.staging_root:
type: text
label: PLUGIN_ADMIN.SAFE_UPGRADE_STAGING
help: PLUGIN_ADMIN.SAFE_UPGRADE_STAGING_HELP
placeholder: '/absolute/path/to/grav-upgrades'
validate:
type: string
http_section:
type: section
title: PLUGIN_ADMIN.HTTP_SECTION
@@ -1936,4 +1928,3 @@ form:
#
# pages.type:
# type: hidden

View File

@@ -205,7 +205,6 @@ gpm:
updates:
safe_upgrade: true # Enable guarded staging+rollback pipeline for Grav self-updates
staging_root: '' # Optional absolute path for staging backups (default: <grav parent>/grav-upgrades)
http:
method: auto # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL

View File

@@ -124,5 +124,3 @@ PLUGIN_ADMIN:
UPDATES_SECTION: Updates
SAFE_UPGRADE: Safe self-upgrade
SAFE_UPGRADE_HELP: When enabled, Grav core updates use staged installation with automatic rollback support.
SAFE_UPGRADE_STAGING: Staging directory
SAFE_UPGRADE_STAGING_HELP: Optional absolute path for storing upgrade backups. Leave empty to use the default inside the parent directory.

View File

@@ -12,6 +12,7 @@ namespace Grav\Common\Upgrade;
use DirectoryIterator;
use Grav\Common\Filesystem\Folder;
use Grav\Common\GPM\GPM;
use Grav\Common\Grav;
use Grav\Common\Yaml;
use InvalidArgumentException;
use RuntimeException;
@@ -83,27 +84,30 @@ class SafeUpgradeService
$this->parentDir = $options['parent_dir'] ?? dirname($this->rootPath);
$this->config = $options['config'] ?? null;
$candidates = [];
if (!empty($options['staging_root'])) {
$candidates[] = $options['staging_root'];
$locator = null;
try {
$locator = Grav::instance()['locator'] ?? null;
} catch (Throwable $e) {
$locator = null;
}
$candidates[] = $this->parentDir . DIRECTORY_SEPARATOR . 'grav-upgrades';
if (getenv('HOME')) {
$candidates[] = getenv('HOME') . DIRECTORY_SEPARATOR . 'grav-upgrades';
}
$candidates[] = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'grav-upgrades';
$this->stagingRoot = null;
foreach ($candidates as $candidate) {
$resolved = $this->resolveStagingPath($candidate);
if ($resolved) {
$this->stagingRoot = $resolved;
break;
$primary = null;
if ($locator && method_exists($locator, 'findResource')) {
try {
$primary = $locator->findResource('tmp://grav-upgrades', true, true);
} catch (Throwable $e) {
$primary = null;
}
}
if (!$primary) {
$primary = $this->rootPath . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'grav-upgrades';
}
$this->stagingRoot = $this->resolveStagingPath($primary);
if (null === $this->stagingRoot) {
throw new RuntimeException('Unable to locate writable staging directory. Configure system.updates.staging_root or adjust permissions.');
throw new RuntimeException('Unable to locate writable staging directory. Ensure tmp://grav-upgrades is writable.');
}
$this->manifestStore = $options['manifest_store'] ?? ($this->rootPath . DIRECTORY_SEPARATOR . 'user' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'upgrades');
if (isset($options['ignored_dirs']) && is_array($options['ignored_dirs'])) {
@@ -671,6 +675,8 @@ class SafeUpgradeService
$home = getenv('HOME');
if ($home) {
$expanded = rtrim($home, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ltrim($expanded, '~\/');
} else {
return null;
}
}
if (!$this->isAbsolutePath($expanded)) {

View File

@@ -292,10 +292,8 @@ class SelfupgradeCommand extends GpmCommand
$config = null;
}
$stagingRoot = $config ? $config->get('system.updates.staging_root') : null;
return new SafeUpgradeService([
'staging_root' => $stagingRoot,
'config' => $config,
]);
}

View File

@@ -266,7 +266,7 @@ ERR;
try {
$grav = Grav::instance();
if ($grav && isset($grav['config'])) {
$options['staging_root'] = $grav['config']->get('system.updates.staging_root');
$options['config'] = $grav['config'];
}
} catch (\Throwable $e) {
// ignore

View File

@@ -94,7 +94,6 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
[$root, $staging, $manifestStore] = $this->prepareLiveEnvironment();
$service = new SafeUpgradeService([
'root' => $root,
'staging_root' => $staging,
'manifest_store' => $manifestStore,
]);
@@ -121,7 +120,6 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
[$root, $staging, $manifestStore] = $this->prepareLiveEnvironment();
$service = new SafeUpgradeService([
'root' => $root,
'staging_root' => $staging,
'manifest_store' => $manifestStore,
]);
@@ -147,7 +145,6 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
$service = new SafeUpgradeService([
'root' => $root,
'staging_root' => $this->tmpDir . '/staging',
]);
$method = new ReflectionMethod(SafeUpgradeService::class, 'detectPsrLogConflicts');
@@ -176,7 +173,6 @@ PHP;
$service = new SafeUpgradeService([
'root' => $root,
'staging_root' => $this->tmpDir . '/staging',
]);
$method = new ReflectionMethod(SafeUpgradeService::class, 'detectMonologConflicts');
@@ -197,7 +193,6 @@ PHP;
$service = new SafeUpgradeService([
'root' => $root,
'staging_root' => $this->tmpDir . '/staging',
]);
$service->clearRecoveryFlag();
@@ -210,7 +205,7 @@ PHP;
private function prepareLiveEnvironment(): array
{
$root = $this->tmpDir . '/root';
$staging = $this->tmpDir . '/staging';
$staging = $root . '/tmp/grav-upgrades';
$manifestStore = $root . '/user/data/upgrades';
Folder::create($root . '/user/plugins/sample');