Skip to main content

Content & marketing

Deploy Console code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/deploy-console.blade.php

@props([
    'repository' => 'harbour/app',
    'branch' => 'main',
    'commit' => '7f3c2e1',
    'environment' => 'Production',
])

@php
    /*
    | Deploy console hero mockup. An alternative to the classic dashboard
    | window: a release pipeline mid-flight. Left column shows the pipeline
    | stages, right column tails the deploy log, and a canary strip across
    | the bottom tracks the rollout. All static markup — no JS, no images.
    |
    | Usage (drop into a hero media slot):
    |   <x-ui.deploy-console />
    |   <x-ui.deploy-console repository="acme/api" branch="release" commit="09fe41c" />
    */
    $steps = [
        ['state' => 'done', 'label' => 'Build', 'meta' => '832 modules via Vite', 'time' => '48s'],
        ['state' => 'done', 'label' => 'Tests', 'meta' => '312 passed · 0 failed', 'time' => '2m 04s'],
        ['state' => 'running', 'label' => 'Canary', 'meta' => '25% of traffic', 'time' => 'running'],
        ['state' => 'queued', 'label' => 'Promote', 'meta' => 'waits on canary health', 'time' => 'queued'],
    ];
@endphp

<x-ui.window variant="app" title="Deploy — {{ $repository }}" flush {{ $attributes->merge(['class' => 'deploy-console text-left']) }}>
    {{-- Release header: ref being shipped and where it's going. --}}
    <div class="flex flex-wrap items-center gap-x-4 gap-y-2 border-b border-gray-200 px-5 py-3 dark:border-gray-800">
        <span class="flex items-center gap-1.5 text-sm font-medium text-gray-700 dark:text-gray-200">
            <x-ui.icon name="git-branch" size="base" class="text-gray-400" />
            {{ $branch }}
        </span>
        <span class="font-mono text-xs text-gray-400">{{ $commit }}</span>
        <span class="text-xs text-gray-400">&ldquo;Tune cache headers for feed endpoints&rdquo;</span>
        <span class="ml-auto flex items-center gap-2">
            <x-ui.badge variant="brand" size="sm">{{ $environment }}</x-ui.badge>
            <x-ui.badge variant="green" size="sm" dot>Healthy</x-ui.badge>
        </span>
    </div>

    <div class="grid lg:grid-cols-[0.85fr_1.3fr]">
        {{-- Pipeline stages --}}
        <div class="border-b border-gray-200 p-5 dark:border-gray-800 lg:border-b-0 lg:border-r">
            <p class="text-xs font-semibold uppercase tracking-[0.14em] text-gray-400">Pipeline</p>
            <ul class="mt-4 space-y-1">
                @foreach ($steps as $step)
                    <li @class([
                        'flex items-center gap-3 rounded-lg px-2 py-2.5',
                        'bg-brand-50/70 ring-1 ring-brand-200 dark:bg-brand-950/40 dark:ring-brand-900' => $step['state'] === 'running',
                    ])>
                        @if ($step['state'] === 'done')
                            <x-ui.icon name="check-circle" weight="fill" size="lg" class="shrink-0 text-green-500" />
                        @elseif ($step['state'] === 'running')
                            <x-ui.icon name="circle-notch" weight="bold" size="lg" class="shrink-0 text-brand-500 motion-safe:animate-spin" />
                        @else
                            <x-ui.icon name="circle-dashed" size="lg" class="shrink-0 text-gray-300 dark:text-gray-600" />
                        @endif
                        <span class="min-w-0 flex-1">
                            <span class="block text-sm font-medium text-gray-900 dark:text-white">{{ $step['label'] }}</span>
                            <span class="block truncate text-xs text-gray-400">{{ $step['meta'] }}</span>
                        </span>
                        <span class="shrink-0 font-mono text-[11px] tabular-nums text-gray-400">{{ $step['time'] }}</span>
                    </li>
                @endforeach
            </ul>
        </div>

        {{-- Log tail: constant dark surface, like an editor pane. --}}
        <div class="bg-gray-950 p-5 font-mono text-xs leading-relaxed" aria-label="Deploy log">
            <div class="space-y-1.5 whitespace-nowrap">
                <p><span class="text-gray-600">14:02:11</span> <span class="text-brand-300">build</span> <span class="text-gray-300">Compiling assets with Vite&hellip;</span></p>
                <p><span class="text-gray-600">14:02:59</span> <span class="text-brand-300">build</span> <span class="text-green-400">✓</span> <span class="text-gray-300"><span class="text-amber-200">832</span> modules transformed in <span class="text-amber-200">48s</span></span></p>
                <p><span class="text-gray-600">14:03:02</span> <span class="text-brand-300">test</span> <span class="text-gray-300">Running suite (Pest, parallel &times;4)</span></p>
                <p><span class="text-gray-600">14:05:06</span> <span class="text-brand-300">test</span> <span class="text-green-400">✓</span> <span class="text-gray-300"><span class="text-amber-200">312</span> passed, <span class="text-amber-200">0</span> failed</span></p>
                <p><span class="text-gray-600">14:05:10</span> <span class="text-brand-300">deploy</span> <span class="text-gray-300">Releasing <span class="text-green-300">{{ $commit }}</span> to canary (<span class="text-amber-200">25%</span>)</span></p>
                <p><span class="text-gray-600">14:05:31</span> <span class="text-brand-300">watch</span> <span class="text-gray-300">p95 <span class="text-amber-200">182ms</span> &middot; error rate <span class="text-amber-200">0.00%</span></span></p>
                <p><span class="text-gray-600">14:06:02</span> <span class="text-brand-300">watch</span> <span class="text-gray-400">canary tracking stable &mdash; no regressions detected</span><span class="ml-1 inline-block h-3 w-1.5 translate-y-0.5 bg-gray-500 motion-safe:animate-dot-pulse"></span></p>
            </div>
        </div>
    </div>

    {{-- Canary strip: rollout progress plus a latency comparison. --}}
    <div class="flex flex-wrap items-center gap-x-6 gap-y-3 border-t border-gray-200 px-5 py-4 dark:border-gray-800">
        <div class="min-w-44 flex-1">
            <div class="flex items-center justify-between text-xs">
                <span class="font-medium text-gray-700 dark:text-gray-200">Canary rollout</span>
                <span class="tabular-nums text-gray-400">25% &rarr; 100%</span>
            </div>
            <div class="mt-2 h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800">
                <div class="h-full w-1/4 rounded-full bg-brand-500"></div>
            </div>
        </div>
        <dl class="flex items-center gap-5 text-xs">
            <div>
                <dt class="text-gray-400">p95 canary</dt>
                <dd class="mt-0.5 font-semibold tabular-nums text-gray-900 dark:text-white">182ms</dd>
            </div>
            <div>
                <dt class="text-gray-400">p95 stable</dt>
                <dd class="mt-0.5 font-semibold tabular-nums text-gray-900 dark:text-white">176ms</dd>
            </div>
            <div>
                <dt class="text-gray-400">Promotes in</dt>
                <dd class="mt-0.5 font-semibold tabular-nums text-gray-900 dark:text-white">12m</dd>
            </div>
        </dl>
    </div>
</x-ui.window>