Supporto Modifiche: sync deploy senza checkout git
This commit is contained in:
parent
8ee59acb31
commit
53047a955a
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
|
||||
|
|
@ -23,13 +22,18 @@ public function handle(): int
|
|||
$branch = trim((string) $this->option('branch')) ?: 'main';
|
||||
$force = (bool) $this->option('force');
|
||||
|
||||
if (! is_dir(base_path('.git'))) {
|
||||
$this->error('Repository Git non trovato nella base path corrente.');
|
||||
$this->writeProgress(100, 'Repository Git non trovato', 'failed', 1);
|
||||
$deployPath = base_path();
|
||||
$repoPath = is_dir(base_path('.git')) ? $deployPath : $this->resolveSourceRepositoryPath();
|
||||
$deploySync = $repoPath !== null && realpath($repoPath) !== realpath($deployPath);
|
||||
|
||||
if ($repoPath === null) {
|
||||
$this->error('Repository Git sorgente non trovato.');
|
||||
$this->writeProgress(100, 'Repository Git sorgente non trovato', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
'status' => 'failed',
|
||||
'exit_code' => 1,
|
||||
'message' => 'Repository Git non trovato',
|
||||
'message' => 'Repository Git sorgente non trovato',
|
||||
'deploy_path' => $deployPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
|
|
@ -37,8 +41,8 @@ public function handle(): int
|
|||
|
||||
$this->writeProgress(5, 'Preparazione sync da Gitea', 'running');
|
||||
|
||||
$currentBranch = $this->runGit(['rev-parse', '--abbrev-ref', 'HEAD']);
|
||||
$currentCommit = $this->runGit(['rev-parse', '--short', 'HEAD']);
|
||||
$currentBranch = $this->runGit($repoPath, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
||||
$currentCommit = $this->runGit($repoPath, ['rev-parse', '--short', 'HEAD']);
|
||||
|
||||
if ($currentBranch === null || $currentCommit === null) {
|
||||
$this->error('Impossibile leggere lo stato Git locale.');
|
||||
|
|
@ -47,15 +51,16 @@ public function handle(): int
|
|||
'status' => 'failed',
|
||||
'exit_code' => 1,
|
||||
'message' => 'Impossibile leggere stato Git locale',
|
||||
'repo_path' => $repoPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$dirtyResult = Process::path(base_path())->run(['git', 'status', '--porcelain']);
|
||||
$dirtyResult = Process::path($repoPath)->run(['git', 'status', '--porcelain']);
|
||||
$isDirty = trim((string) $dirtyResult->output()) !== '';
|
||||
|
||||
if ($isDirty && ! $force) {
|
||||
if ($isDirty && ! $force && ! $deploySync) {
|
||||
$this->error('Working tree sporco: sync bloccata per evitare conflitti locali.');
|
||||
$this->writeProgress(100, 'Working tree sporco: sync bloccata', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
|
|
@ -66,6 +71,7 @@ public function handle(): int
|
|||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'working_tree_dirty' => true,
|
||||
'repo_path' => $repoPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
|
|
@ -74,7 +80,7 @@ public function handle(): int
|
|||
$this->info("Fetch da {$remote}...");
|
||||
$this->writeProgress(18, 'Fetch remoto da Gitea', 'running');
|
||||
|
||||
$fetch = Process::path(base_path())
|
||||
$fetch = Process::path($repoPath)
|
||||
->timeout(1800)
|
||||
->run(['git', 'fetch', $remote]);
|
||||
|
||||
|
|
@ -89,15 +95,94 @@ public function handle(): int
|
|||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'working_tree_dirty' => false,
|
||||
'repo_path' => $repoPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$remoteRef = 'refs/remotes/' . $remote . '/' . $branch;
|
||||
$docsRepoPath = $deployPath;
|
||||
$newCommit = $currentCommit;
|
||||
$cleanupWorktree = null;
|
||||
|
||||
if ($deploySync) {
|
||||
$this->writeProgress(32, 'Creazione sorgente remota pulita', 'running');
|
||||
|
||||
$worktreePath = storage_path('app/support/git-sync-worktrees/' . now()->format('YmdHis') . '-' . uniqid());
|
||||
File::ensureDirectoryExists(dirname($worktreePath));
|
||||
|
||||
$worktreeAdd = Process::path($repoPath)
|
||||
->timeout(1800)
|
||||
->run(['git', 'worktree', 'add', '--force', '--detach', $worktreePath, $remoteRef]);
|
||||
|
||||
if (! $worktreeAdd->successful()) {
|
||||
$this->line(trim((string) ($worktreeAdd->errorOutput() !== '' ? $worktreeAdd->errorOutput() : $worktreeAdd->output())));
|
||||
$this->writeProgress(100, 'Creazione worktree remoto fallita', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
'status' => 'failed',
|
||||
'exit_code' => 1,
|
||||
'message' => 'Creazione worktree remoto fallita',
|
||||
'remote' => $remote,
|
||||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'working_tree_dirty' => $isDirty,
|
||||
'repo_path' => $repoPath,
|
||||
'deploy_path' => $deployPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$cleanupWorktree = static function () use ($repoPath, $worktreePath): void {
|
||||
Process::path($repoPath)->timeout(1800)->run(['git', 'worktree', 'remove', '--force', $worktreePath]);
|
||||
if (is_dir($worktreePath)) {
|
||||
File::deleteDirectory($worktreePath);
|
||||
}
|
||||
};
|
||||
|
||||
$docsRepoPath = $worktreePath;
|
||||
$newCommit = $this->runGit($worktreePath, ['rev-parse', '--short', 'HEAD']) ?? $currentCommit;
|
||||
|
||||
$this->writeProgress(48, 'Sync deploy da worktree remoto', 'running');
|
||||
|
||||
$sync = Process::path($deployPath)
|
||||
->timeout(1800)
|
||||
->run([
|
||||
'bash',
|
||||
'scripts/ops/netgescon-sync-prod-update.sh',
|
||||
'--src',
|
||||
$worktreePath,
|
||||
'--dst',
|
||||
$deployPath,
|
||||
]);
|
||||
|
||||
if (! $sync->successful()) {
|
||||
$this->line(trim((string) ($sync->errorOutput() !== '' ? $sync->errorOutput() : $sync->output())));
|
||||
if ($cleanupWorktree instanceof \Closure) {
|
||||
$cleanupWorktree();
|
||||
}
|
||||
$this->writeProgress(100, 'Sync deploy fallita', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
'status' => 'failed',
|
||||
'exit_code' => 1,
|
||||
'message' => 'Sync deploy fallita',
|
||||
'remote' => $remote,
|
||||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'after_commit' => $newCommit,
|
||||
'working_tree_dirty' => $isDirty,
|
||||
'repo_path' => $repoPath,
|
||||
'deploy_path' => $deployPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
} else {
|
||||
$this->writeProgress(32, 'Allineamento branch locale', 'running');
|
||||
|
||||
if ($currentBranch !== $branch) {
|
||||
$checkout = Process::path(base_path())
|
||||
$checkout = Process::path($repoPath)
|
||||
->timeout(1800)
|
||||
->run(['git', 'checkout', $branch]);
|
||||
|
||||
|
|
@ -112,6 +197,7 @@ public function handle(): int
|
|||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'working_tree_dirty' => false,
|
||||
'repo_path' => $repoPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
|
|
@ -121,7 +207,7 @@ public function handle(): int
|
|||
$this->info("Pull ff-only da {$remote}/{$branch}...");
|
||||
$this->writeProgress(48, 'Pull ff-only da Gitea', 'running');
|
||||
|
||||
$pull = Process::path(base_path())
|
||||
$pull = Process::path($repoPath)
|
||||
->timeout(1800)
|
||||
->run(['git', 'pull', '--ff-only', $remote, $branch]);
|
||||
|
||||
|
|
@ -136,27 +222,35 @@ public function handle(): int
|
|||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'working_tree_dirty' => false,
|
||||
'repo_path' => $repoPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$docsRepoPath = $deployPath;
|
||||
$newCommit = $this->runGit($repoPath, ['rev-parse', '--short', 'HEAD']) ?? $currentCommit;
|
||||
}
|
||||
|
||||
$this->writeProgress(68, 'Rigenerazione changelog Git automatico', 'running');
|
||||
File::ensureDirectoryExists(storage_path('app/support/generated'));
|
||||
|
||||
$docsSync = Process::path(base_path())
|
||||
$docsSync = Process::path($deployPath)
|
||||
->timeout(1800)
|
||||
->run([
|
||||
'bash',
|
||||
'scripts/ops/netgescon-sync-git-changelog.sh',
|
||||
'--repo',
|
||||
base_path(),
|
||||
$docsRepoPath,
|
||||
'--output',
|
||||
storage_path('app/support/generated/NETGESCON-GIT-AUTOCHANGELOG.md'),
|
||||
]);
|
||||
|
||||
if (! $docsSync->successful()) {
|
||||
$this->line(trim((string) ($docsSync->errorOutput() !== '' ? $docsSync->errorOutput() : $docsSync->output())));
|
||||
if ($cleanupWorktree instanceof \Closure) {
|
||||
$cleanupWorktree();
|
||||
}
|
||||
$this->writeProgress(100, 'Rigenerazione changelog Git fallita', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
'status' => 'failed',
|
||||
|
|
@ -165,7 +259,10 @@ public function handle(): int
|
|||
'remote' => $remote,
|
||||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'after_commit' => $newCommit,
|
||||
'working_tree_dirty' => false,
|
||||
'repo_path' => $repoPath,
|
||||
'deploy_path' => $deployPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
|
|
@ -174,6 +271,9 @@ public function handle(): int
|
|||
$this->writeProgress(76, 'Rigenerazione snapshot continuita sviluppo', 'running');
|
||||
$snapshotExit = Artisan::call('netgescon:development-snapshot');
|
||||
if ($snapshotExit !== 0) {
|
||||
if ($cleanupWorktree instanceof \Closure) {
|
||||
$cleanupWorktree();
|
||||
}
|
||||
$this->writeProgress(100, 'Rigenerazione snapshot sviluppo fallita', 'failed', 1);
|
||||
$this->persistSummary([
|
||||
'status' => 'failed',
|
||||
|
|
@ -182,7 +282,10 @@ public function handle(): int
|
|||
'remote' => $remote,
|
||||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'after_commit' => $newCommit,
|
||||
'working_tree_dirty' => false,
|
||||
'repo_path' => $repoPath,
|
||||
'deploy_path' => $deployPath,
|
||||
]);
|
||||
|
||||
return self::FAILURE;
|
||||
|
|
@ -191,8 +294,11 @@ public function handle(): int
|
|||
$this->writeProgress(82, 'Pulizia cache applicativa', 'running');
|
||||
$this->callSilently('optimize:clear');
|
||||
|
||||
$newCommit = $this->runGit(['rev-parse', '--short', 'HEAD']) ?? $currentCommit;
|
||||
$remoteRef = $this->runGit(['rev-parse', '--short', 'refs/remotes/' . $remote . '/' . $branch]) ?? $newCommit;
|
||||
$remoteCommit = $this->runGit($repoPath, ['rev-parse', '--short', $remoteRef]) ?? $newCommit;
|
||||
|
||||
if ($cleanupWorktree instanceof \Closure) {
|
||||
$cleanupWorktree();
|
||||
}
|
||||
|
||||
$this->persistSummary([
|
||||
'status' => 'completed',
|
||||
|
|
@ -202,8 +308,11 @@ public function handle(): int
|
|||
'branch' => $branch,
|
||||
'before_commit' => $currentCommit,
|
||||
'after_commit' => $newCommit,
|
||||
'remote_commit' => $remoteRef,
|
||||
'working_tree_dirty' => false,
|
||||
'remote_commit' => $remoteCommit,
|
||||
'working_tree_dirty' => $isDirty,
|
||||
'repo_path' => $repoPath,
|
||||
'deploy_path' => $deployPath,
|
||||
'mode' => $deploySync ? 'external-repo-rsync' : 'in-place-git',
|
||||
]);
|
||||
|
||||
$this->info('Sync Git completata con successo.');
|
||||
|
|
@ -212,9 +321,9 @@ public function handle(): int
|
|||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function runGit(array $arguments): ?string
|
||||
private function runGit(string $path, array $arguments): ?string
|
||||
{
|
||||
$result = Process::path(base_path())
|
||||
$result = Process::path($path)
|
||||
->timeout(1800)
|
||||
->run(array_merge(['git'], $arguments));
|
||||
|
||||
|
|
@ -227,6 +336,25 @@ private function runGit(array $arguments): ?string
|
|||
return $output !== '' ? $output : null;
|
||||
}
|
||||
|
||||
private function resolveSourceRepositoryPath(): ?string
|
||||
{
|
||||
$candidates = array_values(array_filter(array_unique([
|
||||
trim((string) env('NETGESCON_GIT_SYNC_SOURCE_REPO', '')),
|
||||
'/home/michele/netgescon/netgescon-day0',
|
||||
'/home/michele/netgescon/netgescon-laravel',
|
||||
'/var/www/netgescon_backup_20250722_220433',
|
||||
'/var/www/netgescon_backup_20250722_215454',
|
||||
]), static fn(string $path): bool => $path !== ''));
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
if (is_dir($candidate . '/.git')) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function writeProgress(int $percent, string $message, string $status, ?int $exitCode = null): void
|
||||
{
|
||||
$path = trim((string) $this->option('progress-file'));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user