Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fd48e63
fix: ui inconsistencies
ogzhanolguncu Feb 27, 2026
4b10d44
fix: aniamtions
ogzhanolguncu Feb 27, 2026
48fbf1d
feat: finalize deployment steps page
ogzhanolguncu Feb 27, 2026
b98c769
fix: missing deployentId case
ogzhanolguncu Feb 27, 2026
45c6cb7
refactor: file locations
ogzhanolguncu Feb 27, 2026
6104fe4
feat: add final step to onboarding
ogzhanolguncu Feb 27, 2026
28e3ab1
fix: skeletons
ogzhanolguncu Feb 27, 2026
6817f84
feat: add deployment info to onboarding
ogzhanolguncu Feb 27, 2026
cd3ddb9
refactor: show deployment at last onboarding step
ogzhanolguncu Feb 27, 2026
c7bee00
feat: use the same active deployment card everywhere
ogzhanolguncu Feb 27, 2026
aae69a5
fix: minor spacing issues according to the lastest design
ogzhanolguncu Feb 27, 2026
2544fce
fix: give some depth to icons
ogzhanolguncu Feb 27, 2026
a0b86f2
fix: ui inconsistencies
ogzhanolguncu Feb 27, 2026
8168daa
feat: add repo icons
ogzhanolguncu Mar 2, 2026
0c145ef
chore: fmt
ogzhanolguncu Mar 2, 2026
70ada90
fix: ctrl-worker manifest
ogzhanolguncu Mar 2, 2026
0770b4c
feat: add auto redirect
ogzhanolguncu Mar 2, 2026
8d8e8d2
fix: ui and flow issues
ogzhanolguncu Mar 2, 2026
310c5df
fix: ui issues continues
ogzhanolguncu Mar 2, 2026
b37dd30
fix: deployment list issues
ogzhanolguncu Mar 2, 2026
46ef5ab
fix: deployment list spacings
ogzhanolguncu Mar 2, 2026
895f9a8
feat: add virtualization to reposelect
ogzhanolguncu Mar 2, 2026
4587866
refactor: make consistent colors
ogzhanolguncu Mar 2, 2026
d60503b
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 2, 2026
7da4b91
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Mar 3, 2026
22d7817
fix: nextjs serverside param fetch issue
ogzhanolguncu Mar 3, 2026
0f9faa1
fix: dont let user come back
ogzhanolguncu Mar 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions dev/k8s/manifests/ctrl-worker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,16 @@ data:
url = "clickhouse://default:password@clickhouse:9000?secure=false&skip_verify=true"
admin_url = "clickhouse://unkey_user_admin:C57RqT5EPZBqCJkMxN9mEZZEzMPcw9yBlwhIizk99t7kx6uLi9rYmtWObsXzdl@clickhouse:9000?secure=false&skip_verify=true"

# GitHub App credentials for authenticating with the GitHub API.
# app_id is resolved at runtime via os.ExpandEnv from the github-credentials secret.
# Without a valid app_id the generated JWT has issuer "0" and GitHub returns 401.
[github]
app_id = 0
app_id = ${UNKEY_GITHUB_APP_ID}
private_key_pem = """${UNKEY_GITHUB_PRIVATE_KEY_PEM}"""
allow_unauthenticated_deployments = true
# Set to true only for local dev without GitHub credentials configured.
# When true, deployments skip GitHub auth entirely works only with public repos.
# Controlled via UNKEY_ALLOW_UNAUTHENTICATED_DEPLOYMENTS in .env.github.
allow_unauthenticated_deployments = ${UNKEY_ALLOW_UNAUTHENTICATED_DEPLOYMENTS}

---
apiVersion: apps/v1
Expand Down Expand Up @@ -110,6 +116,18 @@ spec:
name: github-credentials
key: UNKEY_GITHUB_PRIVATE_KEY_PEM
optional: true
- name: UNKEY_GITHUB_APP_ID
valueFrom:
secretKeyRef:
name: github-credentials
key: UNKEY_GITHUB_APP_ID
optional: true
- name: UNKEY_ALLOW_UNAUTHENTICATED_DEPLOYMENTS
valueFrom:
secretKeyRef:
name: github-credentials
key: UNKEY_ALLOW_UNAUTHENTICATED_DEPLOYMENTS
optional: true
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
Expand Down
2 changes: 1 addition & 1 deletion web/apps/dashboard/app/(app)/[workspaceSlug]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function WorkspaceLoadingFallback() {
<div className="flex items-center justify-center w-full h-full min-h-[200px]">
<div className="flex flex-col items-center gap-4">
<Loading size={24} />
<p className="text-sm text-gray-600 dark:text-gray-400">Loading workspace...</p>
<p className="text-sm text-gray-600 dark:text-gray-400">Lasdasdoading workspace...</p>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ export function Card({
children: ReactNode;
className?: string;
}) {
return <div className={cn("border border-gray-4 w-full", className)}>{children}</div>;
return (
<div className={cn("border border-gray-4 w-full rounded-[14px]", className)}>{children}</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { TimestampInfo } from "@unkey/ui";
import { Fragment } from "react/jsx-runtime";
import type { BuildStepRow } from "./columns";

export function BuildStepLogsExpanded({ step }: { step: BuildStepRow }) {
if (!step.logs || step.logs.length === 0) {
return (
<tr>
<td colSpan={6} className="px-8 py-4 text-sm text-gray-9">
No logs available for this step
</td>
</tr>
);
}

return (
<>
<tr>
<td className="border-l-2 border-accent-7 p-0" />
</tr>
{step.logs.map((log, idx) => (
<Fragment key={`row-group-${log.time}-${idx}`}>
<tr key={`spacer-${log.time}-${idx}`} style={{ height: "4px" }}>
<td className="border-l-2 border-accent-7 p-0" />
</tr>
<tr key={`${log.time}-${idx}`}>
<td className="border-l-2 border-accent-7 py-0" />
<td className="py-0">
<TimestampInfo
displayType="local_hours_with_millis"
value={log.time}
className="font-mono text-xs text-grayA-9 hover:underline decoration-dotted"
/>
</td>
<td className="py-0" />
<td colSpan={3} className="h-[26px] py-[1px]">
<span className="whitespace-pre-wrap font-mono text-xs text-gray-12 break-all">
{log.message}
</span>
</td>
</tr>
</Fragment>
))}
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ export type BuildStepRow = BuildStep & {
export const buildStepsColumns: Column<BuildStepRow>[] = [
{
key: "expand",
width: "32px",
width: "25px",
cellClassName: "p-0",
render: (step) =>
step.has_logs ? (
<div className="size-4 flex items-center justify-center ">
<div className="size-4 flex items-center justify-center w-full">
<CaretRight
iconSize="sm-regular"
className={cn(
"shrink-0 transition-transform text-gray-9 ",
"shrink-0 transition-transform text-gray-11",
step._isExpanded && "rotate-90",
)}
/>
Expand All @@ -29,8 +30,7 @@ export const buildStepsColumns: Column<BuildStepRow>[] = [
},
{
key: "started_at",
//header: "Started At",
width: "180px",
width: "85px",
render: (step) => (
<div className="font-mono text-xs truncate max-w-[300px] flex items-center gap-2 ">
<TimestampInfo
Expand Down Expand Up @@ -60,22 +60,19 @@ export const buildStepsColumns: Column<BuildStepRow>[] = [
},
{
key: "name",
// header: "Step",
width: "250px",
render: (step) => (
<div
className="font-mono text-xs truncate max-w-[300px] flex items-center gap-2"
className="font-mono text-xs truncate max-w-[300px] flex items-center gap-2 text-gray-12"
title={step.name}
>
<span className="truncate">{step.name}</span>
</div>
),
},

{
key: "error",
//header: "Error",
width: "300px",
width: "auto",
render: (step) => {
if (!step.error) {
return null;
Expand All @@ -89,8 +86,7 @@ export const buildStepsColumns: Column<BuildStepRow>[] = [
},
{
key: "duration",
//header: "Duration",
width: "10%",
width: "115px",
render: (step) => {
const duration = step.completed_at - step.started_at;
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
"use client";

import { VirtualTable } from "@/components/virtual-table/index";
import { cn } from "@/lib/utils";
import { BookBookmark } from "@unkey/icons";
import { Button, Empty } from "@unkey/ui";
import { useState } from "react";
import { BuildStepLogsExpanded } from "./build-step-logs-expanded";
import { type BuildStepRow, buildStepsColumns } from "./columns/build-steps";
import { getBuildStepRowClass } from "./utils/get-build-step-row-class";
import { type BuildStepRow, buildStepsColumns } from "./columns";
import { getBuildStepRowClass } from "./get-row-class";
import {
DurationColumnSkeleton,
NameColumnSkeleton,
StartedAtColumnSkeleton,
StatusColumnSkeleton,
} from "./skeletons";

type Props = {
steps: BuildStepRow[];
Expand All @@ -15,7 +22,6 @@ type Props = {
export const DeploymentBuildStepsTable: React.FC<Props> = ({ steps }) => {
const [expandedIds, setExpandedIds] = useState<Set<string | number>>(new Set());

// Enrich steps with expansion state for chevron rendering
const enrichedSteps = steps.map((step) => ({
...step,
_isExpanded: expandedIds.has(step.step_id),
Expand All @@ -26,13 +32,35 @@ export const DeploymentBuildStepsTable: React.FC<Props> = ({ steps }) => {
data={enrichedSteps}
isLoading={steps.length === 0}
columns={buildStepsColumns}
renderSkeletonRow={({ columns, rowHeight }) =>
columns.map((column, idx) => (
<td
key={column.key}
className={cn(
"text-xs align-middle whitespace-nowrap",
idx === 0 ? "pl-[18px]" : "",
column.cellClassName,
)}
style={{ height: `${rowHeight}px` }}
>
{column.key === "started_at" && <StartedAtColumnSkeleton />}
{column.key === "status" && <StatusColumnSkeleton />}
{column.key === "name" && <NameColumnSkeleton />}
{column.key === "duration" && <DurationColumnSkeleton />}
</td>
))
}
keyExtractor={(step) => step.step_id}
rowClassName={(step) => getBuildStepRowClass(step)}
expandedIds={expandedIds}
onExpandedChange={setExpandedIds}
fixedHeight={256}
isExpandable={(step) => step.has_logs}
renderExpanded={(step) => <BuildStepLogsExpanded step={step} />}
config={{
containerPadding: "px-0 py-0",
className: "bg-transparent",
}}
emptyState={
<div className="w-full flex justify-center items-center h-full">
<Empty className="w-[400px] flex items-start">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cn } from "@unkey/ui/src/lib/utils";
import type { BuildStepRow } from "../columns/build-steps";
import type { BuildStepRow } from "./columns";

export function getBuildStepRowClass(step: BuildStepRow): string {
if (!step?.step_id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const StartedAtColumnSkeleton = () => (
<div className="h-3 w-16 bg-grayA-3 rounded animate-pulse" />
);

export const StatusColumnSkeleton = () => (
<div className="size-4 bg-grayA-3 rounded-full animate-pulse" />
);

export const NameColumnSkeleton = () => (
<div className="h-3 w-[500px] bg-grayA-3 rounded animate-pulse" />
);

export const DurationColumnSkeleton = () => (
<div className="h-3 w-14 bg-grayA-3 rounded animate-pulse" />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use client";

import { formatCpuParts, formatMemoryParts } from "@/lib/utils/deployment-formatters";
import { Bolt, Cloud, Grid, LayoutRight } from "@unkey/icons";
import { Button, InfoTooltip } from "@unkey/ui";
import { ActiveDeploymentCard } from "../../../../components/active-deployment-card";
import { DeploymentStatusBadge } from "../../../../components/deployment-status-badge";
import { InfoChip } from "../../../../components/info-chip";
import { RegionFlags } from "../../../../components/region-flags";
import { Section, SectionHeader } from "../../../../components/section";
import { useOptionalProjectLayout } from "../../../layout-provider";
import { useDeployment } from "../layout-provider";

export function DeploymentInfo({ title = "Deployment" }: { title?: string }) {
const { deployment } = useDeployment();
const projectLayout = useOptionalProjectLayout();
const deploymentStatus = deployment.status;

return (
<Section>
<SectionHeader icon={<Cloud iconSize="md-regular" className="text-gray-9" />} title={title} />
<ActiveDeploymentCard
deploymentId={deployment.id}
trailingContent={
<div className="flex gap-1.5 items-center">
<div className="2xl:flex gap-1.5 items-center hidden">
<InfoChip icon={Bolt}>
<div className="text-xs flex gap-0.5">
<span className="font-medium text-gray-12">
{formatCpuParts(deployment.cpuMillicores).value}
</span>
<span className="text-gray-11">
{formatCpuParts(deployment.cpuMillicores).unit}
</span>
</div>
</InfoChip>
<InfoChip icon={Grid}>
<div className="text-xs flex gap-0.5">
<span className="font-medium text-gray-12">
{formatMemoryParts(deployment.memoryMib).value}
</span>
<span className="text-gray-11">
{formatMemoryParts(deployment.memoryMib).unit}
</span>
</div>
</InfoChip>
</div>
<RegionFlags instances={deployment.instances} />
{projectLayout && (
<InfoTooltip asChild content="Show deployment details">
<Button
variant="ghost"
className="[&_svg]:size-3 size-3 rounded-sm"
size="icon"
onClick={() => projectLayout.setIsDetailsOpen(!projectLayout.isDetailsOpen)}
>
<LayoutRight iconSize="sm-regular" className="text-gray-10" />
</Button>
</InfoTooltip>
)}
</div>
}
statusBadge={<DeploymentStatusBadge status={deploymentStatus} />}
/>
</Section>
);
}
Loading