mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-01 15:32:48 +08:00
All checks were successful
build-and-deploy / 直传代码并部署到 Host15 (push) Successful in 1m0s
- 重写 getModePlan: 跳过目标模式和 default 都不存在的文件 (不再抛异常) - 重写 applyMode: 切换模式后自动清理孤立的管理文件, 删除前备份以支持 rollback - 修复 HOSTPORT 为 3306 (容器内部端口, 非宿主机映射端口) - 增加 backup_id 空值保护: 无备份时不执行删除
117 lines
3.7 KiB
PHP
117 lines
3.7 KiB
PHP
<?php
|
|
|
|
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;
|
|
}
|
|
}
|