feat(webapp): add triggered via field to deployment details page (#2850)
Display the deployment trigger source (CLI, CI/CD, Dashboard, GitHub Integration) with appropriate icons on the deployment details page. The triggeredVia field was already in the database but not displayed. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -156,6 +156,7 @@ export class DeploymentPresenter {
|
||||
},
|
||||
},
|
||||
buildServerMetadata: true,
|
||||
triggeredVia: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -225,6 +226,7 @@ export class DeploymentPresenter {
|
||||
isBuilt: !!deployment.builtAt,
|
||||
type: deployment.type,
|
||||
git: gitMetadata,
|
||||
triggeredVia: deployment.triggeredVia,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
+109
-1
@@ -3,7 +3,16 @@ import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { useEffect, useState, useRef, useCallback } from "react";
|
||||
import { S2, S2Error } from "@s2-dev/streamstore";
|
||||
import { Clipboard, ClipboardCheck, ChevronDown, ChevronUp } from "lucide-react";
|
||||
import {
|
||||
Clipboard,
|
||||
ClipboardCheck,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
TerminalSquareIcon,
|
||||
LayoutDashboardIcon,
|
||||
GitBranchIcon,
|
||||
ServerIcon,
|
||||
} from "lucide-react";
|
||||
import { ExitIcon } from "~/assets/icons/ExitIcon";
|
||||
import { GitMetadata } from "~/components/GitMetadata";
|
||||
import { RuntimeIcon } from "~/components/RuntimeIcon";
|
||||
@@ -73,6 +82,90 @@ type LogEntry = {
|
||||
level: "info" | "error" | "warn" | "debug";
|
||||
};
|
||||
|
||||
function getTriggeredViaDisplay(triggeredVia: string | null | undefined): {
|
||||
icon: React.ReactNode;
|
||||
label: string;
|
||||
} | null {
|
||||
if (!triggeredVia) return null;
|
||||
|
||||
const iconClass = "size-4 text-text-dimmed";
|
||||
|
||||
switch (triggeredVia) {
|
||||
case "cli:manual":
|
||||
return {
|
||||
icon: <TerminalSquareIcon className={iconClass} />,
|
||||
label: "CLI (Manual)",
|
||||
};
|
||||
case "cli:github_actions":
|
||||
return {
|
||||
icon: <GitBranchIcon className={iconClass} />,
|
||||
label: "CLI (GitHub Actions)",
|
||||
};
|
||||
case "cli:gitlab_ci":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (GitLab CI)",
|
||||
};
|
||||
case "cli:circleci":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (CircleCI)",
|
||||
};
|
||||
case "cli:jenkins":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (Jenkins)",
|
||||
};
|
||||
case "cli:azure_pipelines":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (Azure Pipelines)",
|
||||
};
|
||||
case "cli:bitbucket_pipelines":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (Bitbucket Pipelines)",
|
||||
};
|
||||
case "cli:travis_ci":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (Travis CI)",
|
||||
};
|
||||
case "cli:buildkite":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (Buildkite)",
|
||||
};
|
||||
case "cli:ci_other":
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: "CLI (CI)",
|
||||
};
|
||||
case "git_integration:github":
|
||||
return {
|
||||
icon: <GitBranchIcon className={iconClass} />,
|
||||
label: "GitHub Integration",
|
||||
};
|
||||
case "dashboard":
|
||||
return {
|
||||
icon: <LayoutDashboardIcon className={iconClass} />,
|
||||
label: "Dashboard",
|
||||
};
|
||||
default:
|
||||
// Handle any unknown values gracefully
|
||||
if (triggeredVia.startsWith("cli:")) {
|
||||
return {
|
||||
icon: <TerminalSquareIcon className={iconClass} />,
|
||||
label: `CLI (${triggeredVia.replace("cli:", "")})`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
icon: <ServerIcon className={iconClass} />,
|
||||
label: triggeredVia,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
const { deployment, eventStream } = useTypedLoaderData<typeof loader>();
|
||||
const organization = useOrganization();
|
||||
@@ -408,6 +501,21 @@ export default function Page() {
|
||||
)}
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
<Property.Item>
|
||||
<Property.Label>Triggered via</Property.Label>
|
||||
<Property.Value>
|
||||
{(() => {
|
||||
const display = getTriggeredViaDisplay(deployment.triggeredVia);
|
||||
if (!display) return "–";
|
||||
return (
|
||||
<span className="flex items-center gap-1.5">
|
||||
{display.icon}
|
||||
{display.label}
|
||||
</span>
|
||||
);
|
||||
})()}
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
</Property.Table>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user