Skip to content

Commit c4f20d6

Browse files
author
Itamar Junior
committed
Add system update functionality with automatic version checks and UI components
1 parent 77993bc commit c4f20d6

File tree

17 files changed

+455
-12
lines changed

17 files changed

+455
-12
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use App\Services\System\SystemUpdateService;
7+
8+
class RunSystemUpdate extends Command
9+
{
10+
protected $signature = 'system:update';
11+
protected $description = 'Run the system update commands and log the result';
12+
13+
public function handle()
14+
{
15+
$update = app(SystemUpdateService::class)->runUpdate();
16+
17+
$this->info("System update {$update->status}: {$update->version}");
18+
}
19+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Http\Requests\StoreSystemUpdateRequest;
6+
use App\Http\Requests\UpdateSystemUpdateRequest;
7+
use App\Models\SystemUpdate;
8+
9+
class SystemUpdateController extends Controller
10+
{
11+
12+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Http\Requests;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class StoreSystemUpdateRequest extends FormRequest
8+
{
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*/
12+
public function authorize(): bool
13+
{
14+
return true;
15+
}
16+
17+
/**
18+
* Get the validation rules that apply to the request.
19+
*
20+
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
21+
*/
22+
public function rules(): array
23+
{
24+
return [
25+
//
26+
];
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Http\Requests;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class UpdateSystemUpdateRequest extends FormRequest
8+
{
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*/
12+
public function authorize(): bool
13+
{
14+
return true;
15+
}
16+
17+
/**
18+
* Get the validation rules that apply to the request.
19+
*
20+
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
21+
*/
22+
public function rules(): array
23+
{
24+
return [
25+
//
26+
];
27+
}
28+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace App\Livewire\Settings;
4+
5+
use Livewire\Component;
6+
use App\Services\System\SystemUpdateService;
7+
8+
class SystemUpdate extends Component
9+
{
10+
public $updateAvailable = null;
11+
public $isRunning = false;
12+
public $log = '';
13+
public $status = null;
14+
15+
public function mount(SystemUpdateService $service)
16+
{
17+
$this->updateAvailable = $service->checkForUpdates();
18+
}
19+
20+
public function runUpdate(SystemUpdateService $service)
21+
{
22+
$this->isRunning = true;
23+
$this->log = "Updating...\n";
24+
25+
$update = $service->runUpdate();
26+
27+
$this->log = $update->update_log;
28+
$this->status = $update->status;
29+
$this->isRunning = false;
30+
}
31+
32+
public function render()
33+
{
34+
return view('livewire.settings.system-update');
35+
}
36+
}

app/Models/SystemUpdate.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class SystemUpdate extends Model
9+
{
10+
/** @use HasFactory<\Database\Factories\SystemUpdateFactory> */
11+
use HasFactory;
12+
13+
protected $fillable = [
14+
'version',
15+
'commit_title',
16+
'commit_description',
17+
'update_log',
18+
'status',
19+
];
20+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace App\Policies;
4+
5+
use App\Models\SystemUpdate;
6+
use App\Models\User;
7+
use Illuminate\Auth\Access\Response;
8+
9+
class SystemUpdatePolicy
10+
{
11+
/**
12+
* Determine whether the user can view any models.
13+
*/
14+
public function viewAny(User $user): bool
15+
{
16+
return false;
17+
}
18+
19+
/**
20+
* Determine whether the user can view the model.
21+
*/
22+
public function view(User $user, SystemUpdate $systemUpdate): bool
23+
{
24+
return false;
25+
}
26+
27+
/**
28+
* Determine whether the user can create models.
29+
*/
30+
public function create(User $user): bool
31+
{
32+
return false;
33+
}
34+
35+
/**
36+
* Determine whether the user can update the model.
37+
*/
38+
public function update(User $user, SystemUpdate $systemUpdate): bool
39+
{
40+
return false;
41+
}
42+
43+
/**
44+
* Determine whether the user can delete the model.
45+
*/
46+
public function delete(User $user, SystemUpdate $systemUpdate): bool
47+
{
48+
return false;
49+
}
50+
51+
/**
52+
* Determine whether the user can restore the model.
53+
*/
54+
public function restore(User $user, SystemUpdate $systemUpdate): bool
55+
{
56+
return false;
57+
}
58+
59+
/**
60+
* Determine whether the user can permanently delete the model.
61+
*/
62+
public function forceDelete(User $user, SystemUpdate $systemUpdate): bool
63+
{
64+
return false;
65+
}
66+
}

app/Providers/AppServiceProvider.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,28 @@
22

33
namespace App\Providers;
44

5+
use Illuminate\Support\Facades\Cache;
56
use Illuminate\Support\ServiceProvider;
7+
use App\Services\System\SystemUpdateService;
68

79
class AppServiceProvider extends ServiceProvider
810
{
911
/**
1012
* Register any application services.
1113
*/
12-
public function register(): void
13-
{
14-
//
15-
}
14+
public function register(): void {}
1615

1716
/**
1817
* Bootstrap any application services.
1918
*/
2019
public function boot(): void
2120
{
22-
//
21+
view()->composer('*', function ($view) {
22+
$hasUpdate = Cache::remember('has_system_update', 3600, function () {
23+
return app(SystemUpdateService::class)->checkForUpdates() !== null;
24+
});
25+
26+
$view->with('hasUpdate', $hasUpdate);
27+
});
2328
}
2429
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace App\Services\System;
4+
5+
use App\Models\SystemUpdate;
6+
use Illuminate\Support\Facades\Log;
7+
use Symfony\Component\Process\Process;
8+
9+
class SystemUpdateService
10+
{
11+
public function runUpdate(): SystemUpdate
12+
{
13+
$output = '';
14+
$status = 'successful';
15+
16+
$version = trim(shell_exec('git rev-parse HEAD'));
17+
$commitTitle = trim(shell_exec('git log -1 --pretty=%s'));
18+
$commitDescription = trim(shell_exec('git log -1 --pretty=%b'));
19+
20+
$update = SystemUpdate::create([
21+
'version' => $version,
22+
'commit_title' => $commitTitle,
23+
'commit_description' => $commitDescription,
24+
'update_log' => '',
25+
'status' => 'running',
26+
]);
27+
28+
$commands = [
29+
'git fetch origin',
30+
'git reset --hard origin/main',
31+
'git clean -fd',
32+
'php artisan migrate',
33+
'php artisan optimize:clear',
34+
'php artisan queue:restart',
35+
'npm install',
36+
'npm run build',
37+
];
38+
39+
foreach ($commands as $command) {
40+
$output .= "Running: $command\n";
41+
try {
42+
$process = Process::fromShellCommandline($command, base_path(), null, null, 300);
43+
$process->run();
44+
45+
$output .= $process->getOutput() . "\n";
46+
if (!$process->isSuccessful()) {
47+
$output .= "Error: " . $process->getErrorOutput() . "\n";
48+
$status = 'failed';
49+
break;
50+
}
51+
} catch (\Throwable $e) {
52+
$output .= "Exception: " . $e->getMessage() . "\n";
53+
$status = 'failed';
54+
break;
55+
}
56+
}
57+
58+
$update->update([
59+
'update_log' => $output,
60+
'status' => $status,
61+
]);
62+
63+
return $update;
64+
}
65+
66+
public function checkForUpdates(): ?array
67+
{
68+
$currentVersion = trim(shell_exec('git rev-parse HEAD'));
69+
$latestVersion = trim(shell_exec('git ls-remote origin -h refs/heads/main | cut -f1'));
70+
71+
if ($currentVersion !== $latestVersion) {
72+
return [
73+
'version' => $latestVersion,
74+
'title' => trim(shell_exec("git log $latestVersion -1 --pretty=%s")),
75+
'description' => trim(shell_exec("git log $latestVersion -1 --pretty=%b")),
76+
];
77+
}
78+
79+
return null;
80+
}
81+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use Illuminate\Database\Eloquent\Factories\Factory;
6+
7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SystemUpdate>
9+
*/
10+
class SystemUpdateFactory extends Factory
11+
{
12+
/**
13+
* Define the model's default state.
14+
*
15+
* @return array<string, mixed>
16+
*/
17+
public function definition(): array
18+
{
19+
return [
20+
'version' => $this->faker->uuid,
21+
'commit_title' => $this->faker->sentence,
22+
'commit_description' => $this->faker->paragraph,
23+
'update_log' => $this->faker->paragraph,
24+
'status' => 'successful',
25+
];
26+
}
27+
}

0 commit comments

Comments
 (0)