refactor update
This commit is contained in:
parent
ce43f9a586
commit
ffef98ad2e
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Composer\Semver\Comparator;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Contracts\Console\Kernel as Artisan;
|
||||||
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class UpdateCommand extends Command
|
class UpdateCommand extends Command
|
||||||
{
|
{
|
||||||
|
|
@ -10,9 +14,38 @@ class UpdateCommand extends Command
|
||||||
|
|
||||||
protected $description = 'Execute update.';
|
protected $description = 'Execute update.';
|
||||||
|
|
||||||
public function handle()
|
public function handle(Artisan $artisan, Filesystem $filesystem)
|
||||||
{
|
{
|
||||||
app()->call('App\Http\Controllers\UpdateController@update');
|
$this->procedures()->each(function ($procedure, $version) {
|
||||||
|
if (Comparator::lessThan(option('version'), $version)) {
|
||||||
|
$procedure();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
option(['version' => config('app.version')]);
|
||||||
|
$artisan->call('migrate', ['--force' => true]);
|
||||||
|
$artisan->call('view:clear');
|
||||||
|
$filesystem->put(storage_path('install.lock'), '');
|
||||||
|
Cache::flush();
|
||||||
|
|
||||||
$this->info(trans('setup.updates.success.title'));
|
$this->info(trans('setup.updates.success.title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
protected function procedures()
|
||||||
|
{
|
||||||
|
return collect([
|
||||||
|
'0.0.1' => function () {
|
||||||
|
// this is just for testing
|
||||||
|
event('__0.0.1');
|
||||||
|
},
|
||||||
|
'5.0.0' => function () {
|
||||||
|
if (option('home_pic_url') === './app/bg.jpg') {
|
||||||
|
option(['home_pic_url' => './app/bg.webp']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,9 @@ use App\Services\Unzip;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Composer\CaBundle\CaBundle;
|
use Composer\CaBundle\CaBundle;
|
||||||
use Composer\Semver\Comparator;
|
use Composer\Semver\Comparator;
|
||||||
use Illuminate\Contracts\Console\Kernel as Artisan;
|
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Symfony\Component\Finder\SplFileInfo;
|
|
||||||
|
|
||||||
class UpdateController extends Controller
|
class UpdateController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -58,28 +56,6 @@ class UpdateController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Filesystem $filesystem, Artisan $artisan)
|
|
||||||
{
|
|
||||||
collect($filesystem->files(database_path('update_scripts')))
|
|
||||||
->filter(function (SplFileInfo $file) {
|
|
||||||
$name = $file->getFilenameWithoutExtension();
|
|
||||||
|
|
||||||
return preg_match('/^\d+\.\d+\.\d+$/', $name) > 0
|
|
||||||
&& Comparator::greaterThanOrEqualTo($name, option('version'));
|
|
||||||
})
|
|
||||||
->each(function (SplFileInfo $file) use ($filesystem) {
|
|
||||||
$filesystem->getRequire($file->getPathname());
|
|
||||||
});
|
|
||||||
|
|
||||||
option(['version' => config('app.version')]);
|
|
||||||
$artisan->call('migrate', ['--force' => true]);
|
|
||||||
$artisan->call('view:clear');
|
|
||||||
$filesystem->put(storage_path('install.lock'), '');
|
|
||||||
Cache::flush();
|
|
||||||
|
|
||||||
return view('setup.updates.success');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getUpdateInfo()
|
protected function getUpdateInfo()
|
||||||
{
|
{
|
||||||
$response = Http::withOptions([
|
$response = Http::withOptions([
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class CheckInstallation
|
||||||
public function handle($request, \Closure $next)
|
public function handle($request, \Closure $next)
|
||||||
{
|
{
|
||||||
$hasLock = resolve(Filesystem::class)->exists(storage_path('install.lock'));
|
$hasLock = resolve(Filesystem::class)->exists(storage_path('install.lock'));
|
||||||
if ($hasLock && !$request->is('setup/*update')) {
|
if ($hasLock) {
|
||||||
return response()->view('setup.locked');
|
return response()->view('setup.locked');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Composer\Semver\Comparator;
|
use Composer\Semver\Comparator;
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
class RedirectToSetup
|
class RedirectToSetup
|
||||||
{
|
{
|
||||||
|
|
@ -20,14 +21,7 @@ class RedirectToSetup
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasLock && !$request->is('setup*') && Comparator::greaterThan($version, option('version', $version))) {
|
if ($hasLock && !$request->is('setup*') && Comparator::greaterThan($version, option('version', $version))) {
|
||||||
$user = $request->user();
|
Artisan::call('update');
|
||||||
if ($user && $user->isAdmin()) {
|
|
||||||
return redirect('/setup/update');
|
|
||||||
} elseif ($request->is('auth/login')) {
|
|
||||||
return $next($request);
|
|
||||||
} else {
|
|
||||||
abort(503);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasLock || $request->is('setup*')) {
|
if ($hasLock || $request->is('setup*')) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
Artisan::call('migrate', ['--force' => true]);
|
|
||||||
|
|
||||||
if (option('home_pic_url') === './app/bg.jpg') {
|
|
||||||
option(['home_pic_url' => './app/bg.webp']);
|
|
||||||
}
|
|
||||||
|
|
@ -3,16 +3,7 @@
|
||||||
{% block title %}503 Service Unavailable{% endblock %}
|
{% block title %}503 Service Unavailable{% endblock %}
|
||||||
|
|
||||||
{% block message %}
|
{% block message %}
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13.0/css/all.min.css">
|
|
||||||
<p>
|
<p>
|
||||||
{{ trans('errors.exception.detail', {msg: exception.message ?: trans('errors.http.msg-503')}) }}
|
{{ trans('errors.exception.detail', {msg: exception.message ?: trans('errors.http.msg-503')}) }}
|
||||||
</p>
|
</p>
|
||||||
{% if not auth_check() %}
|
|
||||||
<div class="mt-5">
|
|
||||||
<a href="{{ url('/auth/login') }}" class="btn btn-primary">
|
|
||||||
<i class="icon fas fa-sign-in-alt mr-1"></i>
|
|
||||||
{{ trans('general.login') }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{% extends 'setup.base' %}
|
|
||||||
|
|
||||||
{% block title %}{{ trans('setup.updates.master.title') }}{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}{{ trans('setup.updates.success.title') }}{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<p>
|
|
||||||
{{ trans('setup.updates.success.text', {version: config('app.version')}) }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="{{ url('/') }}" class="btn btn-primary">
|
|
||||||
{{ trans('setup.updates.welcome.button') }}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{% extends 'setup.base' %}
|
|
||||||
|
|
||||||
{% block title %}{{ trans('setup.updates.master.title') }}{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}{{ trans('setup.updates.welcome.title') }}{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<p>
|
|
||||||
{{ trans('setup.updates.welcome.text', {version: config('app.version')})|nl2br }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="{{ url('/setup/exec-update') }}" class="btn btn-primary">
|
|
||||||
{{ trans('setup.updates.welcome.button') }}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -204,9 +204,4 @@ Route::prefix('setup')->group(function () {
|
||||||
Route::view('info', 'setup.wizard.info');
|
Route::view('info', 'setup.wizard.info');
|
||||||
Route::post('finish', 'SetupController@finish');
|
Route::post('finish', 'SetupController@finish');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware('authorize')->group(function () {
|
|
||||||
Route::view('update', 'setup.updates.welcome')->middleware('setup');
|
|
||||||
Route::any('exec-update', 'UpdateController@update')->middleware('setup');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ namespace Tests;
|
||||||
|
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
|
||||||
class UpdateCommandTest extends TestCase
|
class UpdateCommandTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -11,25 +13,23 @@ class UpdateCommandTest extends TestCase
|
||||||
|
|
||||||
public function testUpdate()
|
public function testUpdate()
|
||||||
{
|
{
|
||||||
|
Event::fake();
|
||||||
$this->mock(Filesystem::class, function ($mock) {
|
$this->mock(Filesystem::class, function ($mock) {
|
||||||
$mock->shouldReceive('exists')
|
|
||||||
->with(storage_path('install.lock'))
|
|
||||||
->andReturn(true);
|
|
||||||
|
|
||||||
$mock->shouldReceive('put')
|
$mock->shouldReceive('put')
|
||||||
->with(storage_path('install.lock'), '')
|
->with(storage_path('install.lock'), '')
|
||||||
->once()
|
->once()
|
||||||
->andReturn(true);
|
->andReturn(true);
|
||||||
|
|
||||||
$mock->shouldReceive('files')
|
|
||||||
->with(database_path('update_scripts'))
|
|
||||||
->once()
|
|
||||||
->andReturn([]);
|
|
||||||
});
|
});
|
||||||
config(['app.version' => '100.0.0']);
|
Cache::partialMock()->shouldReceive('flush')->once();
|
||||||
|
option(['version' => '0.0.0']);
|
||||||
|
config([
|
||||||
|
'app.version' => '0.0.1',
|
||||||
|
'translation-loader.translation_loaders' => [],
|
||||||
|
]);
|
||||||
|
|
||||||
$this->artisan('update')
|
$this->artisan('update')
|
||||||
->expectsOutput(trans('setup.updates.success.title'));
|
->expectsOutput(trans('setup.updates.success.title'));
|
||||||
$this->assertEquals('100.0.0', option('version'));
|
$this->assertEquals('0.0.1', option('version'));
|
||||||
|
Event::assertDispatched('__0.0.1');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,8 @@
|
||||||
namespace Tests;
|
namespace Tests;
|
||||||
|
|
||||||
use App\Services\Unzip;
|
use App\Services\Unzip;
|
||||||
use Illuminate\Contracts\Console\Kernel as Artisan;
|
|
||||||
use Illuminate\Filesystem\Filesystem;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Symfony\Component\Finder\SplFileInfo;
|
|
||||||
|
|
||||||
class UpdateControllerTest extends TestCase
|
class UpdateControllerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -71,51 +68,6 @@ class UpdateControllerTest extends TestCase
|
||||||
->assertJson(['code' => 0, 'message' => trans('admin.update.complete')]);
|
->assertJson(['code' => 0, 'message' => trans('admin.update.complete')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdate()
|
|
||||||
{
|
|
||||||
$this->mock(Filesystem::class, function ($mock) {
|
|
||||||
$mock->shouldReceive('exists')
|
|
||||||
->with(storage_path('install.lock'))
|
|
||||||
->andReturn(true);
|
|
||||||
|
|
||||||
$mock->shouldReceive('put')
|
|
||||||
->with(storage_path('install.lock'), '')
|
|
||||||
->once()
|
|
||||||
->andReturn(true);
|
|
||||||
|
|
||||||
$mock->shouldReceive('files')
|
|
||||||
->with(database_path('update_scripts'))
|
|
||||||
->once()
|
|
||||||
->andReturn([
|
|
||||||
new SplFileInfo('/1.0.0.php', '', ''),
|
|
||||||
new SplFileInfo('/99.0.0.php', '', ''),
|
|
||||||
new SplFileInfo('/100.0.0.php', '', ''),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$mock->shouldNotReceive('getRequire')->with('/1.0.0.php');
|
|
||||||
|
|
||||||
$mock->shouldReceive('getRequire')
|
|
||||||
->with('/99.0.0.php')
|
|
||||||
->once();
|
|
||||||
|
|
||||||
$mock->shouldReceive('getRequire')
|
|
||||||
->with('/100.0.0.php')
|
|
||||||
->once();
|
|
||||||
});
|
|
||||||
$this->spy(Artisan::class, function ($spy) {
|
|
||||||
$spy->shouldReceive('call')
|
|
||||||
->with('migrate', ['--force' => true])
|
|
||||||
->once();
|
|
||||||
$spy->shouldReceive('call')->with('view:clear')->once();
|
|
||||||
});
|
|
||||||
config(['app.version' => '100.0.0']);
|
|
||||||
|
|
||||||
$this->actingAs(factory(\App\Models\User::class)->states('superAdmin')->create())
|
|
||||||
->get('/setup/exec-update')
|
|
||||||
->assertViewIs('setup.updates.success');
|
|
||||||
$this->assertEquals('100.0.0', option('version'));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function fakeUpdateInfo(string $version, $extra = [])
|
protected function fakeUpdateInfo(string $version, $extra = [])
|
||||||
{
|
{
|
||||||
return array_merge([
|
return array_merge([
|
||||||
|
|
|
||||||
|
|
@ -19,22 +19,10 @@ class CheckInstallationTest extends TestCase
|
||||||
->with(storage_path('install.lock'))
|
->with(storage_path('install.lock'))
|
||||||
->twice()
|
->twice()
|
||||||
->andReturn(false);
|
->andReturn(false);
|
||||||
$mock->shouldReceive('exists')
|
|
||||||
->with(base_path('.env'))
|
|
||||||
->andReturn(true);
|
|
||||||
});
|
});
|
||||||
$this->get('/setup')->assertSee(trans(
|
$this->get('/setup')->assertSee(trans(
|
||||||
'setup.wizard.welcome.text',
|
'setup.wizard.welcome.text',
|
||||||
['version' => config('app.version')]
|
['version' => config('app.version')]
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->actingAs(factory(User::class)->states('superAdmin')->make());
|
|
||||||
$this->mock(Filesystem::class, function ($mock) {
|
|
||||||
$mock->shouldReceive('exists')
|
|
||||||
->with(storage_path('install.lock'))
|
|
||||||
->andReturn(true);
|
|
||||||
});
|
|
||||||
config(['app.version' => '100.0.0']);
|
|
||||||
$this->get('/setup/update')->assertSee(trans('setup.updates.welcome.title'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace Tests;
|
namespace Tests;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
class RedirectToSetupTest extends TestCase
|
class RedirectToSetupTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -12,23 +12,16 @@ class RedirectToSetupTest extends TestCase
|
||||||
|
|
||||||
public function testHandle()
|
public function testHandle()
|
||||||
{
|
{
|
||||||
$superAdmin = factory(User::class)->states('superAdmin')->create();
|
|
||||||
|
|
||||||
$current = config('app.version');
|
$current = config('app.version');
|
||||||
config(['app.version' => '100.0.0']);
|
config(['app.version' => '100.0.0']);
|
||||||
$this->get('/')->assertStatus(503);
|
Artisan::shouldReceive('call')->with('update')->once();
|
||||||
$this->get('/auth/login')->assertViewIs('auth.login');
|
$this->get('/');
|
||||||
$this->actingAs($superAdmin)->get('/')->assertRedirect('/setup/update');
|
|
||||||
config(['app.version' => $current]);
|
config(['app.version' => $current]);
|
||||||
|
|
||||||
$this->mock(Filesystem::class, function ($mock) {
|
$this->mock(Filesystem::class, function ($mock) {
|
||||||
$mock->shouldReceive('exists')
|
$mock->shouldReceive('exists')
|
||||||
->with(storage_path('install.lock'))
|
->with(storage_path('install.lock'))
|
||||||
->andReturn(true, false, false);
|
->andReturn(true, false, false);
|
||||||
|
|
||||||
$mock->shouldReceive('exists')
|
|
||||||
->with(base_path('.env'))
|
|
||||||
->andReturn(true);
|
|
||||||
});
|
});
|
||||||
$this->get('/')->assertViewIs('home');
|
$this->get('/')->assertViewIs('home');
|
||||||
$this->get('/setup')->assertViewIs('setup.wizard.welcome');
|
$this->get('/setup')->assertViewIs('setup.wizard.welcome');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user