diff --git a/app/Livewire/Release/Index.php b/app/Livewire/Release/Index.php index 6ac1c5a..209adbe 100644 --- a/app/Livewire/Release/Index.php +++ b/app/Livewire/Release/Index.php @@ -3,7 +3,6 @@ namespace App\Livewire\Release; use App\Models\AuditEvent; -use App\Models\Setting; use App\Services\PipelineStatus; use App\Services\ReleaseBridge; use App\Services\ReleasePlanner; @@ -40,14 +39,9 @@ class Index extends Component /** The tag of the last successfully-pushed staging beta (shown until the next deploy). */ public ?string $lastTag = null; - /** The configured test-server URL (bound to the inline input). */ - public string $testServer = ''; - public function mount(): void { abort_unless((bool) config('clusev.release_controls'), 404); - - $this->testServer = (string) Setting::get('pipeline_test_server', ''); } /** Opens the wire-elements/modal confirm dialog (R5) before cutting a staging beta of $target. */ @@ -155,35 +149,12 @@ class Index extends Component } /** wire:poll target while the pipeline is in flight — drops the cached step results so the next - * render re-fetches the live GitHub/test-server status. */ + * render re-fetches the live GitHub status. */ public function pollPipeline(PipelineStatus $pipeline): void { $pipeline->refresh(); } - /** Save (or clear) the test-server URL whose /version.json the pipeline polls. */ - public function saveTestServer(string $url): void - { - $url = trim($url); - if ($url === '') { - Setting::put('pipeline_test_server', ''); - $this->testServer = ''; - app(PipelineStatus::class)->refresh(); // drop the stale cached test-step status - $this->dispatch('notify', message: __('release.test_server_cleared')); - - return; - } - if (filter_var($url, FILTER_VALIDATE_URL) === false || ! preg_match('#^https?://#i', $url)) { - $this->dispatch('notify', message: __('release.test_server_invalid'), level: 'error'); - - return; - } - Setting::put('pipeline_test_server', $url); - $this->testServer = $url; - app(PipelineStatus::class)->refresh(); // reflect the new test server immediately - $this->dispatch('notify', message: __('release.test_server_saved')); - } - /** * Open the shared ConfirmAction modal (R5) for the staging release. The issued token carries NO * audit descriptor — applyDeployStaging → deployStaging audits exactly once itself. diff --git a/app/Services/PipelineStatus.php b/app/Services/PipelineStatus.php index 924a0a3..373f242 100644 --- a/app/Services/PipelineStatus.php +++ b/app/Services/PipelineStatus.php @@ -2,16 +2,16 @@ namespace App\Services; -use App\Models\Setting; use Illuminate\Http\Client\PendingRequest; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; /** - * Live status of the build/deploy pipeline for the currently-cut beta, for the dev Release page. - * Queries GitHub (tag mirror + CI run) and the configured test server's /version.json. Each step is - * cached briefly; any failure degrades to 'unknown' (never throws). The read-only GitHub token and the - * private staging slug come from config (env) and are never rendered or put in a URL. + * Live status of the build pipeline for the currently-cut beta, for the dev Release page: tag (Gitea), + * mirror (GitHub-private), CI (GitHub Actions). These are global build facts of one beta — there is no + * "deployed" step because any beta-channel server pulls a release itself (no single staging target). + * Each step is cached briefly; any failure degrades to 'unknown' (never throws). The read-only GitHub + * token and the private staging slug come from config (env) and are never rendered or put in a URL. */ class PipelineStatus { @@ -30,13 +30,11 @@ class PipelineStatus $mirror = $this->mirrorStep($tag); $ci = $this->ciStep($tag); - $test = $this->testStep($tag, $version); $steps = [ ['key' => 'tag', 'state' => 'done', 'detail' => $tag, 'url' => null], $mirror, $ci, - $test, ]; $ciRunning = $mirror['state'] === 'pending' @@ -53,7 +51,7 @@ class PipelineStatus return; } $tag = 'v'.ltrim($version, 'vV'); - foreach (['mirror', 'ci', 'test'] as $step) { + foreach (['mirror', 'ci'] as $step) { Cache::forget("clusev:pipeline:{$tag}:{$step}"); } } @@ -129,30 +127,4 @@ class PipelineStatus } }); } - - /** @return array{key:string,state:string,detail:?string,url:?string} */ - private function testStep(string $tag, string $version): array - { - $url = trim((string) Setting::get('pipeline_test_server', '')); - if ($url === '') { - return ['key' => 'test', 'state' => 'unset', 'detail' => null, 'url' => null]; - } - - return Cache::remember("clusev:pipeline:{$tag}:test", self::TTL_SECONDS, function () use ($url, $version) { - try { - $res = Http::timeout(5)->acceptJson()->get(rtrim($url, '/').'/version.json'); - $running = $res->successful() ? (string) ($res->json('version') ?? '') : ''; - if ($running === '') { - return ['key' => 'test', 'state' => 'unknown', 'detail' => null, 'url' => null]; - } - $state = version_compare(ltrim($running, 'vV'), ltrim($version, 'vV')) >= 0 ? 'done' : 'pending'; - - return ['key' => 'test', 'state' => $state, 'detail' => $running, 'url' => null]; - } catch (\Throwable $e) { - report($e); - - return ['key' => 'test', 'state' => 'unknown', 'detail' => null, 'url' => null]; - } - }); - } } diff --git a/lang/de/release.php b/lang/de/release.php index 04737ee..fdbea2f 100644 --- a/lang/de/release.php +++ b/lang/de/release.php @@ -29,25 +29,17 @@ return [ 'staged_label' => 'Zuletzt gepusht:', 'failed' => 'Release fehlgeschlagen: :reason', - // pipeline rail + // pipeline rail (Tag → Mirror → CI; build readiness of a beta) 'pipeline' => 'Pipeline', 'pipe_sub_gitea' => 'Quelle · Tag wird hier erzeugt', 'pipe_sub_mirror' => 'Automatischer Push-Mirror', 'pipe_sub_ci' => 'Tests laufen', - 'pipe_sub_staging' => 'Beta wird ausgerollt', - 'pipe_sub_test' => 'Beta auf deinem Test-Server', 'no_beta_running' => 'Keine Beta in Arbeit.', - 'step_test' => 'Test-Server', 'state_done' => 'fertig', 'state_running' => 'läuft …', 'state_failed' => 'fehlgeschlagen', 'state_pending' => 'ausstehend', 'state_unknown' => 'unbekannt', - 'state_unset' => 'URL setzen', - 'save' => 'Speichern', - 'test_server_saved' => 'Test-Server gespeichert.', - 'test_server_cleared' => 'Test-Server entfernt.', - 'test_server_invalid' => 'Ungültige URL (http/https).', // confirm modal (R5) 'confirm_title' => 'Beta auf Staging schneiden?', diff --git a/lang/en/release.php b/lang/en/release.php index 1874363..e053dcc 100644 --- a/lang/en/release.php +++ b/lang/en/release.php @@ -29,25 +29,17 @@ return [ 'staged_label' => 'Last pushed:', 'failed' => 'Release failed: :reason', - // pipeline rail + // pipeline rail (Tag → Mirror → CI; build readiness of a beta) 'pipeline' => 'Pipeline', 'pipe_sub_gitea' => 'Source · tag is cut here', 'pipe_sub_mirror' => 'Automatic push mirror', 'pipe_sub_ci' => 'Tests run', - 'pipe_sub_staging' => 'Beta is deployed', - 'pipe_sub_test' => 'Beta on your test server', 'no_beta_running' => 'No beta in flight.', - 'step_test' => 'Test server', 'state_done' => 'done', 'state_running' => 'running …', 'state_failed' => 'failed', 'state_pending' => 'pending', 'state_unknown' => 'unknown', - 'state_unset' => 'set a URL', - 'save' => 'Save', - 'test_server_saved' => 'Test server saved.', - 'test_server_cleared' => 'Test server cleared.', - 'test_server_invalid' => 'Invalid URL (http/https).', // confirm modal (R5) 'confirm_title' => 'Cut a staging beta?', diff --git a/resources/views/livewire/release/index.blade.php b/resources/views/livewire/release/index.blade.php index 8a8748b..ca034b3 100644 --- a/resources/views/livewire/release/index.blade.php +++ b/resources/views/livewire/release/index.blade.php @@ -125,18 +125,17 @@ @foreach ($pipeline['steps'] as $s) @php $names = [ - 'tag' => 'Gitea', 'mirror' => 'GitHub-privat', 'ci' => 'CI', 'test' => __('release.step_test'), + 'tag' => 'Gitea', 'mirror' => 'GitHub-privat', 'ci' => 'CI', ]; $sub = [ 'tag' => __('release.pipe_sub_gitea'), 'mirror' => __('release.pipe_sub_mirror'), - 'ci' => __('release.pipe_sub_ci'), 'test' => __('release.pipe_sub_test'), + 'ci' => __('release.pipe_sub_ci'), ]; $detail = match ($s['state']) { 'done' => $s['detail'] ?? __('release.state_done'), 'running' => __('release.state_running'), 'failed' => __('release.state_failed'), 'pending' => __('release.state_pending'), - 'unset' => __('release.state_unset'), default => __('release.state_unknown'), }; $detailClass = match ($s['state']) { @@ -173,14 +172,6 @@ @else

{{ $detail }}

@endif - - @if ($s['key'] === 'test') -
- - {{ __('release.save') }} -
- @endif @endforeach diff --git a/tests/Feature/PipelineStatusTest.php b/tests/Feature/PipelineStatusTest.php index 3223d07..78af98b 100644 --- a/tests/Feature/PipelineStatusTest.php +++ b/tests/Feature/PipelineStatusTest.php @@ -2,7 +2,6 @@ namespace Tests\Feature; -use App\Models\Setting; use App\Services\PipelineStatus; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\Client\Factory as HttpFactory; @@ -131,29 +130,6 @@ class PipelineStatusTest extends TestCase Http::assertNothingSent(); } - public function test_test_server_step_states(): void - { - Http::fake([ - 'api.github.com/*' => Http::response([], 404), - 'staging.local/version.json' => Http::response(['version' => '0.9.61-beta1']), - ]); - Setting::put('pipeline_test_server', 'http://staging.local'); - $this->assertSame('done', $this->step(app(PipelineStatus::class)->forTrackedBeta(), 'test')['state']); - - $this->resetForNextPhase(); - Http::fake([ - 'api.github.com/*' => Http::response([], 404), - 'staging.local/version.json' => Http::response(['version' => '0.9.60']), - ]); - $this->assertSame('pending', $this->step(app(PipelineStatus::class)->forTrackedBeta(), 'test')['state']); - } - - public function test_test_server_unset_when_no_url(): void - { - Http::fake(['api.github.com/*' => Http::response([], 404)]); - $this->assertSame('unset', $this->step(app(PipelineStatus::class)->forTrackedBeta(), 'test')['state']); - } - public function test_token_is_sent_in_the_header_never_in_the_url(): void { Http::fake(['api.github.com/*' => Http::response(['ref' => 'x'])]); @@ -177,14 +153,4 @@ class PipelineStatusTest extends TestCase $this->assertSame('unknown', $this->step($p, 'mirror')['state']); $this->assertSame('unknown', $this->step($p, 'ci')['state']); } - - public function test_test_server_unreachable_is_unknown(): void - { - Http::fake([ - 'api.github.com/*' => Http::response([], 404), - '*/version.json' => Http::response('nope', 503), - ]); - Setting::put('pipeline_test_server', 'http://staging.local'); - $this->assertSame('unknown', $this->step(app(PipelineStatus::class)->forTrackedBeta(), 'test')['state']); - } } diff --git a/tests/Feature/ReleasePageTest.php b/tests/Feature/ReleasePageTest.php index e015098..e319384 100644 --- a/tests/Feature/ReleasePageTest.php +++ b/tests/Feature/ReleasePageTest.php @@ -4,7 +4,6 @@ namespace Tests\Feature; use App\Livewire\Release\Index; use App\Models\AuditEvent; -use App\Models\Setting; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\RateLimiter; @@ -112,23 +111,4 @@ class ReleasePageTest extends TestCase config()->set('clusev.version', '0.9.60'); Livewire::test(Index::class)->assertViewHas('pipeline', null); } - - public function test_save_test_server_persists_a_valid_url(): void - { - Livewire::test(Index::class)->call('saveTestServer', 'http://staging.local'); - $this->assertSame('http://staging.local', Setting::get('pipeline_test_server')); - } - - public function test_save_test_server_rejects_a_bad_url(): void - { - Livewire::test(Index::class)->call('saveTestServer', 'not-a-url'); - $this->assertNull(Setting::get('pipeline_test_server')); - } - - public function test_save_test_server_empty_clears_it(): void - { - Setting::put('pipeline_test_server', 'http://staging.local'); - Livewire::test(Index::class)->call('saveTestServer', ''); - $this->assertSame('', (string) Setting::get('pipeline_test_server', '')); - } }