Engineering headline
Deploy frequency, lead time, change failure rate and time to restore over the last thirty days, a thin median saying how many incidents it stands on; reads engineeringStats().
Preview
import { StatCard } from "@/components/ui/stat-card"
import { StatCardGroup } from "@/components/ui/stat-card-group"
import { engineeringStats } from "../data"
export function EngineeringStats() {
return (
<StatCardGroup data-widget="widget-engineering-overview-engineering-stats" columns={4}>
{engineeringStats().map((stat) => (
<StatCard
key={stat.key}
label={stat.label}
value={
stat.note ? (
<span className="flex items-baseline gap-1.5">
{stat.value}
<span className="text-sm font-normal text-muted-foreground">· {stat.note}</span>
</span>
) : (
stat.value
)
}
description={stat.description}
/>
))}
</StatCardGroup>
)
}Install
$
npx shadcn@latest add @vibra/widget-engineering-overview-engineering-statsNeeds the @vibra registry in your components.json — set it up once.
Source
import { StatCard } from "@/components/ui/stat-card"
import { StatCardGroup } from "@/components/ui/stat-card-group"
import { engineeringStats } from "../data"
export function EngineeringStats() {
return (
<StatCardGroup data-widget="widget-engineering-overview-engineering-stats" columns={4}>
{engineeringStats().map((stat) => (
<StatCard
key={stat.key}
label={stat.label}
value={
stat.note ? (
<span className="flex items-baseline gap-1.5">
{stat.value}
<span className="text-sm font-normal text-muted-foreground">· {stat.note}</span>
</span>
) : (
stat.value
)
}
description={stat.description}
/>
))}
</StatCardGroup>
)
}/**
* What this page reads. `db.deployments` is the whole pipeline history, and
* three of the four headline numbers fall straight out of it: how often
* production ships, how often a production deploy fails, and how long the
* next green one takes to arrive after a red one.
*
* Two things the entity does not record are derived, and neither is a literal.
* Lead time is a *rule* over the row db does have — a deploy off `main` was
* cut hours after its commit, a feature branch days, with a jitter fixed by
* `seeded("dashboard-engineering")` so the same deploy always reads the same.
* The open pull requests have no entity at all, so they are generated once
* from the same generator over the branches in `db.deployments` and the people
* in `db.members`. "Now" is `REFERENCE_DATE`; nothing here reads a clock.
*/
import { formatDuration, formatNumber, formatPercent, getInitials } from "@/lib/format"
import {
db,
intBetween,
REFERENCE_DATE,
seeded,
type Deployment,
type Member,
} from "@/lib/sample-data"
export type { Deployment }
const HOUR_MS = 3_600_000
const DAY_MS = 86_400_000
/** The window the four headline numbers are measured over. */
export const WINDOW_DAYS = 30
const WINDOW_START = REFERENCE_DATE.getTime() - WINDOW_DAYS * DAY_MS
// One series for the whole block: one lead time per deployment first, then the
// pull requests.
const SEED = "dashboard-engineering"
const rand = seeded(SEED)
const BY_TIME = db.deployments.all().sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime())
const PRODUCTION = BY_TIME.filter((deployment) => deployment.environment === "production")
// How long a change waits before it ships, in hours: work on main goes out the
// same day, a feature branch takes days. The jitter is drawn once per
// deployment, in time order, so a row's lead time never moves.
const LEAD_HOURS = new Map<string, number>(
BY_TIME.map((deployment) => [
deployment.id,
deployment.branch === "main" ? 2 + rand() * 7 : 14 + rand() * 60,
])
)
/** How long this change waited between its first commit and this deploy. */
export function leadTimeHours(deployment: Deployment): number {
return LEAD_HOURS.get(deployment.id) ?? 0
}
const inWindow = (deployment: Deployment) => deployment.startedAt.getTime() >= WINDOW_START
const median = (values: number[]): number => {
if (values.length === 0) return 0
const sorted = [...values].sort((a, b) => a - b)
return sorted[Math.floor(sorted.length / 2)]
}
/**
* How long production stayed broken: from a failed production deploy inside
* the window to the next successful one, in milliseconds. The recovery itself
* may land outside the window — what is windowed is the failure. A failure
* with nothing green after it is still open and cannot be measured.
*/
function recoveryTimes(): number[] {
const times: number[] = []
PRODUCTION.forEach((deployment, index) => {
if (deployment.status !== "failed" || !inWindow(deployment)) return
const fixed = PRODUCTION.slice(index + 1).find((next) => next.status === "success")
if (!fixed) return
times.push(fixed.startedAt.getTime() - deployment.startedAt.getTime())
})
return times
}
// Below this many incidents a median is one or two readings wearing a
// statistic's clothes, so the card says how many it stands on.
const THIN_SAMPLE = 5
export type EngineeringStat = {
key: string
label: string
value: string
/** Trails the value in quieter type — the sample a thin median stands on. */
note?: string
description: string
}
/** Deploy frequency, lead time, change failure rate and time to restore. */
export function engineeringStats(): EngineeringStat[] {
const shipped = PRODUCTION.filter(inWindow)
// A cancelled deploy never reached production, so it is neither a change
// that shipped nor a change that failed: it leaves the ratio entirely.
const completed = shipped.filter(
(deployment) => deployment.status === "success" || deployment.status === "failed"
)
const failed = completed.filter((deployment) => deployment.status === "failed")
const recoveries = recoveryTimes()
return [
{
key: "frequency",
label: "Deploy frequency",
value: `${formatNumber(shipped.length / WINDOW_DAYS, { maximumFractionDigits: 1 })}/day`,
description: `${shipped.length} production deploys in ${WINDOW_DAYS} days`,
},
{
key: "lead-time",
label: "Lead time",
value: formatDuration(median(shipped.map(leadTimeHours)) * HOUR_MS),
description: "median, first commit to production",
},
{
key: "failure-rate",
label: "Change failure rate",
value: formatPercent(completed.length === 0 ? 0 : failed.length / completed.length, {
maximumFractionDigits: 1,
}),
description: `${failed.length} of ${completed.length} completed deploys failed`,
},
{
key: "mttr",
label: "Time to restore",
value: formatDuration(median(recoveries)),
...(recoveries.length < THIN_SAMPLE
? { note: `${recoveries.length} incident${recoveries.length === 1 ? "" : "s"}` }
: {}),
description: "median, failed deploy to the next green one",
},
]
}
export type WeekPoint = { week: string; succeeded: number; failed: number }
const CHART_WEEKS = 12
const WEEK_LABEL = new Intl.DateTimeFormat("en-US", {
month: "short",
day: "numeric",
timeZone: "UTC",
})
/** Production deploys per week over the last twelve, green against red. */
export function deploysByWeek(): WeekPoint[] {
const end = REFERENCE_DATE.getTime()
return Array.from({ length: CHART_WEEKS }, (_, index) => {
const from = end - (CHART_WEEKS - index) * 7 * DAY_MS
const to = from + 7 * DAY_MS
const week = PRODUCTION.filter(
(deployment) =>
deployment.startedAt.getTime() >= from && deployment.startedAt.getTime() < to
)
return {
week: WEEK_LABEL.format(new Date(from)),
succeeded: week.filter((deployment) => deployment.status === "success").length,
failed: week.filter((deployment) => deployment.status === "failed").length,
}
})
}
/** The last production deploys, newest first. */
export function productionTimeline(limit = 6): Deployment[] {
return [...PRODUCTION].reverse().slice(0, limit)
}
/** The last deploys to any environment, newest first. */
export function recentDeployments(limit = 8): Deployment[] {
return [...BY_TIME].reverse().slice(0, limit)
}
export type PullRequest = {
id: string
number: number
title: string
branch: string
author: Member
additions: number
deletions: number
checks: "passing" | "failing" | "running"
reviews: number
openedAt: Date
}
// How a branch name reads as a pull request title: "feat/sso-login" becomes
// "Sso login". The branch is the record; the sentence is derived from it.
function titleFor(branch: string): string {
const words = branch.split("/").slice(1).join(" ").replace(/-/g, " ")
return words.charAt(0).toUpperCase() + words.slice(1)
}
const PR_COUNT = 6
function generatePullRequests(): PullRequest[] {
// The pull requests come after the lead times in the block's series: that
// part of it is replayed per request, so the authors are the members as they
// are now, a rename or a deactivation included, and every other figure is
// the one it always was.
const rand = seeded(SEED)
for (let drawn = 0; drawn < BY_TIME.length; drawn++) rand()
// Every branch the pipeline has seen, except main, newest first.
const branches = [
...new Set(
[...BY_TIME].reverse().map((deployment) => deployment.branch).filter((branch) => branch !== "main")
),
].slice(0, PR_COUNT)
const authors = db.members.all().filter((member) => member.status === "active")
return branches.map((branch, index) => {
const checks = rand()
return {
id: branch,
number: 1200 + index * intBetween(rand, 3, 19),
title: titleFor(branch),
branch,
author: authors[intBetween(rand, 0, authors.length - 1)],
additions: intBetween(rand, 12, 940),
deletions: intBetween(rand, 4, 420),
checks: checks < 0.68 ? "passing" : checks < 0.86 ? "failing" : "running",
reviews: intBetween(rand, 0, 3),
openedAt: new Date(REFERENCE_DATE.getTime() - intBetween(rand, 2, 260) * HOUR_MS),
}
})
}
/** What is waiting for review, oldest first. */
export function openPullRequests(): PullRequest[] {
return generatePullRequests().sort((a, b) => a.openedAt.getTime() - b.openedAt.getTime())
}
/** How long a deploy took, written out. */
export function deployDuration(deployment: Deployment): string {
return formatDuration(deployment.durationSec * 1000)
}
/** The moment every "ago" on this page is measured against. */
export const NOW = REFERENCE_DATE
/** How long ago something happened, in whole minutes, hours or days. */
export function since(at: Date): string {
const ms = REFERENCE_DATE.getTime() - at.getTime()
if (ms < HOUR_MS) return `${Math.max(1, Math.round(ms / 60_000))}m ago`
return ms < DAY_MS
? `${Math.round(ms / HOUR_MS)}h ago`
: `${Math.round(ms / DAY_MS)}d ago`
}
/** The bell's contents: the newest notifications, unread first in the panel. */
export function shellNotifications() {
return db.notifications
.all()
.sort((a, b) => b.at.getTime() - a.at.getTime())
.slice(0, 6)
.map(({ id, title, description, at, read, href }) => ({ id, title, description, at, read, href }))
}
function ownerRow(): Member {
return db.members.all().find((member) => member.role === "owner") ?? db.members.all()[0]
}
/** The person looking at the page: whoever owns this workspace. */
export function currentUser() {
const owner = ownerRow()
return { name: owner.name, email: owner.email, initials: getInitials(owner.name), avatarUrl: owner.avatarUrl }
}
// Fixed to UTC so the line reads the same wherever the page is rendered.
const WINDOW_LABEL = new Intl.DateTimeFormat("en-US", { dateStyle: "medium", timeZone: "UTC" })
/** The window the headline numbers cover, written out. */
export function windowLabel(): string {
return `${WINDOW_LABEL.format(new Date(WINDOW_START))} – ${WINDOW_LABEL.format(REFERENCE_DATE)} UTC`
}Its page
On its page the card sits among the rest of the dashboard and shares its range and its data with them.
From the Engineering dashboard page