feat(release): collapse to a single stable channel
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/v1-foundation
parent
176b132da9
commit
4e4023f12d
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\Setting;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
|
@ -16,8 +15,6 @@ use Illuminate\Support\Facades\Http;
|
||||||
*/
|
*/
|
||||||
class ReleaseChecker
|
class ReleaseChecker
|
||||||
{
|
{
|
||||||
private const CHANNELS = ['stable', 'beta'];
|
|
||||||
|
|
||||||
/** Cache the resolved tag long enough that the scheduled refresh keeps it continuously warm. */
|
/** Cache the resolved tag long enough that the scheduled refresh keeps it continuously warm. */
|
||||||
private const TTL_MINUTES = 60;
|
private const TTL_MINUTES = 60;
|
||||||
|
|
||||||
|
|
@ -38,9 +35,7 @@ class ReleaseChecker
|
||||||
|
|
||||||
public function channel(): string
|
public function channel(): string
|
||||||
{
|
{
|
||||||
$channel = (string) (Setting::get('release_channel', config('clusev.channel')) ?? 'stable');
|
return 'stable';
|
||||||
|
|
||||||
return in_array($channel, self::CHANNELS, true) ? $channel : 'stable';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Last resolved latest tag (no network). Null when unknown. */
|
/** Last resolved latest tag (no network). Null when unknown. */
|
||||||
|
|
@ -191,9 +186,7 @@ class ReleaseChecker
|
||||||
*/
|
*/
|
||||||
public function newestVersion(array $tagNames, string $channel): ?string
|
public function newestVersion(array $tagNames, string $channel): ?string
|
||||||
{
|
{
|
||||||
$pattern = $channel === 'beta'
|
$pattern = '/^v?\d+\.\d+\.\d+$/';
|
||||||
? '/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?$/'
|
|
||||||
: '/^v?\d+\.\d+\.\d+$/';
|
|
||||||
|
|
||||||
$versions = [];
|
$versions = [];
|
||||||
foreach (array_unique($tagNames) as $tag) {
|
foreach (array_unique($tagNames) as $tag) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\Setting;
|
||||||
|
use App\Services\ReleaseChecker;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ReleaseCheckerChannelTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
public function test_channel_is_always_stable_even_if_a_beta_setting_lingers(): void
|
||||||
|
{
|
||||||
|
Setting::put('release_channel', 'beta'); // a stale setting from before the drop
|
||||||
|
$this->assertSame('stable', app(ReleaseChecker::class)->channel());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_newest_version_ignores_rc_and_beta_prereleases(): void
|
||||||
|
{
|
||||||
|
$checker = app(ReleaseChecker::class);
|
||||||
|
$tags = ['v0.11.0', 'v0.12.0-rc1', 'v0.12.0-beta2', 'v0.10.0'];
|
||||||
|
$this->assertSame('0.11.0', $checker->newestVersion($tags, 'stable'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -110,7 +110,7 @@ class VersionUpdateCheckTest extends TestCase
|
||||||
->assertSet('updateState', 'current');
|
->assertSet('updateState', 'current');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_stable_channel_ignores_prereleases_but_beta_sees_them(): void
|
public function test_stable_channel_ignores_prereleases(): void
|
||||||
{
|
{
|
||||||
config()->set('clusev.version', '0.9.6');
|
config()->set('clusev.version', '0.9.6');
|
||||||
Http::fake([self::TAGS_URL => Http::response([
|
Http::fake([self::TAGS_URL => Http::response([
|
||||||
|
|
@ -121,13 +121,12 @@ class VersionUpdateCheckTest extends TestCase
|
||||||
Setting::put('release_channel', 'stable');
|
Setting::put('release_channel', 'stable');
|
||||||
Livewire::test(Index::class)->call('checkUpdates')->assertSet('updateState', 'current');
|
Livewire::test(Index::class)->call('checkUpdates')->assertSet('updateState', 'current');
|
||||||
|
|
||||||
// beta: the prerelease is newer → update available
|
// a stale beta setting from before the channel drop is ignored → still current
|
||||||
Cache::flush();
|
Cache::flush();
|
||||||
Setting::put('release_channel', 'beta');
|
Setting::put('release_channel', 'beta');
|
||||||
Livewire::test(Index::class)
|
Livewire::test(Index::class)
|
||||||
->call('checkUpdates')
|
->call('checkUpdates')
|
||||||
->assertSet('updateState', 'update')
|
->assertSet('updateState', 'current');
|
||||||
->assertSee('1.0.0-beta1');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_degrades_gracefully_when_the_remote_api_is_unreachable(): void
|
public function test_degrades_gracefully_when_the_remote_api_is_unreachable(): void
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue