Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import {
} from "@ctrlplane/validators/conditions";
import { JobFilterType, JobStatus } from "@ctrlplane/validators/jobs";

import { useReleaseChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/channel/drawer/useReleaseChannelDrawer";
import { useReleaseChannel } from "~/app/[workspaceSlug]/(app)/_hooks/channel/useReleaseChannel";
import { useDeploymentVersionChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/channel/drawer/useDeploymentVersionChannelDrawer";
import { useDeploymentVersionChannel } from "~/app/[workspaceSlug]/(app)/_hooks/channel/useDeploymentVersionChannel";
import { api } from "~/trpc/react";
import { Cancelled, Failing, Loading, Passing, Waiting } from "./StatusIcons";

Expand Down Expand Up @@ -132,53 +132,64 @@ const WaitingOnActiveCheck: React.FC<EnvironmentNodeProps["data"]> = ({
);
};

const ReleaseChannelCheck: React.FC<EnvironmentNodeProps["data"]> = ({
const DeploymentVersionChannelCheck: React.FC<EnvironmentNodeProps["data"]> = ({
deploymentId,
environmentId,
releaseVersion,
}) => {
const { setReleaseChannelId } = useReleaseChannelDrawer();
const { isPassingReleaseChannel, releaseChannelId, loading } =
useReleaseChannel(deploymentId, environmentId, releaseVersion);
const { setDeploymentVersionChannelId } = useDeploymentVersionChannelDrawer();
const {
isPassingDeploymentVersionChannel,
deploymentVersionChannelId,
loading,
} = useDeploymentVersionChannel(deploymentId, environmentId, releaseVersion);

return (
<div className="flex items-center gap-2">
{loading && <Loading />}
{!loading && releaseChannelId == null && (
{!loading && deploymentVersionChannelId == null && (
<>
<Cancelled /> No release channel
</>
)}
{!loading && releaseChannelId != null && !isPassingReleaseChannel && (
<>
<Failing />
<span className="flex items-center gap-1">
Blocked by{" "}
<Button
variant="link"
onClick={() => setReleaseChannelId(releaseChannelId)}
className="h-fit px-0 py-0 text-inherit underline-offset-2"
>
release channel
</Button>
</span>
</>
)}
{!loading && releaseChannelId != null && isPassingReleaseChannel && (
<>
<Passing />
<span className="flex items-center gap-1">
Passing{" "}
<Button
variant="link"
onClick={() => setReleaseChannelId(releaseChannelId)}
className="h-fit px-0 py-0 text-inherit underline-offset-2"
>
release channel
</Button>
</span>
</>
)}
{!loading &&
deploymentVersionChannelId != null &&
!isPassingDeploymentVersionChannel && (
<>
<Failing />
<span className="flex items-center gap-1">
Blocked by{" "}
<Button
variant="link"
onClick={() =>
setDeploymentVersionChannelId(deploymentVersionChannelId)
}
className="h-fit px-0 py-0 text-inherit underline-offset-2"
>
release channel
</Button>
</span>
</>
)}
{!loading &&
deploymentVersionChannelId != null &&
isPassingDeploymentVersionChannel && (
<>
<Passing />
<span className="flex items-center gap-1">
Passing{" "}
<Button
variant="link"
onClick={() =>
setDeploymentVersionChannelId(deploymentVersionChannelId)
}
className="h-fit px-0 py-0 text-inherit underline-offset-2"
>
release channel
</Button>
</span>
</>
)}
</div>
);
};
Expand Down Expand Up @@ -265,7 +276,7 @@ export const EnvironmentNode: React.FC<EnvironmentNodeProps> = ({ data }) => (
<Separator className="!m-0 bg-neutral-800" />
<div className="px-2 pb-2">
<WaitingOnActiveCheck {...data} />
<ReleaseChannelCheck {...data} />
<DeploymentVersionChannelCheck {...data} />
<MinReleaseIntervalCheck {...data} />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { JobConditionDialog } from "~/app/[workspaceSlug]/(app)/_components/job/
import { useJobDrawer } from "~/app/[workspaceSlug]/(app)/_components/job/drawer/useJobDrawer";
import { JobDropdownMenu } from "~/app/[workspaceSlug]/(app)/_components/job/JobDropdownMenu";
import { JobTableStatusIcon } from "~/app/[workspaceSlug]/(app)/_components/job/JobTableStatusIcon";
import { useReleaseChannel } from "~/app/[workspaceSlug]/(app)/_hooks/channel/useReleaseChannel";
import { useDeploymentVersionChannel } from "~/app/[workspaceSlug]/(app)/_hooks/channel/useDeploymentVersionChannel";
import { useFilter } from "~/app/[workspaceSlug]/(app)/_hooks/useFilter";
import { Sidebars } from "~/app/[workspaceSlug]/sidebars";
import { api } from "~/trpc/react";
Expand Down Expand Up @@ -133,10 +133,16 @@ const CollapsibleTableRow: React.FC<CollapsibleTableRowProps> = ({
return newState;
});

const { isPassingReleaseChannel, loading: releaseChannelLoading } =
useReleaseChannel(deployment.id, environment.id, release.version);
const {
isPassingDeploymentVersionChannel,
loading: deploymentVersionChannelLoading,
} = useDeploymentVersionChannel(
deployment.id,
environment.id,
release.version,
);

const loading = approvalsQ.isLoading || releaseChannelLoading;
const loading = approvalsQ.isLoading || deploymentVersionChannelLoading;

if (allTriggers.length === 0) return null;

Expand Down Expand Up @@ -312,7 +318,9 @@ const CollapsibleTableRow: React.FC<CollapsibleTableRowProps> = ({
id: trigger.job.id,
status: trigger.job.status,
}}
isPassingReleaseChannel={isPassingReleaseChannel}
isPassingDeploymentVersionChannel={
isPassingDeploymentVersionChannel
}
>
<Button
variant="ghost"
Expand Down Expand Up @@ -417,8 +425,8 @@ const CollapsibleTableRow: React.FC<CollapsibleTableRowProps> = ({
id: trigger.job.id,
status: trigger.job.status,
}}
isPassingReleaseChannel={
isPassingReleaseChannel
isPassingDeploymentVersionChannel={
isPassingDeploymentVersionChannel
}
>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,15 @@ type DeploymentPageContentProps = {
deployment: Deployment;
environments: schema.Environment[];
directories: { path: string; environments: schema.Environment[] }[];
releaseChannel: schema.DeploymentVersionChannel | null;
deploymentVersionChannel: schema.DeploymentVersionChannel | null;
};

export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
workspace,
deployment,
environments,
directories,
releaseChannel,
deploymentVersionChannel,
}) => {
const { filter, setFilter } = useReleaseFilter();

Expand Down Expand Up @@ -211,7 +211,7 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
<ReleaseConditionDialog
condition={filter}
onChange={setFilter}
releaseChannels={deployment.releaseChannels}
deploymentVersionChannels={deployment.versionChannels}
>
<div className="flex items-center gap-2">
<Button
Expand All @@ -222,7 +222,7 @@ export const DeploymentPageContent: React.FC<DeploymentPageContentProps> = ({
<IconFilter className="h-4 w-4" />
</Button>

{filter != null && releaseChannel == null && (
{filter != null && deploymentVersionChannel == null && (
<ReleaseConditionBadge condition={filter} />
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { usePathname } from "next/navigation";
import { Button } from "@ctrlplane/ui/button";

import { CreateReleaseDialog } from "~/app/[workspaceSlug]/(app)/(deploy)/_components/release/CreateRelease";
import { CreateReleaseChannelDialog } from "../channels/CreateReleaseChannelDialog";
import { CreateDeploymentVersionChannelDialog } from "../channels/CreateDeploymentVersionChannelDialog";
import { CreateVariableDialog } from "../variables/CreateVariableDialog";

export const DeploymentCTA: React.FC<{
Expand All @@ -27,11 +27,11 @@ export const DeploymentCTA: React.FC<{

if (tab === "channels")
return (
<CreateReleaseChannelDialog deploymentId={deploymentId}>
<CreateDeploymentVersionChannelDialog deploymentId={deploymentId}>
<Button variant="outline" className="flex items-center gap-2" size="sm">
New Channel
</Button>
</CreateReleaseChannelDialog>
</CreateDeploymentVersionChannelDialog>
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { JobStatus } from "@ctrlplane/validators/jobs";
import { ReleaseStatus } from "@ctrlplane/validators/releases";

import { useReleaseChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/channel/drawer/useReleaseChannelDrawer";
import { useDeploymentVersionChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/channel/drawer/useDeploymentVersionChannelDrawer";
import { ApprovalDialog } from "~/app/[workspaceSlug]/(app)/(deploy)/_components/release/ApprovalDialog";
import { ReleaseDropdownMenu } from "~/app/[workspaceSlug]/(app)/(deploy)/_components/release/ReleaseDropdownMenu";
import { api } from "~/trpc/react";
Expand Down Expand Up @@ -106,7 +106,7 @@ const ReleaseEnvironmentCell: React.FC<ReleaseEnvironmentCellProps> = ({
{ refetchInterval: 2_000 },
);

const { setReleaseChannelId } = useReleaseChannelDrawer();
const { setDeploymentVersionChannelId } = useDeploymentVersionChannelDrawer();

const isLoading =
isStatusesLoading ||
Expand Down Expand Up @@ -135,16 +135,18 @@ const ReleaseEnvironmentCell: React.FC<ReleaseEnvironmentCellProps> = ({
const isAlreadyDeployed = statuses != null && statuses.length > 0;

const hasJobAgent = deployment.jobAgentId != null;
const isBlockedByReleaseChannel = blockedEnv != null;
const isBlockedByDeploymentVersionChannel = blockedEnv != null;

const isPendingApproval = approval?.status === "pending";

const showBlockedByReleaseChannel =
isBlockedByReleaseChannel &&
const showBlockedByDeploymentVersionChannel =
isBlockedByDeploymentVersionChannel &&
!statuses?.some((s) => s.job.status === JobStatus.InProgress);

const showRelease =
isAlreadyDeployed && !showBlockedByReleaseChannel && !isPendingApproval;
isAlreadyDeployed &&
!showBlockedByDeploymentVersionChannel &&
!isPendingApproval;

if (showRelease)
return (
Expand Down Expand Up @@ -175,15 +177,17 @@ const ReleaseEnvironmentCell: React.FC<ReleaseEnvironmentCellProps> = ({
<div className="text-center text-xs text-red-500">Release failed</div>
);

if (showBlockedByReleaseChannel)
if (showBlockedByDeploymentVersionChannel)
return (
<div className="text-center text-xs text-muted-foreground/70">
Blocked by{" "}
<Button
variant="link"
size="sm"
onClick={() =>
setReleaseChannelId(blockedEnv.releaseChannelId ?? null)
setDeploymentVersionChannelId(
blockedEnv.deploymentVersionChannelId ?? null,
)
}
className="px-0 text-muted-foreground/70"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { ReleaseConditionDialog } from "~/app/[workspaceSlug]/(app)/_components/
import { urls } from "~/app/urls";
import { api } from "~/trpc/react";

type CreateReleaseChannelDialogProps = {
type CreateDeploymentVersionChannelDialogProps = {
deploymentId: string;
children: React.ReactNode;
};
Expand All @@ -52,13 +52,13 @@ const getFinalFilter = (filter?: ReleaseCondition) =>
const schema = z.object({
name: z.string().min(1).max(50),
description: z.string().max(1000).optional(),
releaseFilter: releaseCondition
versionSelector: releaseCondition
.optional()
.refine((cond) => cond == null || isValidReleaseCondition(cond)),
});

export const CreateReleaseChannelDialog: React.FC<
CreateReleaseChannelDialogProps
export const CreateDeploymentVersionChannelDialog: React.FC<
CreateDeploymentVersionChannelDialogProps
> = ({ deploymentId, children }) => {
const [open, setOpen] = useState(false);
const { workspaceSlug, systemSlug, deploymentSlug } = useParams<{
Expand All @@ -67,23 +67,23 @@ export const CreateReleaseChannelDialog: React.FC<
deploymentSlug: string;
}>();

const createReleaseChannel =
api.deployment.releaseChannel.create.useMutation();
const createDeploymentVersionChannel =
api.deployment.version.channel.create.useMutation();
const router = useRouter();

const form = useForm({ schema });
const onSubmit = form.handleSubmit((data) => {
const filter = getFinalFilter(data.releaseFilter);
createReleaseChannel
.mutateAsync({ ...data, deploymentId, releaseFilter: filter })
const filter = getFinalFilter(data.versionSelector);
createDeploymentVersionChannel
.mutateAsync({ ...data, deploymentId, versionSelector: filter })
.then(() => form.reset(data))
.then(() => router.refresh())
.then(() => setOpen(false))
.catch((error) => toast.error(error.message));
});

const { releaseFilter } = form.watch();
const filter = getFinalFilter(releaseFilter);
const { versionSelector } = form.watch();
const filter = getFinalFilter(versionSelector);

const filterHash =
filter != null
Expand Down Expand Up @@ -143,7 +143,7 @@ export const CreateReleaseChannelDialog: React.FC<

<FormField
control={form.control}
name="releaseFilter"
name="versionSelector"
render={({ field: { value, onChange } }) => (
<FormItem className="space-y-2">
<FormLabel>
Expand Down Expand Up @@ -186,7 +186,10 @@ export const CreateReleaseChannelDialog: React.FC<
/>

<DialogFooter>
<Button type="submit" disabled={createReleaseChannel.isPending}>
<Button
type="submit"
disabled={createDeploymentVersionChannel.isPending}
>
Create
</Button>
</DialogFooter>
Expand Down
Loading
Loading