From aa57de8ff12b74146921e7f76314134e5c6c8a46 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 22 Dec 2024 21:18:39 -0500 Subject: [PATCH 1/7] init --- packages/db/src/schema/deployment.ts | 14 +++++++++++++- packages/job-dispatch/src/release-job-trigger.ts | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/db/src/schema/deployment.ts b/packages/db/src/schema/deployment.ts index 52dfefbc..8ea70cb8 100644 --- a/packages/db/src/schema/deployment.ts +++ b/packages/db/src/schema/deployment.ts @@ -1,5 +1,6 @@ +import type { ResourceCondition } from "@ctrlplane/validators/resources"; import type { InferSelectModel } from "drizzle-orm"; -import { relations } from "drizzle-orm"; +import { relations, sql } from "drizzle-orm"; import { integer, jsonb, @@ -11,6 +12,11 @@ import { import { createInsertSchema } from "drizzle-zod"; import { z } from "zod"; +import { + isValidResourceCondition, + resourceCondition, +} from "@ctrlplane/validators/resources"; + import { jobAgent } from "./job-agent.js"; import { system } from "./system.js"; @@ -39,6 +45,9 @@ export const deploymentSchema = z.object({ .refine((val) => val >= 0, { message: "Retry count must be a non-negative number.", }), + resourceFilter: resourceCondition + .optional() + .refine((filter) => filter == null || isValidResourceCondition(filter)), }); export const deployment = pgTable( @@ -59,6 +68,9 @@ export const deployment = pgTable( .$type>() .notNull(), retryCount: integer("retry_count").notNull().default(0), + resourceFilter: jsonb("resource_filter") + .$type() + .default(sql`NULL`), }, (t) => ({ uniq: uniqueIndex().on(t.systemId, t.slug) }), ); diff --git a/packages/job-dispatch/src/release-job-trigger.ts b/packages/job-dispatch/src/release-job-trigger.ts index 42b2cfd2..f7ecaef7 100644 --- a/packages/job-dispatch/src/release-job-trigger.ts +++ b/packages/job-dispatch/src/release-job-trigger.ts @@ -136,6 +136,7 @@ class ReleaseJobTriggerBuilder { return Promise.all( releases.flatMap(async (release) => { const { resourceFilter } = release.environment; + const { resourceFilter: deploymentResourceFilter } = release.deployment; const { workspaceId } = release.system; const resources = await this.tx .select() @@ -143,6 +144,7 @@ class ReleaseJobTriggerBuilder { .where( and( resourceMatchesMetadata(this.tx, resourceFilter), + resourceMatchesMetadata(this.tx, deploymentResourceFilter), eq(resource.workspaceId, workspaceId), isNull(resource.lockedAt), isNull(resource.deletedAt), From f4d3919da09d333ac8640fd13b372d44a4d3990d Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 22 Dec 2024 22:27:44 -0500 Subject: [PATCH 2/7] update hook --- .../job-dispatch/src/deployment-update.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/packages/job-dispatch/src/deployment-update.ts b/packages/job-dispatch/src/deployment-update.ts index 10eb6331..7aec14bf 100644 --- a/packages/job-dispatch/src/deployment-update.ts +++ b/packages/job-dispatch/src/deployment-update.ts @@ -1,4 +1,6 @@ +import type { HookEvent } from "@ctrlplane/validators/events"; import type { ResourceCondition } from "@ctrlplane/validators/resources"; +import _ from "lodash"; import { isPresent } from "ts-is-present"; import { and, eq, inArray, isNotNull, takeFirst } from "@ctrlplane/db"; @@ -97,6 +99,74 @@ export const handleDeploymentSystemChanged = async ( ); }; +const handleDeploymentFilterChanged = async ( + deployment: SCHEMA.Deployment, + prevFilter: ResourceCondition | null, + userId?: string, +) => { + const environments = await db.query.environment.findMany({ + where: eq(SCHEMA.environment.systemId, deployment.systemId), + }); + + const isInSystem: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.Or, + conditions: environments.map((e) => e.resourceFilter).filter(isPresent), + }; + + const oldResourcesFilter: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.And, + conditions: [prevFilter, isInSystem].filter(isPresent), + }; + + const newResourcesFilter: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.And, + conditions: [deployment.resourceFilter, isInSystem].filter(isPresent), + }; + + const oldResources = await db.query.resource.findMany({ + where: SCHEMA.resourceMatchesMetadata(db, oldResourcesFilter), + }); + + const newResources = await db.query.resource.findMany({ + where: SCHEMA.resourceMatchesMetadata(db, newResourcesFilter), + }); + + const resourcesToRemove = oldResources.filter( + (r) => !newResources.some((nr) => nr.id === r.id), + ); + const resourcesToAdd = newResources.filter( + (r) => !oldResources.some((nr) => nr.id === r.id), + ); + + const events: HookEvent[] = resourcesToRemove.map((resource) => ({ + action: "deployment.resource.removed", + payload: { deployment, resource }, + })); + + await Promise.allSettled(events.map(handleEvent)); + + const createTriggers = + userId != null + ? createReleaseJobTriggers(db, "new_release").causedById(userId) + : createReleaseJobTriggers(db, "new_release"); + + await createTriggers + .deployments([deployment.id]) + .resources(resourcesToAdd.map((r) => r.id)) + .filter(isPassingReleaseStringCheckPolicy) + .then(createJobApprovals) + .insert() + .then((triggers) => + dispatchReleaseJobTriggers(db) + .releaseTriggers(triggers) + .filter(isPassingAllPolicies) + .dispatch(), + ); +}; + export const updateDeployment = async ( deploymentId: string, data: SCHEMA.UpdateDeployment, @@ -122,6 +192,15 @@ export const updateDeployment = async ( userId, ); + if ( + !_.isEqual(prevDeployment.resourceFilter, updatedDeployment.resourceFilter) + ) + await handleDeploymentFilterChanged( + updatedDeployment, + prevDeployment.resourceFilter, + userId, + ); + const sys = await db .select() .from(SCHEMA.system) From 16ce2096f0ff74ad8c18216f393b9b65a0dbdf74 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 23 Dec 2024 12:43:47 -0500 Subject: [PATCH 3/7] more changes --- .../_components/environment-drawer/Filter.tsx | 55 +- .../resource-condition/ResourceList.tsx | 64 + .../DeploymentResourcesDialog.tsx | 120 + .../EditDeploymentSection.tsx | 61 +- .../deployments/[deploymentSlug]/page.tsx | 6 +- .../drizzle/0049_condemned_franklin_storm.sql | 1 + packages/db/drizzle/meta/0049_snapshot.json | 4778 +++++++++++++++++ packages/db/drizzle/meta/_journal.json | 9 +- 8 files changed, 5038 insertions(+), 56 deletions(-) create mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceList.tsx create mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx create mode 100644 packages/db/drizzle/0049_condemned_franklin_storm.sql create mode 100644 packages/db/drizzle/meta/0049_snapshot.json diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/environment-drawer/Filter.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/environment-drawer/Filter.tsx index 99ab863a..8aa5ab0a 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/environment-drawer/Filter.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/environment-drawer/Filter.tsx @@ -1,14 +1,7 @@ import type * as SCHEMA from "@ctrlplane/db/schema"; import type { ResourceCondition } from "@ctrlplane/validators/resources"; import { useState } from "react"; -import Link from "next/link"; -import { useParams } from "next/navigation"; -import { - IconExternalLink, - IconLoader2, - IconSelector, -} from "@tabler/icons-react"; -import * as LZString from "lz-string"; +import { IconLoader2, IconSelector } from "@tabler/icons-react"; import { z } from "zod"; import { Button } from "@ctrlplane/ui/button"; @@ -28,7 +21,6 @@ import { FormMessage, useForm, } from "@ctrlplane/ui/form"; -import { Label } from "@ctrlplane/ui/label"; import { Popover, PopoverContent, PopoverTrigger } from "@ctrlplane/ui/popover"; import { ComparisonOperator, @@ -42,7 +34,7 @@ import { import { api } from "~/trpc/react"; import { ResourceConditionRender } from "../resource-condition/ResourceConditionRender"; -import { ResourceIcon } from "../ResourceIcon"; +import { ResourceList } from "../resource-condition/ResourceList"; const ResourceViewsCombobox: React.FC<{ workspaceId: string; @@ -120,7 +112,6 @@ export const EditFilterForm: React.FC<{ environment: SCHEMA.Environment; workspaceId: string; }> = ({ environment, workspaceId }) => { - const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); const update = api.environment.update.useMutation(); const form = useForm({ schema: filterForm, @@ -208,43 +199,11 @@ export const EditFilterForm: React.FC<{ {resourceFilter != null && resources.data != null && resources.data.total > 0 && ( -
- -
- {resources.data.items.map((resource) => ( -
- -
- - {resource.name} - - - {resource.version} - -
-
- ))} -
- - -
+ )} diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceList.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceList.tsx new file mode 100644 index 00000000..277936e7 --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceList.tsx @@ -0,0 +1,64 @@ +import type { RouterOutputs } from "@ctrlplane/api"; +import type { ResourceCondition } from "@ctrlplane/validators/resources"; +import Link from "next/link"; +import { useParams } from "next/navigation"; +import { IconExternalLink } from "@tabler/icons-react"; +import * as LZString from "lz-string"; + +import { Button } from "@ctrlplane/ui/button"; +import { Label } from "@ctrlplane/ui/label"; + +import { ResourceIcon } from "../ResourceIcon"; + +type Resource = + RouterOutputs["resource"]["byWorkspaceId"]["list"]["items"][number]; + +type ResourceListProps = { + resources: Resource[]; + count: number; + filter: ResourceCondition; +}; + +export const ResourceList: React.FC = ({ + resources, + count, + filter, +}) => { + const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); + + return ( +
+ +
+ {resources.map((resource) => ( +
+ +
+ + {resource.name} + + + {resource.version} + +
+
+ ))} +
+ +
+ ); +}; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx new file mode 100644 index 00000000..9c08272c --- /dev/null +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx @@ -0,0 +1,120 @@ +import type { ResourceCondition } from "@ctrlplane/validators/resources"; +import { useState } from "react"; +import { IconFilter } from "@tabler/icons-react"; +import { isPresent } from "ts-is-present"; + +import { Button } from "@ctrlplane/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@ctrlplane/ui/dialog"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@ctrlplane/ui/select"; +import { + ComparisonOperator, + FilterType, +} from "@ctrlplane/validators/conditions"; +import { isValidResourceCondition } from "@ctrlplane/validators/resources"; + +import { ResourceConditionRender } from "~/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceConditionRender"; +import { ResourceList } from "~/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceList"; +import { api } from "~/trpc/react"; + +type Environment = { + id: string; + name: string; + resourceFilter: ResourceCondition; +}; +type DeploymentResourcesDialogProps = { + environments: Environment[]; + resourceFilter: ResourceCondition; + workspaceId: string; +}; + +export const DeploymentResourcesDialog: React.FC< + DeploymentResourcesDialogProps +> = ({ environments, resourceFilter, workspaceId }) => { + const [selectedEnvironment, setSelectedEnvironment] = + useState(environments[0] ?? null); + + const filter: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.And, + conditions: [selectedEnvironment?.resourceFilter, resourceFilter].filter( + isPresent, + ), + }; + + const { data, isLoading } = api.resource.byWorkspaceId.list.useQuery( + { workspaceId, filter, limit: 5 }, + { enabled: selectedEnvironment != null }, + ); + + const resources = data?.items ?? []; + const count = data?.total ?? 0; + + if (environments.length === 0) return null; + return ( + + + + + + + View Resources + + Select an environment to view the resources based on the combined + environment and deployment filter. + + + + + + {selectedEnvironment != null && ( + <> + {}} /> + {!isLoading && ( + + )} + + )} + + + ); +}; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx index d6fc133e..c43e14ec 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx @@ -1,5 +1,6 @@ "use client"; +import type { RouterOutputs } from "@ctrlplane/api"; import { useParams, useRouter } from "next/navigation"; import { z } from "zod"; @@ -24,23 +25,43 @@ import { SelectValue, } from "@ctrlplane/ui/select"; import { Textarea } from "@ctrlplane/ui/textarea"; +import { + defaultCondition, + isEmptyCondition, +} from "@ctrlplane/validators/resources"; +import { ResourceConditionRender } from "~/app/[workspaceSlug]/(app)/_components/resource-condition/ResourceConditionRender"; import { api } from "~/trpc/react"; +import { DeploymentResourcesDialog } from "./DeploymentResourcesDialog"; const deploymentForm = z.object(schema.deploymentSchema.shape); +type System = RouterOutputs["system"]["list"]["items"][number]; + type EditDeploymentSectionProps = { deployment: schema.Deployment; - systems: schema.System[]; + systems: System[]; + workspaceId: string; }; export const EditDeploymentSection: React.FC = ({ deployment, systems, + workspaceId, }) => { + const system = systems.find((s) => s.id === deployment.systemId); + + const envsWithFilter = + system?.environments + .filter((e) => e.resourceFilter != null) + .map((e) => ({ ...e, resourceFilter: e.resourceFilter! })) ?? []; + const form = useForm({ schema: deploymentForm, - defaultValues: { ...deployment }, + defaultValues: { + ...deployment, + resourceFilter: deployment.resourceFilter ?? undefined, + }, mode: "onSubmit", }); const { handleSubmit, setError } = form; @@ -49,8 +70,13 @@ export const EditDeploymentSection: React.FC = ({ const router = useRouter(); const updateDeployment = api.deployment.update.useMutation(); const onSubmit = handleSubmit((data) => { + const filter = + data.resourceFilter == null || isEmptyCondition(data.resourceFilter) + ? undefined + : data.resourceFilter; + const updates = { ...data, resourceFilter: filter }; updateDeployment - .mutateAsync({ id: deployment.id, data }) + .mutateAsync({ id: deployment.id, data: updates }) .then((updatedDeployment) => { if ( data.slug !== deployment.slug || @@ -61,11 +87,11 @@ export const EditDeploymentSection: React.FC = ({ ); router.refresh(); }) - .catch(() => { + .catch(() => setError("root", { message: "Deployment with this slug already exists", - }); - }); + }), + ); }); return (
@@ -172,6 +198,29 @@ export const EditDeploymentSection: React.FC = ({ )} /> + ( + + Resource Filter + + + + {envsWithFilter.length > 0 && value != null && ( + + )} + + + )} + /> diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/page.tsx index 7f9c4a83..16ca8b49 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/page.tsx @@ -164,7 +164,11 @@ export default async function DeploymentPage({
- + Date: Mon, 23 Dec 2024 13:16:06 -0500 Subject: [PATCH 4/7] more changes --- .../deployments/ReleaseEnvironmentCell.tsx | 36 +++++++++- .../deployments/TableDeployments.tsx | 22 +++++- .../releases/DeploymentPageContent.tsx | 71 ++++++++++++++++--- packages/api/src/router/environment.ts | 33 ++------- 4 files changed, 120 insertions(+), 42 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/ReleaseEnvironmentCell.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/ReleaseEnvironmentCell.tsx index b715b5a5..58eac65c 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/ReleaseEnvironmentCell.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/ReleaseEnvironmentCell.tsx @@ -1,10 +1,17 @@ "use client"; import type { RouterOutputs } from "@ctrlplane/api"; +import type * as SCHEMA from "@ctrlplane/db/schema"; +import type { ResourceCondition } from "@ctrlplane/validators/resources"; import { useParams } from "next/navigation"; import { useInView } from "react-intersection-observer"; +import { isPresent } from "ts-is-present"; import { Button } from "@ctrlplane/ui/button"; +import { + ComparisonOperator, + FilterType, +} from "@ctrlplane/validators/conditions"; import { useReleaseChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/release-channel-drawer/useReleaseChannelDrawer"; import { api } from "~/trpc/react"; @@ -16,7 +23,7 @@ type BlockedEnv = RouterOutputs["release"]["blocked"][number]; type ReleaseEnvironmentCellProps = { environment: Environment; - deployment: { slug: string; jobAgentId: string | null }; + deployment: SCHEMA.Deployment; release: { id: string; version: string; createdAt: Date }; blockedEnv?: BlockedEnv; }; @@ -32,18 +39,41 @@ const ReleaseEnvironmentCell: React.FC = ({ systemSlug: string; }>(); - const { data: statuses, isLoading } = + const { data: workspace, isLoading: isWorkspaceLoading } = + api.workspace.bySlug.useQuery(workspaceSlug); + const workspaceId = workspace?.id ?? ""; + + const { data: statuses, isLoading: isStatusesLoading } = api.release.status.byEnvironmentId.useQuery( { releaseId: release.id, environmentId: environment.id }, { refetchInterval: 2_000 }, ); + const { resourceFilter: envResourceFilter } = environment; + const { resourceFilter: deploymentResourceFilter } = deployment; + + const resourceFilter: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.And, + conditions: [envResourceFilter, deploymentResourceFilter].filter(isPresent), + }; + + const { data: resourcesResult, isLoading: isResourcesLoading } = + api.resource.byWorkspaceId.list.useQuery( + { workspaceId, filter: resourceFilter, limit: 0 }, + { enabled: workspaceId !== "" && envResourceFilter != null }, + ); + + const total = resourcesResult?.total ?? 0; + const { setReleaseChannelId } = useReleaseChannelDrawer(); + const isLoading = + isWorkspaceLoading || isStatusesLoading || isResourcesLoading; if (isLoading) return

Loading...

; - const hasResources = environment.resources.length > 0; + const hasResources = total > 0; const isAlreadyDeployed = statuses != null && statuses.length > 0; const hasJobAgent = deployment.jobAgentId != null; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx index 761d4683..52bd84be 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx @@ -3,12 +3,13 @@ import type { RouterOutputs } from "@ctrlplane/api"; import type { Deployment, Workspace } from "@ctrlplane/db/schema"; import Link from "next/link"; -import { IconCircleFilled } from "@tabler/icons-react"; +import { IconCircleFilled, IconLoader2 } from "@tabler/icons-react"; import { cn } from "@ctrlplane/ui"; import { Badge } from "@ctrlplane/ui/badge"; import { DeploymentOptionsDropdown } from "~/app/[workspaceSlug]/(app)/_components/DeploymentOptionsDropdown"; +import { api } from "~/trpc/react"; import { LazyReleaseEnvironmentCell } from "./ReleaseEnvironmentCell"; type Environment = RouterOutputs["environment"]["bySystemId"][number]; @@ -34,6 +35,20 @@ const EnvIcon: React.FC<{ workspaceSlug: string; systemSlug: string; }> = ({ environment: env, isFirst, isLast, workspaceSlug, systemSlug }) => { + const { data: workspace, isLoading: isWorkspaceLoading } = + api.workspace.bySlug.useQuery(workspaceSlug); + const workspaceId = workspace?.id ?? ""; + + const filter = env.resourceFilter ?? undefined; + const { data: resourcesResult, isLoading: isResourcesLoading } = + api.resource.byWorkspaceId.list.useQuery( + { workspaceId, filter, limit: 0 }, + { enabled: workspaceId !== "" && filter != null }, + ); + const total = resourcesResult?.total ?? 0; + + const isLoading = isWorkspaceLoading || isResourcesLoading; + const envUrl = `/${workspaceSlug}/systems/${systemSlug}/deployments?environment_id=${env.id}`; return ( - {env.resources.length} + {isLoading && ( + + )} + {!isLoading && total}
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx index 68e8f1ae..65d7a0d3 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx @@ -2,16 +2,19 @@ import type { RouterOutputs } from "@ctrlplane/api"; import type * as schema from "@ctrlplane/db/schema"; +import type { ResourceCondition } from "@ctrlplane/validators/resources"; import { useState } from "react"; import { useParams, useRouter } from "next/navigation"; import { IconFilter, IconGraph, IconHistory, + IconLoader2, IconSettings, } from "@tabler/icons-react"; import { formatDistanceToNowStrict } from "date-fns"; import _ from "lodash"; +import { isPresent } from "ts-is-present"; import { cn } from "@ctrlplane/ui"; import { Badge } from "@ctrlplane/ui/badge"; @@ -27,6 +30,10 @@ import { TableHeader, TableRow, } from "@ctrlplane/ui/table"; +import { + ComparisonOperator, + FilterType, +} from "@ctrlplane/validators/conditions"; import { useReleaseChannelDrawer } from "~/app/[workspaceSlug]/(app)/_components/release-channel-drawer/useReleaseChannelDrawer"; import { ReleaseConditionBadge } from "~/app/[workspaceSlug]/(app)/_components/release-condition/ReleaseConditionBadge"; @@ -40,6 +47,54 @@ import { ReleaseDistributionGraphPopover } from "./ReleaseDistributionPopover"; type Environment = RouterOutputs["environment"]["bySystemId"][number]; type Deployment = NonNullable; +type EnvHeaderProps = { + environment: Environment; + deployment: Deployment; +}; + +const EnvHeader: React.FC = ({ environment, deployment }) => { + const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); + const { data: workspace, isLoading: isWorkspaceLoading } = + api.workspace.bySlug.useQuery(workspaceSlug); + const workspaceId = workspace?.id ?? ""; + + const { resourceFilter: envResourceFilter } = environment; + const { resourceFilter: deploymentResourceFilter } = deployment; + + const filter: ResourceCondition = { + type: FilterType.Comparison, + operator: ComparisonOperator.And, + conditions: [envResourceFilter, deploymentResourceFilter].filter(isPresent), + }; + + const { data: resourcesResult, isLoading: isResourcesLoading } = + api.resource.byWorkspaceId.list.useQuery( + { workspaceId, filter, limit: 0 }, + { enabled: workspaceId !== "" && envResourceFilter != null }, + ); + + const total = resourcesResult?.total ?? 0; + + const isLoading = isWorkspaceLoading || isResourcesLoading; + + return ( + +
+ {environment.name} + + {isLoading && ( + + )} + {!isLoading && total} + +
+
+ ); +}; + type DeploymentPageContentProps = { deployment: Deployment; environments: Environment[]; @@ -189,17 +244,11 @@ export const DeploymentPageContent: React.FC = ({ {selectedEnvironments.map((env) => ( - -
- {env.name} - - {env.resources.length} - -
-
+ ))} diff --git a/packages/api/src/router/environment.ts b/packages/api/src/router/environment.ts index 0072f162..61f113d7 100644 --- a/packages/api/src/router/environment.ts +++ b/packages/api/src/router/environment.ts @@ -153,36 +153,17 @@ export const environmentRouter = createTRPCRouter({ canUser.perform(Permission.SystemGet).on({ type: "system", id: input }), }) .input(z.string().uuid()) - .query(async ({ ctx, input }) => { - const envs = await ctx.db + .query(({ ctx, input }) => + ctx.db .select() .from(environment) .innerJoin(system, eq(system.id, environment.systemId)) .orderBy(environment.name) - .where(eq(environment.systemId, input)); - - return await Promise.all( - envs.map(async (e) => ({ - ...e.environment, - system: e.system, - resources: - e.environment.resourceFilter != null - ? await ctx.db - .select() - .from(resource) - .where( - and( - isNull(resource.deletedAt), - resourceMatchesMetadata( - ctx.db, - e.environment.resourceFilter, - ), - ), - ) - : [], - })), - ); - }), + .where(eq(environment.systemId, input)) + .then((envs) => + envs.map((e) => ({ ...e.environment, system: e.system })), + ), + ), byWorkspaceId: protectedProcedure .meta({ From ce9b9d8f3c060eceafd9378456f27d75fe3619ba Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 23 Dec 2024 13:28:10 -0500 Subject: [PATCH 5/7] code cleanup --- .../[deploymentSlug]/EditDeploymentSection.tsx | 17 ++++++----------- .../releases/DeploymentPageContent.tsx | 5 +---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx index c43e14ec..fdb2f26a 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/EditDeploymentSection.tsx @@ -4,7 +4,7 @@ import type { RouterOutputs } from "@ctrlplane/api"; import { useParams, useRouter } from "next/navigation"; import { z } from "zod"; -import * as schema from "@ctrlplane/db/schema"; +import * as SCHEMA from "@ctrlplane/db/schema"; import { Button } from "@ctrlplane/ui/button"; import { Form, @@ -34,12 +34,12 @@ import { ResourceConditionRender } from "~/app/[workspaceSlug]/(app)/_components import { api } from "~/trpc/react"; import { DeploymentResourcesDialog } from "./DeploymentResourcesDialog"; -const deploymentForm = z.object(schema.deploymentSchema.shape); +const schema = z.object(SCHEMA.deploymentSchema.shape); type System = RouterOutputs["system"]["list"]["items"][number]; type EditDeploymentSectionProps = { - deployment: schema.Deployment; + deployment: SCHEMA.Deployment; systems: System[]; workspaceId: string; }; @@ -56,14 +56,9 @@ export const EditDeploymentSection: React.FC = ({ .filter((e) => e.resourceFilter != null) .map((e) => ({ ...e, resourceFilter: e.resourceFilter! })) ?? []; - const form = useForm({ - schema: deploymentForm, - defaultValues: { - ...deployment, - resourceFilter: deployment.resourceFilter ?? undefined, - }, - mode: "onSubmit", - }); + const resourceFilter = deployment.resourceFilter ?? undefined; + const defaultValues = { ...deployment, resourceFilter }; + const form = useForm({ schema, defaultValues, mode: "onSubmit" }); const { handleSubmit, setError } = form; const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx index 65d7a0d3..0f0f79d5 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/DeploymentPageContent.tsx @@ -47,10 +47,7 @@ import { ReleaseDistributionGraphPopover } from "./ReleaseDistributionPopover"; type Environment = RouterOutputs["environment"]["bySystemId"][number]; type Deployment = NonNullable; -type EnvHeaderProps = { - environment: Environment; - deployment: Deployment; -}; +type EnvHeaderProps = { environment: Environment; deployment: Deployment }; const EnvHeader: React.FC = ({ environment, deployment }) => { const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); From c826e6e2e41c711efeca76c29658d3bcc2ec351c Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 23 Dec 2024 13:52:20 -0500 Subject: [PATCH 6/7] ability to clear filter --- .../DeploymentResourcesDialog.tsx | 6 ++-- .../EditDeploymentSection.tsx | 29 ++++++++++++++----- packages/db/src/schema/deployment.ts | 1 + 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx index 9c08272c..f22aae46 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/DeploymentResourcesDialog.tsx @@ -53,10 +53,11 @@ export const DeploymentResourcesDialog: React.FC< isPresent, ), }; + const isFilterValid = isValidResourceCondition(filter); const { data, isLoading } = api.resource.byWorkspaceId.list.useQuery( { workspaceId, filter, limit: 5 }, - { enabled: selectedEnvironment != null }, + { enabled: selectedEnvironment != null && isFilterValid }, ); const resources = data?.items ?? []; @@ -65,10 +66,11 @@ export const DeploymentResourcesDialog: React.FC< if (environments.length === 0) return null; return ( - + + + {envsWithFilter.length > 0 && value != null && ( + + )} + )} diff --git a/packages/db/src/schema/deployment.ts b/packages/db/src/schema/deployment.ts index 8ea70cb8..b9c1b537 100644 --- a/packages/db/src/schema/deployment.ts +++ b/packages/db/src/schema/deployment.ts @@ -46,6 +46,7 @@ export const deploymentSchema = z.object({ message: "Retry count must be a non-negative number.", }), resourceFilter: resourceCondition + .nullable() .optional() .refine((filter) => filter == null || isValidResourceCondition(filter)), }); From 4a797d52a113a61ad56e3eeec74becbe98c2a81d Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 23 Dec 2024 14:01:17 -0500 Subject: [PATCH 7/7] format --- packages/db/drizzle/meta/0049_snapshot.json | 726 +++++--------------- packages/db/drizzle/meta/_journal.json | 2 +- 2 files changed, 180 insertions(+), 548 deletions(-) diff --git a/packages/db/drizzle/meta/0049_snapshot.json b/packages/db/drizzle/meta/0049_snapshot.json index 1e8f542a..79190531 100644 --- a/packages/db/drizzle/meta/0049_snapshot.json +++ b/packages/db/drizzle/meta/0049_snapshot.json @@ -81,12 +81,8 @@ "name": "account_userId_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["userId"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -94,10 +90,7 @@ "compositePrimaryKeys": { "account_provider_providerAccountId_pk": { "name": "account_provider_providerAccountId_pk", - "columns": [ - "provider", - "providerAccountId" - ] + "columns": ["provider", "providerAccountId"] } }, "uniqueConstraints": {} @@ -131,12 +124,8 @@ "name": "session_userId_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["userId"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -200,12 +189,8 @@ "name": "user_active_workspace_id_workspace_id_fk", "tableFrom": "user", "tableTo": "workspace", - "columnsFrom": [ - "active_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["active_workspace_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -289,12 +274,8 @@ "name": "user_api_key_user_id_user_id_fk", "tableFrom": "user_api_key", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -351,12 +332,8 @@ "name": "dashboard_workspace_id_workspace_id_fk", "tableFrom": "dashboard", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -425,12 +402,8 @@ "name": "dashboard_widget_dashboard_id_dashboard_id_fk", "tableFrom": "dashboard_widget", "tableTo": "dashboard", - "columnsFrom": [ - "dashboard_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["dashboard_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -510,12 +483,8 @@ "name": "deployment_variable_deployment_id_deployment_id_fk", "tableFrom": "deployment_variable", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -523,12 +492,8 @@ "name": "deployment_variable_default_value_id_deployment_variable_value_id_fk", "tableFrom": "deployment_variable", "tableTo": "deployment_variable_value", - "columnsFrom": [ - "default_value_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["default_value_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -588,12 +553,8 @@ "name": "deployment_variable_set_deployment_id_deployment_id_fk", "tableFrom": "deployment_variable_set", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -601,12 +562,8 @@ "name": "deployment_variable_set_variable_set_id_variable_set_id_fk", "tableFrom": "deployment_variable_set", "tableTo": "variable_set", - "columnsFrom": [ - "variable_set_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -673,12 +630,8 @@ "name": "deployment_variable_value_variable_id_deployment_variable_id_fk", "tableFrom": "deployment_variable_value", "tableTo": "deployment_variable", - "columnsFrom": [ - "variable_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["variable_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "restrict" } @@ -777,12 +730,8 @@ "name": "deployment_system_id_system_id_fk", "tableFrom": "deployment", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -790,12 +739,8 @@ "name": "deployment_job_agent_id_job_agent_id_fk", "tableFrom": "deployment", "tableTo": "job_agent", - "columnsFrom": [ - "job_agent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -854,12 +799,8 @@ "name": "deployment_meta_dependency_deployment_id_deployment_id_fk", "tableFrom": "deployment_meta_dependency", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -867,12 +808,8 @@ "name": "deployment_meta_dependency_depends_on_id_deployment_id_fk", "tableFrom": "deployment_meta_dependency", "tableTo": "deployment", - "columnsFrom": [ - "depends_on_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["depends_on_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -966,12 +903,8 @@ "name": "environment_system_id_system_id_fk", "tableFrom": "environment", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -979,12 +912,8 @@ "name": "environment_policy_id_environment_policy_id_fk", "tableFrom": "environment", "tableTo": "environment_policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1050,12 +979,8 @@ "name": "environment_metadata_environment_id_environment_id_fk", "tableFrom": "environment_metadata", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1151,12 +1076,8 @@ "name": "environment_policy_system_id_system_id_fk", "tableFrom": "environment_policy", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -1230,12 +1151,8 @@ "name": "environment_policy_approval_policy_id_environment_policy_id_fk", "tableFrom": "environment_policy_approval", "tableTo": "environment_policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1243,12 +1160,8 @@ "name": "environment_policy_approval_release_id_release_id_fk", "tableFrom": "environment_policy_approval", "tableTo": "release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1256,12 +1169,8 @@ "name": "environment_policy_approval_user_id_user_id_fk", "tableFrom": "environment_policy_approval", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -1321,12 +1230,8 @@ "name": "environment_policy_deployment_policy_id_environment_policy_id_fk", "tableFrom": "environment_policy_deployment", "tableTo": "environment_policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1334,12 +1239,8 @@ "name": "environment_policy_deployment_environment_id_environment_id_fk", "tableFrom": "environment_policy_deployment", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1426,12 +1327,8 @@ "name": "environment_policy_release_channel_policy_id_environment_policy_id_fk", "tableFrom": "environment_policy_release_channel", "tableTo": "environment_policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1439,12 +1336,8 @@ "name": "environment_policy_release_channel_channel_id_release_channel_id_fk", "tableFrom": "environment_policy_release_channel", "tableTo": "release_channel", - "columnsFrom": [ - "channel_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["channel_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1452,12 +1345,8 @@ "name": "environment_policy_release_channel_deployment_id_deployment_id_fk", "tableFrom": "environment_policy_release_channel", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1508,12 +1397,8 @@ "name": "environment_policy_release_window_policy_id_environment_policy_id_fk", "tableFrom": "environment_policy_release_window", "tableTo": "environment_policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1600,12 +1485,8 @@ "name": "environment_release_channel_environment_id_environment_id_fk", "tableFrom": "environment_release_channel", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1613,12 +1494,8 @@ "name": "environment_release_channel_channel_id_release_channel_id_fk", "tableFrom": "environment_release_channel", "tableTo": "release_channel", - "columnsFrom": [ - "channel_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["channel_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1626,12 +1503,8 @@ "name": "environment_release_channel_deployment_id_deployment_id_fk", "tableFrom": "environment_release_channel", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1768,12 +1641,8 @@ "name": "runhook_hook_id_hook_id_fk", "tableFrom": "runhook", "tableTo": "hook", - "columnsFrom": [ - "hook_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["hook_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1781,12 +1650,8 @@ "name": "runhook_runbook_id_runbook_id_fk", "tableFrom": "runhook", "tableTo": "runbook", - "columnsFrom": [ - "runbook_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1878,12 +1743,8 @@ "name": "github_organization_added_by_user_id_user_id_fk", "tableFrom": "github_organization", "tableTo": "user", - "columnsFrom": [ - "added_by_user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["added_by_user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1891,12 +1752,8 @@ "name": "github_organization_workspace_id_workspace_id_fk", "tableFrom": "github_organization", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1940,12 +1797,8 @@ "name": "github_user_user_id_user_id_fk", "tableFrom": "github_user", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2005,12 +1858,8 @@ "name": "job_resource_relationship_job_id_job_id_fk", "tableFrom": "job_resource_relationship", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2126,12 +1975,8 @@ "name": "resource_provider_id_resource_provider_id_fk", "tableFrom": "resource", "tableTo": "resource_provider", - "columnsFrom": [ - "provider_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -2139,12 +1984,8 @@ "name": "resource_workspace_id_workspace_id_fk", "tableFrom": "resource", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2210,12 +2051,8 @@ "name": "resource_metadata_resource_id_resource_id_fk", "tableFrom": "resource_metadata", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2288,12 +2125,8 @@ "name": "resource_relationship_workspace_id_workspace_id_fk", "tableFrom": "resource_relationship", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2371,12 +2204,8 @@ "name": "resource_schema_workspace_id_workspace_id_fk", "tableFrom": "resource_schema", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -2449,12 +2278,8 @@ "name": "resource_variable_resource_id_resource_id_fk", "tableFrom": "resource_variable", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2505,12 +2330,8 @@ "name": "resource_view_workspace_id_workspace_id_fk", "tableFrom": "resource_view", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2577,12 +2398,8 @@ "name": "resource_provider_workspace_id_workspace_id_fk", "tableFrom": "resource_provider", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -2620,12 +2437,8 @@ "name": "resource_provider_aws_resource_provider_id_resource_provider_id_fk", "tableFrom": "resource_provider_aws", "tableTo": "resource_provider", - "columnsFrom": [ - "resource_provider_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_provider_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2684,12 +2497,8 @@ "name": "resource_provider_google_resource_provider_id_resource_provider_id_fk", "tableFrom": "resource_provider_google", "tableTo": "resource_provider", - "columnsFrom": [ - "resource_provider_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_provider_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2769,12 +2578,8 @@ "name": "release_deployment_id_deployment_id_fk", "tableFrom": "release", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2848,12 +2653,8 @@ "name": "release_channel_deployment_id_deployment_id_fk", "tableFrom": "release_channel", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2920,12 +2721,8 @@ "name": "release_dependency_release_id_release_id_fk", "tableFrom": "release_dependency", "tableTo": "release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2933,12 +2730,8 @@ "name": "release_dependency_deployment_id_deployment_id_fk", "tableFrom": "release_dependency", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3008,12 +2801,8 @@ "name": "release_job_trigger_job_id_job_id_fk", "tableFrom": "release_job_trigger", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -3021,12 +2810,8 @@ "name": "release_job_trigger_caused_by_id_user_id_fk", "tableFrom": "release_job_trigger", "tableTo": "user", - "columnsFrom": [ - "caused_by_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["caused_by_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -3034,12 +2819,8 @@ "name": "release_job_trigger_release_id_release_id_fk", "tableFrom": "release_job_trigger", "tableTo": "release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3047,12 +2828,8 @@ "name": "release_job_trigger_resource_id_resource_id_fk", "tableFrom": "release_job_trigger", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3060,12 +2837,8 @@ "name": "release_job_trigger_environment_id_environment_id_fk", "tableFrom": "release_job_trigger", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3075,9 +2848,7 @@ "release_job_trigger_job_id_unique": { "name": "release_job_trigger_job_id_unique", "nullsNotDistinct": false, - "columns": [ - "job_id" - ] + "columns": ["job_id"] } } }, @@ -3139,12 +2910,8 @@ "name": "release_metadata_release_id_release_id_fk", "tableFrom": "release_metadata", "tableTo": "release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3217,12 +2984,8 @@ "name": "system_workspace_id_workspace_id_fk", "tableFrom": "system", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3279,12 +3042,8 @@ "name": "runbook_system_id_system_id_fk", "tableFrom": "runbook", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3292,12 +3051,8 @@ "name": "runbook_job_agent_id_job_agent_id_fk", "tableFrom": "runbook", "tableTo": "job_agent", - "columnsFrom": [ - "job_agent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -3342,12 +3097,8 @@ "name": "runbook_job_trigger_job_id_job_id_fk", "tableFrom": "runbook_job_trigger", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3355,12 +3106,8 @@ "name": "runbook_job_trigger_runbook_id_runbook_id_fk", "tableFrom": "runbook_job_trigger", "tableTo": "runbook", - "columnsFrom": [ - "runbook_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3370,9 +3117,7 @@ "runbook_job_trigger_job_id_unique": { "name": "runbook_job_trigger_job_id_unique", "nullsNotDistinct": false, - "columns": [ - "job_id" - ] + "columns": ["job_id"] } } }, @@ -3406,12 +3151,8 @@ "name": "team_workspace_id_workspace_id_fk", "tableFrom": "team", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3471,12 +3212,8 @@ "name": "team_member_team_id_team_id_fk", "tableFrom": "team_member", "tableTo": "team", - "columnsFrom": [ - "team_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["team_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3484,12 +3221,8 @@ "name": "team_member_user_id_user_id_fk", "tableFrom": "team_member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3601,12 +3334,8 @@ "name": "job_job_agent_id_job_agent_id_fk", "tableFrom": "job", "tableTo": "job_agent", - "columnsFrom": [ - "job_agent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -3672,12 +3401,8 @@ "name": "job_metadata_job_id_job_id_fk", "tableFrom": "job_metadata", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3750,12 +3475,8 @@ "name": "job_variable_job_id_job_id_fk", "tableFrom": "job_variable", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -3806,9 +3527,7 @@ "workspace_slug_unique": { "name": "workspace_slug_unique", "nullsNotDistinct": false, - "columns": [ - "slug" - ] + "columns": ["slug"] } } }, @@ -3896,12 +3615,8 @@ "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", "tableFrom": "workspace_email_domain_matching", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -3909,12 +3624,8 @@ "name": "workspace_email_domain_matching_role_id_role_id_fk", "tableFrom": "workspace_email_domain_matching", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3958,12 +3669,8 @@ "name": "variable_set_system_id_system_id_fk", "tableFrom": "variable_set", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4001,12 +3708,8 @@ "name": "variable_set_environment_variable_set_id_variable_set_id_fk", "tableFrom": "variable_set_environment", "tableTo": "variable_set", - "columnsFrom": [ - "variable_set_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4014,12 +3717,8 @@ "name": "variable_set_environment_environment_id_environment_id_fk", "tableFrom": "variable_set_environment", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4085,12 +3784,8 @@ "name": "variable_set_value_variable_set_id_variable_set_id_fk", "tableFrom": "variable_set_value", "tableTo": "variable_set", - "columnsFrom": [ - "variable_set_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["variable_set_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4147,12 +3842,8 @@ "name": "workspace_invite_token_role_id_role_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4160,12 +3851,8 @@ "name": "workspace_invite_token_workspace_id_workspace_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -4173,12 +3860,8 @@ "name": "workspace_invite_token_created_by_user_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4188,9 +3871,7 @@ "workspace_invite_token_token_unique": { "name": "workspace_invite_token_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } } }, @@ -4243,12 +3924,8 @@ "name": "resource_metadata_group_workspace_id_workspace_id_fk", "tableFrom": "resource_metadata_group", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4334,12 +4011,8 @@ "name": "runbook_variable_runbook_id_runbook_id_fk", "tableFrom": "runbook_variable", "tableTo": "runbook", - "columnsFrom": [ - "runbook_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["runbook_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4437,12 +4110,8 @@ "name": "entity_role_role_id_role_id_fk", "tableFrom": "entity_role", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4486,12 +4155,8 @@ "name": "role_workspace_id_workspace_id_fk", "tableFrom": "role", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4551,12 +4216,8 @@ "name": "role_permission_role_id_role_id_fk", "tableFrom": "role_permission", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4629,12 +4290,8 @@ "name": "job_agent_workspace_id_workspace_id_fk", "tableFrom": "job_agent", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -4647,54 +4304,32 @@ "public.environment_policy_approval_requirement": { "name": "environment_policy_approval_requirement", "schema": "public", - "values": [ - "manual", - "automatic" - ] + "values": ["manual", "automatic"] }, "public.approval_status_type": { "name": "approval_status_type", "schema": "public", - "values": [ - "pending", - "approved", - "rejected" - ] + "values": ["pending", "approved", "rejected"] }, "public.environment_policy_deployment_success_type": { "name": "environment_policy_deployment_success_type", "schema": "public", - "values": [ - "all", - "some", - "optional" - ] + "values": ["all", "some", "optional"] }, "public.recurrence_type": { "name": "recurrence_type", "schema": "public", - "values": [ - "hourly", - "daily", - "weekly", - "monthly" - ] + "values": ["hourly", "daily", "weekly", "monthly"] }, "public.release_sequencing_type": { "name": "release_sequencing_type", "schema": "public", - "values": [ - "wait", - "cancel" - ] + "values": ["wait", "cancel"] }, "public.resource_relationship_type": { "name": "resource_relationship_type", "schema": "public", - "values": [ - "associated_with", - "depends_on" - ] + "values": ["associated_with", "depends_on"] }, "public.release_job_trigger_type": { "name": "release_job_trigger_type", @@ -4740,10 +4375,7 @@ "public.entity_type": { "name": "entity_type", "schema": "public", - "values": [ - "user", - "team" - ] + "values": ["user", "team"] }, "public.scope_type": { "name": "scope_type", @@ -4775,4 +4407,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 59029497..03bc1e9d 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -353,4 +353,4 @@ "breakpoints": true } ] -} \ No newline at end of file +}