feat(release): live pipeline rail + test-server input on the Release page
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/v1-foundation
parent
0ac819e4ad
commit
787e48d8fd
|
|
@ -35,6 +35,19 @@ return [
|
||||||
'pipe_sub_mirror' => 'Automatischer Push-Mirror',
|
'pipe_sub_mirror' => 'Automatischer Push-Mirror',
|
||||||
'pipe_sub_ci' => 'Tests laufen',
|
'pipe_sub_ci' => 'Tests laufen',
|
||||||
'pipe_sub_staging' => 'Beta wird ausgerollt',
|
'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 modal (R5)
|
||||||
'confirm_title' => 'Beta auf Staging schneiden?',
|
'confirm_title' => 'Beta auf Staging schneiden?',
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,19 @@ return [
|
||||||
'pipe_sub_mirror' => 'Automatic push mirror',
|
'pipe_sub_mirror' => 'Automatic push mirror',
|
||||||
'pipe_sub_ci' => 'Tests run',
|
'pipe_sub_ci' => 'Tests run',
|
||||||
'pipe_sub_staging' => 'Beta is deployed',
|
'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 modal (R5)
|
||||||
'confirm_title' => 'Cut a staging beta?',
|
'confirm_title' => 'Cut a staging beta?',
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,6 @@
|
||||||
$tiles[] = ['target' => $targets['patch'], 'label' => __('release.kind_patch'), 'icon' => 'tag', 'primary' => false];
|
$tiles[] = ['target' => $targets['patch'], 'label' => __('release.kind_patch'), 'icon' => 'tag', 'primary' => false];
|
||||||
$tiles[] = ['target' => $targets['minor'], 'label' => __('release.kind_minor'), 'icon' => 'tag', 'primary' => false];
|
$tiles[] = ['target' => $targets['minor'], 'label' => __('release.kind_minor'), 'icon' => 'tag', 'primary' => false];
|
||||||
$tiles[] = ['target' => $targets['major'], 'label' => __('release.kind_major'), 'icon' => 'git-branch', 'primary' => false];
|
$tiles[] = ['target' => $targets['major'], 'label' => __('release.kind_major'), 'icon' => 'git-branch', 'primary' => false];
|
||||||
|
|
||||||
$steps = [
|
|
||||||
['name' => 'Gitea', 'sub' => __('release.pipe_sub_gitea'), 'active' => $pendingId !== null],
|
|
||||||
['name' => 'GitHub-privat', 'sub' => __('release.pipe_sub_mirror'), 'active' => false],
|
|
||||||
['name' => 'CI', 'sub' => __('release.pipe_sub_ci'), 'active' => false],
|
|
||||||
['name' => 'Staging', 'sub' => __('release.pipe_sub_staging'), 'active' => false],
|
|
||||||
];
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="space-y-5">
|
<div class="space-y-5">
|
||||||
|
|
@ -123,28 +116,72 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Right: pipeline rail --}}
|
{{-- Right: live pipeline rail --}}
|
||||||
<x-panel :title="__('release.pipeline')">
|
<x-panel :title="__('release.pipeline')">
|
||||||
|
@if ($pipeline === null)
|
||||||
|
<p class="font-mono text-[11px] text-ink-4">{{ __('release.no_beta_running') }}</p>
|
||||||
|
@else
|
||||||
<ol>
|
<ol>
|
||||||
@foreach ($steps as $s)
|
@foreach ($pipeline['steps'] as $s)
|
||||||
<li class="flex gap-3" wire:key="step-{{ $loop->index }}">
|
@php
|
||||||
|
$names = [
|
||||||
|
'tag' => 'Gitea', 'mirror' => 'GitHub-privat', 'ci' => 'CI', 'test' => __('release.step_test'),
|
||||||
|
];
|
||||||
|
$sub = [
|
||||||
|
'tag' => __('release.pipe_sub_gitea'), 'mirror' => __('release.pipe_sub_mirror'),
|
||||||
|
'ci' => __('release.pipe_sub_ci'), 'test' => __('release.pipe_sub_test'),
|
||||||
|
];
|
||||||
|
$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'),
|
||||||
|
};
|
||||||
|
@endphp
|
||||||
|
<li class="flex gap-3" wire:key="pstep-{{ $s['key'] }}">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<span @class([
|
<span class="grid h-6 w-6 shrink-0 place-items-center rounded-full border border-line bg-inset">
|
||||||
'grid h-6 w-6 shrink-0 place-items-center rounded-full border font-mono text-[10px]',
|
@if ($s['state'] === 'running')
|
||||||
'border-accent/40 bg-accent/15 text-accent-text' => $s['active'],
|
<x-icon name="rotate" class="h-3 w-3 animate-spin text-warning" />
|
||||||
'border-line bg-inset text-ink-3' => ! $s['active'],
|
@elseif ($s['state'] === 'done')
|
||||||
])>{{ $loop->iteration }}</span>
|
<x-status-dot status="online" />
|
||||||
|
@elseif ($s['state'] === 'failed')
|
||||||
|
<x-status-dot status="offline" />
|
||||||
|
@elseif ($s['state'] === 'pending')
|
||||||
|
<x-status-dot status="pending" />
|
||||||
|
@else
|
||||||
|
<span class="h-1.5 w-1.5 rounded-full bg-ink-4"></span>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
@unless ($loop->last)
|
@unless ($loop->last)
|
||||||
<span class="my-1 w-px flex-1 bg-line" aria-hidden="true"></span>
|
<span class="my-1 w-px flex-1 bg-line" aria-hidden="true"></span>
|
||||||
@endunless
|
@endunless
|
||||||
</div>
|
</div>
|
||||||
<div @class(['min-w-0', 'pb-5' => ! $loop->last])>
|
<div @class(['min-w-0', 'pb-5' => ! $loop->last])>
|
||||||
<p class="font-mono text-xs {{ $s['active'] ? 'text-accent-text' : 'text-ink' }}">{{ $s['name'] }}</p>
|
<p class="font-mono text-xs text-ink">{{ $names[$s['key']] }}</p>
|
||||||
<p class="mt-0.5 font-mono text-[11px] text-ink-4">{{ $s['sub'] }}</p>
|
@if ($s['key'] === 'ci' && $s['url'])
|
||||||
|
<a href="{{ $s['url'] }}" target="_blank" rel="noopener" class="mt-0.5 block font-mono text-[11px] text-cyan hover:text-cyan-bright">{{ $detail }}</a>
|
||||||
|
@else
|
||||||
|
<p class="mt-0.5 font-mono text-[11px] text-ink-4">{{ $detail }}</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($s['key'] === 'test')
|
||||||
|
<div class="mt-2 flex items-center gap-2">
|
||||||
|
<input type="url" wire:model="testServer" placeholder="https://test-server"
|
||||||
|
class="h-8 w-full rounded-md border border-line bg-inset px-2.5 font-mono text-[11px] text-ink placeholder:text-ink-4 focus:border-accent/40 focus:outline-none" />
|
||||||
|
<x-btn variant="secondary" wire:click="saveTestServer($wire.testServer)" wire:loading.attr="disabled">{{ __('release.save') }}</x-btn>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@endforeach
|
@endforeach
|
||||||
</ol>
|
</ol>
|
||||||
|
@if ($pipeline['ciRunning'])
|
||||||
|
<span class="hidden" wire:poll.5s="pollPipeline"></span>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
</x-panel>
|
</x-panel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue