mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-01 15:32:48 +08:00
feat(stack): 切换模式时自动删除多余的管理文件
All checks were successful
build-and-deploy / 直传代码并部署到 Host15 (push) Successful in 1m0s
All checks were successful
build-and-deploy / 直传代码并部署到 Host15 (push) Successful in 1m0s
- 重写 getModePlan: 跳过目标模式和 default 都不存在的文件 (不再抛异常) - 重写 applyMode: 切换模式后自动清理孤立的管理文件, 删除前备份以支持 rollback - 修复 HOSTPORT 为 3306 (容器内部端口, 非宿主机映射端口) - 增加 backup_id 空值保护: 无备份时不执行删除
This commit is contained in:
@@ -3,7 +3,114 @@
|
||||
namespace app\common\service\stack;
|
||||
|
||||
use base\common\service\stack\StackModeServiceBase;
|
||||
use RuntimeException;
|
||||
|
||||
class StackModeService extends StackModeServiceBase
|
||||
{
|
||||
public function getModePlan(string $mode): array
|
||||
{
|
||||
$mode = trim($mode);
|
||||
if ($mode === '') {
|
||||
throw new RuntimeException('模式不能为空');
|
||||
}
|
||||
|
||||
$config = $this->loadConfig();
|
||||
$modes = $config['modes'];
|
||||
if (!isset($modes[$mode])) {
|
||||
throw new RuntimeException("模式不存在:{$mode}");
|
||||
}
|
||||
|
||||
$defaultMode = $config['default_mode'];
|
||||
$managedFiles = $config['managed_files'];
|
||||
|
||||
$plan = [];
|
||||
$skippedFiles = [];
|
||||
foreach ($managedFiles as $relativePath) {
|
||||
$modeSource = $this->resolveModeFile($mode, $relativePath);
|
||||
if ($modeSource !== null) {
|
||||
$plan[] = [
|
||||
'file' => $relativePath,
|
||||
'source_mode' => $mode,
|
||||
'source_path' => $modeSource,
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
$defaultSource = $this->resolveModeFile($defaultMode, $relativePath);
|
||||
if ($defaultSource !== null) {
|
||||
$plan[] = [
|
||||
'file' => $relativePath,
|
||||
'source_mode' => $defaultMode,
|
||||
'source_path' => $defaultSource,
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
// File not found in mode OR default - skip it (don't throw)
|
||||
$skippedFiles[] = $relativePath;
|
||||
}
|
||||
|
||||
return [
|
||||
'mode' => $mode,
|
||||
'default_mode' => $defaultMode,
|
||||
'managed_files' => $managedFiles,
|
||||
'plan' => $plan,
|
||||
'skipped_files' => $skippedFiles,
|
||||
];
|
||||
}
|
||||
|
||||
public function applyMode(string $mode, string $operator = 'system'): array
|
||||
{
|
||||
// Use our overridden getModePlan (skips missing files instead of throwing)
|
||||
$result = parent::applyMode($mode, $operator);
|
||||
|
||||
$appliedFiles = $result['applied_files'] ?? [];
|
||||
$backupId = $result['backup_id'] ?? '';
|
||||
|
||||
$config = $this->loadConfig();
|
||||
$managedFiles = $config['managed_files'];
|
||||
|
||||
$deletedFiles = [];
|
||||
|
||||
foreach ($managedFiles as $relativePath) {
|
||||
// Skip files already handled by parent
|
||||
if (in_array($relativePath, $appliedFiles)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$targetPath = $this->toRootPath($relativePath);
|
||||
if (!is_file($targetPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This file was skipped by getModePlan (not in mode or default)
|
||||
// Back it up before deleting
|
||||
if ($backupId !== '') {
|
||||
$backupDir = $this->joinPath($this->backupRoot, $backupId);
|
||||
$backupFilesDir = $this->joinPath($backupDir, 'files');
|
||||
$backupFilePath = $this->joinPath($backupFilesDir, $this->toSystemPath($relativePath));
|
||||
|
||||
$this->ensureDir(dirname($backupFilePath));
|
||||
copy($targetPath, $backupFilePath);
|
||||
|
||||
// Update backup meta
|
||||
$metaPath = $this->joinPath($backupDir, 'meta.json');
|
||||
if (is_file($metaPath)) {
|
||||
$meta = $this->readJsonFile($metaPath);
|
||||
$meta['files'][] = [
|
||||
'file' => $relativePath,
|
||||
'existed' => true,
|
||||
];
|
||||
$this->writeJsonFile($metaPath, $meta);
|
||||
}
|
||||
|
||||
// Only delete if we successfully backed up
|
||||
@unlink($targetPath);
|
||||
$deletedFiles[] = $relativePath;
|
||||
}
|
||||
}
|
||||
|
||||
$result['deleted_files'] = $deletedFiles;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user