refactor: remove git-based update method, keep only direct GitHub deployment

- Remove 'Update HMS (Git)' button and related functionality
- Remove runUpdate() method from SystemOperations
- Remove update() controller method
- Remove /setting/admin/system-ops/update route
- Remove setup_git_config.sh (no longer needed)
- Keep 'Deploy from GitHub' button as the only update method
- Rationale: Direct GitHub deployment is more reliable and requires no git config

Result: Single, simpler deployment method that always works
This commit is contained in:
DevSoftTech Server 2026-08-04 03:27:22 +05:30
parent b2fdf9751d
commit eb81f1999f
5 changed files with 3 additions and 166 deletions

View File

@ -1217,7 +1217,6 @@ $routes->group('setting', static function($routes) {
$routes->get('admin/system-ops', 'SystemOps::index', ['filter' => $settingsAdminFilter]);
$routes->get('admin/system-ops/panel', 'SystemOps::panel', ['filter' => $settingsAdminFilter]);
$routes->get('admin/system-ops/diagnose', 'SystemOps::diagnose', ['filter' => $settingsAdminFilter]);
$routes->post('admin/system-ops/update', 'SystemOps::update', ['filter' => $settingsAdminFilter]);
$routes->post('admin/system-ops/updateDirect', 'SystemOps::updateDirect', ['filter' => $settingsAdminFilter]);
$routes->post('admin/system-ops/action', 'SystemOps::action', ['filter' => $settingsAdminFilter]);
$routes->post('admin/hospital-profile/save', 'Setting\\HospitalProfile::save');

View File

@ -29,14 +29,6 @@ class SystemOps extends BaseController
return view('Setting/Admin/system_ops_panel', $data);
}
public function update()
{
$ops = new SystemOperations();
$result = $ops->runUpdate();
return $this->response->setJSON($result);
}
public function updateDirect()
{
$ops = new SystemOperations();

View File

@ -195,156 +195,6 @@ class SystemOperations
@rmdir($dir);
}
public function runUpdate(): array
{
$repoPath = ROOTPATH;
$logFile = WRITEPATH . 'system_update.log';
$startedAt = date('Y-m-d H:i:s');
$entry = [
'timestamp' => $startedAt,
'type' => 'update',
'status' => 'running',
'message' => 'HMS update started (git pull)',
];
$this->appendHistory($entry);
// Pre-check: Verify .git directory exists
if (!is_dir($repoPath . '/.git')) {
$errorMsg = 'Git repository not found. .git directory missing.';
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'failed',
'message' => 'HMS update failed',
'detail' => $errorMsg,
]);
file_put_contents($logFile, 'FAILED: ' . $errorMsg . PHP_EOL, FILE_APPEND);
return ['ok' => false, 'message' => $errorMsg];
}
// Find git command location (try common paths)
$gitPath = $this->findGitCommand();
if (!$gitPath) {
$errorMsg = 'Git command not found. Tried: /usr/bin/git, /bin/git, /usr/local/bin/git. Ensure git is installed on the system.';
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'failed',
'message' => 'HMS update failed',
'detail' => $errorMsg,
]);
file_put_contents($logFile, 'FAILED: ' . $errorMsg . PHP_EOL, FILE_APPEND);
return ['ok' => false, 'message' => $errorMsg];
}
// Run git status first to check connectivity and permissions
$statusCmd = 'cd ' . escapeshellarg($repoPath) . ' && ' . escapeshellarg($gitPath) . ' status 2>&1';
$statusResult = $this->runCommand($statusCmd);
if ($statusResult['exit_code'] !== 0) {
$statusError = trim($statusResult['output']);
$errorMsg = '';
// Get diagnostics first
$diagnostics = $this->getGitDiagnostics($gitPath, $repoPath);
// Build detailed diagnostic summary
$diagSummary = 'DIAGNOSTICS: ' .
'Version=' . $diagnostics['git_version'] . '; ' .
'User=' . $diagnostics['git_config_user_name'] . '; ' .
'Email=' . $diagnostics['git_config_user_email'] . '; ' .
'Remote=' . $diagnostics['remote_url'] . '; ' .
'Branch=' . $diagnostics['current_branch'] . '; ' .
'.git=' . $diagnostics['git_dir_exists'] . '; ' .
'Config=' . $diagnostics['git_config_exists'];
// Parse error message
if (strpos($statusError, 'Permission denied') !== false) {
$errorMsg = 'PERMISSION ERROR: Git directory may not be writable by www-data user. Check directory ownership.';
} elseif (strpos($statusError, 'fatal: Not a git repository') !== false) {
$errorMsg = 'REPO ERROR: Not a valid git repository. .git directory corrupted.';
} elseif (strpos($statusError, 'user.email') !== false || strpos($statusError, 'user.name') !== false) {
$errorMsg = 'CONFIG ERROR: Git user not configured. RUN: git config user.name "www-data" && git config user.email "deploy@example.com"';
} elseif (strpos($statusError, 'SSL certificate problem') !== false) {
$errorMsg = 'SSL ERROR: Certificate verification failed. RUN: git config http.sslVerify false';
} elseif (strpos($statusError, 'Could not resolve host') !== false || strpos($statusError, 'Connection refused') !== false) {
$errorMsg = 'NETWORK ERROR: Cannot connect to GitHub. Check network/firewall.';
} elseif (trim($statusError) === '') {
$errorMsg = 'GIT ERROR: Command returned no output. Possible permission or file system issue.';
} else {
$errorMsg = 'GIT ERROR: ' . substr($statusError, 0, 150);
}
$fullMsg = $errorMsg . ' | ' . $diagSummary;
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'failed',
'message' => 'HMS update failed',
'detail' => $fullMsg,
]);
file_put_contents($logFile, 'FAILED: ' . $fullMsg . ' (Raw error: ' . $statusError . ')' . PHP_EOL, FILE_APPEND);
return ['ok' => false, 'message' => $fullMsg];
}
// Run git pull with timeout protection
$command = 'cd ' . escapeshellarg($repoPath) . ' && timeout 60 ' . escapeshellarg($gitPath) . ' pull origin main 2>&1';
$result = $this->runCommand($command);
$output = $result['output'];
// Check for timeout
if (str_contains($output, 'Terminated') || $result['exit_code'] === 124) {
$errorMsg = 'Update timed out after 60 seconds. Network connectivity or server response issue.';
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'timeout',
'message' => 'HMS update timed out (60 seconds)',
'detail' => $errorMsg,
]);
file_put_contents($logFile, 'TIMEOUT: ' . $output . PHP_EOL, FILE_APPEND);
return ['ok' => false, 'message' => $errorMsg];
}
if ($result['exit_code'] !== 0) {
// Parse error message for user-friendly output
$errorMsg = $output;
if (strpos($output, 'Permission denied') !== false) {
$errorMsg = 'Permission denied. Check SSH key setup and permissions.';
} elseif (strpos($output, 'Authentication failed') !== false || strpos($output, 'fatal: could not read') !== false) {
$errorMsg = 'Authentication failed. SSH keys may not be configured for www-data user.';
} elseif (strpos($output, 'Connection refused') !== false) {
$errorMsg = 'Connection refused. GitHub server may be unreachable.';
} elseif (strpos($output, 'fatal: remote origin does not appear to be a git repository') !== false) {
$errorMsg = 'Remote origin not configured correctly.';
}
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'failed',
'message' => 'HMS update failed',
'detail' => $errorMsg,
]);
file_put_contents($logFile, 'FAILED: ' . $output . PHP_EOL, FILE_APPEND);
return ['ok' => false, 'message' => $errorMsg, 'output' => $output];
}
// Success
$this->appendHistory([
'timestamp' => date('Y-m-d H:i:s'),
'type' => 'update',
'status' => 'success',
'message' => 'HMS update completed',
'detail' => $output,
]);
file_put_contents($logFile, 'SUCCESS: ' . $output . PHP_EOL, FILE_APPEND);
return ['ok' => true, 'message' => 'HMS update completed successfully', 'output' => $output];
}
private function findGitCommand(): ?string
{
// Try common git installation paths

View File

@ -88,9 +88,8 @@
setHealthState('healthy');
setInterval(function(){ refreshPanel(); }, 30000);
$(document).off('click', '#btnUpdateSystem, #btnUpdateDirectGithub, #btnRestartWeb, #btnRestartPhp, #btnReboot, #btnShutdown')
.on('click', '#btnUpdateSystem', function(){ if (!confirm('Pull latest HMS code from repository?\n\nThis method requires git to be configured on the server.')) return; postAction('<?= base_url('setting/admin/system-ops/update') ?>', {}, this); })
.on('click', '#btnUpdateDirectGithub', function(){ if (!confirm('Deploy latest HMS code from GitHub?\n\nThis will download the latest code and update files.\nThis method is more reliable if git is not available.')) return; postAction('<?= base_url('setting/admin/system-ops/updateDirect') ?>', {}, this); })
$(document).off('click', '#btnUpdateDirectGithub, #btnRestartWeb, #btnRestartPhp, #btnReboot, #btnShutdown')
.on('click', '#btnUpdateDirectGithub', function(){ if (!confirm('Deploy latest HMS code from GitHub?\n\nThis will download the latest code and update all files.')) return; postAction('<?= base_url('setting/admin/system-ops/updateDirect') ?>', {}, this); })
.on('click', '#btnRestartWeb', function(){ if (!confirm('Restart the web server now?')) return; postAction('<?= base_url('setting/admin/system-ops/action') ?>', {action: 'restart_web'}, this); })
.on('click', '#btnRestartPhp', function(){ if (!confirm('Restart PHP-FPM now?')) return; postAction('<?= base_url('setting/admin/system-ops/action') ?>', {action: 'restart_php'}, this); })
.on('click', '#btnReboot', function(){ if (!confirm('Reboot the server now?')) return; postAction('<?= base_url('setting/admin/system-ops/action') ?>', {action: 'reboot'}, this); })

View File

@ -44,10 +44,7 @@
<h5 class="mb-0">Maintenance Actions</h5>
</div>
<div class="card-body d-grid gap-2">
<div class="d-grid gap-2">
<button class="btn btn-primary" id="btnUpdateSystem" title="Update via git (requires git configuration)">Update HMS (Git)</button>
<button class="btn btn-success" id="btnUpdateDirectGithub" title="Download and deploy latest from GitHub (more reliable)">Deploy from GitHub</button>
</div>
<button class="btn btn-success" id="btnUpdateDirectGithub" title="Download and deploy latest from GitHub">Deploy from GitHub</button>
<hr class="my-2">
<button class="btn btn-outline-warning" id="btnRestartWeb">Restart Web Server</button>
<button class="btn btn-outline-info" id="btnRestartPhp">Restart PHP-FPM</button>