From 342fc9edab4397b6b98e9e1b5918a760ccad388a Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sat, 23 Nov 2024 19:44:05 -0800 Subject: [PATCH 1/7] init --- .../ResourceVisualizationDiagram.tsx | 47 ++++---- .../visualize/nodes/DeploymentNode.tsx | 18 +--- .../visualize/nodes/EnvironmentNode.tsx | 85 +++++++++++---- .../visualize/nodes/ProviderNode.tsx | 9 +- .../visualize/nodes/ResourceNode.tsx | 4 +- .../[targetId]/visualize/nodes/SystemNode.tsx | 18 +--- packages/api/src/router/deployment.ts | 101 +++++++++++++++--- packages/api/src/router/resources.ts | 54 +++++++++- 8 files changed, 242 insertions(+), 94 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx index 8b67bddb..3ba45336 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx @@ -65,24 +65,31 @@ export const ResourceVisualizationDiagram: React.FC< system.environments.map((env) => ({ id: env.id, type: NodeType.Environment, - data: { ...env, label: env.name }, - position: { x: 0, y: 0 }, - })), - ), - ...systems.map((system) => ({ - id: system.id, - type: NodeType.System, - data: { ...system, label: system.name }, - position: { x: 0, y: 0 }, - })), - ...systems.flatMap((system) => - system.deployments.map((deployment) => ({ - id: deployment.id, - type: NodeType.Deployment, - data: { ...deployment, label: deployment.name }, + data: { + environment: { + ...env, + deployments: system.deployments, + resource, + }, + label: `${system.name}/${env.name}`, + }, position: { x: 0, y: 0 }, })), ), + // ...systems.map((system) => ({ + // id: system.id, + // type: NodeType.System, + // data: { ...system, label: system.name }, + // position: { x: 0, y: 0 }, + // })), + // ...systems.flatMap((system) => + // system.deployments.map((deployment) => ({ + // id: deployment.id, + // type: NodeType.Deployment, + // data: { ...deployment, label: deployment.name }, + // position: { x: 0, y: 0 }, + // })), + // ), provider != null && { id: provider.id, type: NodeType.Provider, @@ -96,20 +103,20 @@ export const ResourceVisualizationDiagram: React.FC< resource, systems.flatMap((s) => s.environments), ); - const envToSystemEdges = createEdgesFromEnvironmentsToSystems(systems); - const systemToDeploymentsEdges = createEdgesFromSystemsToDeployments(systems); + // const envToSystemEdges = createEdgesFromEnvironmentsToSystems(systems); + // const systemToDeploymentsEdges = createEdgesFromSystemsToDeployments(systems); const providerEdge = createEdgeFromProviderToResource(provider, resource); const [edges, __, onEdgesChange] = useEdgesState( compact([ ...resourceToEnvEdges, - ...envToSystemEdges, - ...systemToDeploymentsEdges, + // ...envToSystemEdges, + // ...systemToDeploymentsEdges, providerEdge, ]), ); - const setReactFlowInstance = useLayoutAndFitView(nodes); + const setReactFlowInstance = useLayoutAndFitView(nodes, { direction: "LR" }); return ( = (node) => { const { data } = node; @@ -16,22 +15,13 @@ export const DeploymentNode: React.FC = (node) => { ); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx index 32eb7be7..85366c30 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx @@ -1,37 +1,86 @@ +"use client"; + +import type * as SCHEMA from "@ctrlplane/db/schema"; import type { NodeProps } from "reactflow"; +import React from "react"; import { IconPlant } from "@tabler/icons-react"; import { Handle, Position } from "reactflow"; -import colors from "tailwindcss/colors"; -export const EnvironmentNode: React.FC = (node) => { +import { api } from "~/trpc/react"; +import { ReleaseCell } from "../../ReleaseCell"; + +type Environment = SCHEMA.Environment & { + deployments: SCHEMA.Deployment[]; + resource: SCHEMA.Resource; +}; + +type EnvironmentNodeProps = NodeProps<{ + label: string; + environment: Environment; +}>; + +const DeploymentCard: React.FC<{ + environment: Environment; + deployment: SCHEMA.Deployment; + resource: SCHEMA.Resource; +}> = ({ deployment, resource, environment }) => { + const latestActiveReleaseQ = api.deployment.byTargetId.useQuery({ + resourceId: resource.id, + environmentIds: [environment.id], + deploymentIds: [deployment.id], + jobsPerDeployment: 1, + showAllStatuses: true, + }); + + const latestActiveRelease = latestActiveReleaseQ.data?.at(0); + if (latestActiveReleaseQ.isLoading) + return ( +
+ ); + + if (latestActiveRelease?.releaseJobTrigger == null) + return
No active release
; + + return ( +
+
{deployment.name}
+ +
+ ); +}; + +export const EnvironmentNode: React.FC = (node) => { const { data } = node; return ( <> -
+
- Environment + {data.label} +
+
+ {data.environment.deployments.map((deployment) => ( + + ))}
-
{data.label}
); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ProviderNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ProviderNode.tsx index e4184c78..90f1fe4d 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ProviderNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ProviderNode.tsx @@ -52,7 +52,7 @@ export const ProviderNode: React.FC = (node) => { "h-2 w-2 rounded-full border border-green-500 bg-neutral-800", data.google != null && "border-red-500 bg-red-800", )} - position={Position.Top} + position={Position.Left} /> = (node) => { "h-2 w-2 rounded-full border border-green-500 bg-neutral-800", data.google != null && "border-red-500 bg-red-800", )} - style={{ - bottom: "0", - left: "50%", - transform: "translate(-50%, 50%)", - }} - position={Position.Bottom} + position={Position.Right} /> ); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ResourceNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ResourceNode.tsx index 492252b0..7f525939 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ResourceNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/ResourceNode.tsx @@ -44,7 +44,7 @@ export const ResourceNode: React.FC = (node) => { isTerraform && "border-purple-500/70", isSharedCluster && "border-blue-500/70", )} - position={Position.Top} + position={Position.Left} /> = (node) => { isTerraform && "border-purple-500/70", isSharedCluster && "border-blue-500/70", )} - position={Position.Bottom} + position={Position.Right} /> ); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/SystemNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/SystemNode.tsx index 84ad12c5..e6d1abf9 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/SystemNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/SystemNode.tsx @@ -1,7 +1,6 @@ import type { NodeProps } from "reactflow"; import { IconCategory } from "@tabler/icons-react"; import { Handle, Position } from "reactflow"; -import colors from "tailwindcss/colors"; export const SystemNode: React.FC = (node) => { const { data } = node; @@ -16,22 +15,13 @@ export const SystemNode: React.FC = (node) => {
); diff --git a/packages/api/src/router/deployment.ts b/packages/api/src/router/deployment.ts index dc7e1829..a56661d3 100644 --- a/packages/api/src/router/deployment.ts +++ b/packages/api/src/router/deployment.ts @@ -370,6 +370,7 @@ const latestActiveReleaseSubQuery = (db: Tx) => name: release.name, config: release.config, environmentId: releaseJobTrigger.environmentId, + resourceId: releaseJobTrigger.resourceId, rank: sql`ROW_NUMBER() OVER (PARTITION BY ${release.deploymentId}, ${releaseJobTrigger.environmentId} ORDER BY ${release.createdAt} DESC)`.as( "rank", @@ -611,18 +612,33 @@ export const deploymentRouter = createTRPCRouter({ }), byTargetId: protectedProcedure - .input(z.string().uuid()) + .input( + z.object({ + resourceId: z.string().uuid(), + environmentIds: z.array(z.string().uuid()).optional(), + deploymentIds: z.array(z.string().uuid()).optional(), + jobsPerDeployment: z.number().optional().default(30), + showAllStatuses: z.boolean().optional().default(false), + }), + ) .meta({ authorizationCheck: ({ canUser, input }) => canUser .perform(Permission.DeploymentList) - .on({ type: "resource", id: input }), + .on({ type: "resource", id: input.resourceId }), }) .query(async ({ ctx, input }) => { + const { + resourceId, + environmentIds, + deploymentIds, + jobsPerDeployment, + showAllStatuses, + } = input; const tg = await ctx.db .select() .from(resource) - .where(and(eq(resource.id, input), isNull(resource.deletedAt))) + .where(and(eq(resource.id, resourceId), isNull(resource.deletedAt))) .then(takeFirst); const envs = await ctx.db @@ -633,6 +649,9 @@ export const deploymentRouter = createTRPCRouter({ and( eq(system.workspaceId, tg.workspaceId), isNotNull(environment.resourceFilter), + environmentIds != null + ? inArray(environment.id, environmentIds) + : undefined, ), ); @@ -660,33 +679,85 @@ export const deploymentRouter = createTRPCRouter({ .where( and( - eq(resource.id, input), + eq(resource.id, resourceId), isNull(resource.deletedAt), - inArray(job.status, [ - JobStatus.Completed, - JobStatus.Pending, - JobStatus.InProgress, - ]), + showAllStatuses + ? undefined + : inArray(job.status, [ + JobStatus.Completed, + JobStatus.Pending, + JobStatus.InProgress, + ]), + deploymentIds != null + ? inArray(deployment.id, deploymentIds) + : undefined, ), ) + .limit(jobsPerDeployment) .orderBy(deployment.id, releaseJobTrigger.createdAt) .then((r) => r.map((row) => ({ ...row.deployment, environment: row.environment, system: row.system, - releaseJobTrigger: { - ...row.release_job_trigger, - job: row.job, - release: row.release, - resourceId: row.resource.id, - }, + releaseJobTrigger: + row.release_job_trigger != null + ? { + ...row.release_job_trigger, + job: row.job!, + release: row.release!, + resourceId: row.resource.id, + } + : null, })), ), ), ).then((r) => r.flat()); }), + byResourceAndDeploymentId: protectedProcedure + .input( + z.object({ + resourceId: z.string().uuid(), + deploymentId: z.string().uuid(), + }), + ) + .meta({ + authorizationCheck: async ({ canUser, input }) => { + const { resourceId, deploymentId } = input; + const canGetDeploymentPromise = canUser + .perform(Permission.DeploymentGet) + .on({ type: "deployment", id: deploymentId }); + const canGetResourcePromise = canUser + .perform(Permission.ResourceGet) + .on({ type: "resource", id: resourceId }); + const [canGetDeployment, canGetResource] = await Promise.all([ + canGetDeploymentPromise, + canGetResourcePromise, + ]); + return canGetDeployment && canGetResource; + }, + }) + .query(async ({ ctx, input }) => { + const { resourceId, deploymentId } = input; + const activeRelease = latestActiveReleaseSubQuery(ctx.db); + return ctx.db + .select() + .from(deployment) + .innerJoin(activeRelease, eq(activeRelease.deploymentId, deployment.id)) + .where( + and( + eq(activeRelease.resourceId, resourceId), + eq(deployment.id, deploymentId), + ), + ) + .then(takeFirst) + .then((row) => ({ + ...row.deployment, + latestActiveRelease: row.active_releases, + })); + }), + byWorkspaceId: protectedProcedure .meta({ authorizationCheck: ({ canUser, input }) => diff --git a/packages/api/src/router/resources.ts b/packages/api/src/router/resources.ts index 54f9f37f..378d7cf6 100644 --- a/packages/api/src/router/resources.ts +++ b/packages/api/src/router/resources.ts @@ -394,12 +394,58 @@ export const resourceRouter = createTRPCRouter({ ? null : { ...resource.provider, - google: - resource.provider.google.length > 0 - ? resource.provider.google[0]! - : null, + google: resource.provider.google[0] ?? null, }; + // const latestJobsForDeploymentsPromises = matchedSystems.flatMap((sys) => + // sys.deployments.map(async (d) => { + // const latestReleaseSubquery = ctx.db + // .select({ + // id: schema.release.id, + // deploymentId: schema.release.deploymentId, + // version: schema.release.version, + // createdAt: schema.release.createdAt, + // environmentId: schema.releaseJobTrigger.environmentId, + // status: schema.job.status, + // rank: sql`ROW_NUMBER() OVER (PARTITION BY ${schema.release.deploymentId}, ${schema.releaseJobTrigger.environmentId} ORDER BY ${schema.release.createdAt} DESC)`.as( + // "rank", + // ), + // }) + // .from(schema.release) + // .innerJoin( + // schema.releaseJobTrigger, + // eq(schema.releaseJobTrigger.releaseId, schema.release.id), + // ) + // .innerJoin( + // schema.job, + // eq(schema.releaseJobTrigger.jobId, schema.job.id), + // ) + // .as("latest_releases"); + + // const latestReleases = await ctx.db + // .select() + // .from(latestReleaseSubquery) + // .where( + // and( + // eq(latestReleaseSubquery.deploymentId, d.id), + // eq(latestReleaseSubquery.rank, 1), + // ), + // ); + + // return { ...d, latestReleases }; + // }), + // ); + // const latestJobsForDeployments = await Promise.all( + // latestJobsForDeploymentsPromises, + // ); + + // const matchedSystemsWithDeployments = matchedSystems.map((sys) => ({ + // ...sys, + // deployments: latestJobsForDeployments.filter( + // (d) => d.systemId === sys.id, + // ), + // })); + return { systems: matchedSystems, provider }; }), From 6504257f2b4bcf46474b246d4f71a2d6d6065c27 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 13:26:29 -0800 Subject: [PATCH 2/7] more change --- .../targets/[targetId]/ReleaseCell.tsx | 42 +- .../(targets)/targets/[targetId]/page.tsx | 12 +- .../targets/[targetId]/variables/page.tsx | 7 +- .../ResourceVisualizationDiagram.tsx | 31 +- .../targets/[targetId]/visualize/edges.ts | 29 - .../visualize/nodes/DeploymentNode.tsx | 28 - .../visualize/nodes/EnvironmentNode.tsx | 120 +- .../[targetId]/visualize/nodes/SystemNode.tsx | 28 - .../target-drawer/DeploymentContent.tsx | 11 +- .../target-drawer/VariablesContent.tsx | 5 +- .../deployment-to-resource/route.ts | 74 - packages/api/src/router/deployment.ts | 23 +- packages/api/src/router/resources.ts | 49 - packages/db/drizzle/0042_lonely_warstar.sql | 1 + packages/db/drizzle/meta/0042_snapshot.json | 4634 +++++++++++++++++ packages/db/drizzle/meta/_journal.json | 9 +- packages/db/src/schema/resource.ts | 23 - packages/job-dispatch/src/resource/delete.ts | 30 +- 18 files changed, 4813 insertions(+), 343 deletions(-) delete mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/DeploymentNode.tsx delete mode 100644 apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/SystemNode.tsx delete mode 100644 apps/webservice/src/app/api/v1/relationship/deployment-to-resource/route.ts create mode 100644 packages/db/drizzle/0042_lonely_warstar.sql create mode 100644 packages/db/drizzle/meta/0042_snapshot.json diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/ReleaseCell.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/ReleaseCell.tsx index 763f20a9..e7ed0400 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/ReleaseCell.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/ReleaseCell.tsx @@ -8,12 +8,19 @@ import type { } from "@ctrlplane/db/schema"; import Link from "next/link"; import { useParams } from "next/navigation"; -import { IconCircleCheck, IconClock, IconLoader2 } from "@tabler/icons-react"; +import { + IconAlertCircle, + IconCircleCheck, + IconCircleDashed, + IconCircleX, + IconClock, + IconLoader2, +} from "@tabler/icons-react"; import { format } from "date-fns"; import { JobStatus } from "@ctrlplane/validators/jobs"; -const ReleaseIcon: React.FC<{ +export const ReleaseIcon: React.FC<{ job?: Job; }> = ({ job }) => { if (job?.status === JobStatus.Pending) @@ -37,6 +44,37 @@ const ReleaseIcon: React.FC<{
); + if (job?.status === JobStatus.Cancelled) + return ( +
+ +
+ ); + + if (job?.status === JobStatus.Failure) + return ( +
+ +
+ ); + + if (job?.status === JobStatus.Skipped) + return ( +
+ +
+ ); + + if ( + job?.status === JobStatus.InvalidJobAgent || + job?.status === JobStatus.InvalidIntegration + ) + return ( +
+ +
+ ); + return null; }; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx index 27bcae5d..ee19ca29 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx @@ -25,8 +25,9 @@ import { useMatchSorterWithSearch } from "~/utils/useMatchSorter"; import { ReleaseCell } from "./ReleaseCell"; const DeploymentsTable: React.FC<{ targetId: string }> = ({ targetId }) => { - const jobs = api.job.byResourceId.useQuery(targetId); - const deployments = api.deployment.byTargetId.useQuery(targetId); + const resourceId = targetId; + const jobs = api.job.byResourceId.useQuery(resourceId); + const deployments = api.deployment.byTargetId.useQuery({ resourceId }); return ( @@ -106,9 +107,10 @@ export default function TargetPage({ }: { params: { targetId: string }; }) { - const target = api.resource.byId.useQuery(params.targetId); - const jobs = api.job.byResourceId.useQuery(params.targetId); - const deployments = api.deployment.byTargetId.useQuery(params.targetId); + const resourceId = params.targetId; + const target = api.resource.byId.useQuery(resourceId); + const jobs = api.job.byResourceId.useQuery(resourceId); + const deployments = api.deployment.byTargetId.useQuery({ resourceId }); const unlockTarget = api.resource.unlock.useMutation(); const lockTarget = api.resource.lock.useMutation(); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx index d6d2820a..d02b9363 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx @@ -34,10 +34,9 @@ export default function VariablePage({ }: { params: { targetId: string }; }) { - const deployments = api.deployment.byTargetId.useQuery(params.targetId); - const variables = api.deployment.variable.byTargetId.useQuery( - params.targetId, - ); + const resourceId = params.targetId; + const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const variables = api.deployment.variable.byTargetId.useQuery(resourceId); return (
{deployments.data?.map((deployment) => { diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx index 3ba45336..e751f843 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx @@ -15,15 +15,11 @@ import { useLayoutAndFitView } from "~/app/[workspaceSlug]/(app)/_components/rea import { DepEdge } from "./DepEdge"; import { createEdgeFromProviderToResource, - createEdgesFromEnvironmentsToSystems, createEdgesFromResourceToEnvironments, - createEdgesFromSystemsToDeployments, } from "./edges"; -import { DeploymentNode } from "./nodes/DeploymentNode"; import { EnvironmentNode } from "./nodes/EnvironmentNode"; import { ProviderNode } from "./nodes/ProviderNode"; import { ResourceNode } from "./nodes/ResourceNode"; -import { SystemNode } from "./nodes/SystemNode"; type Relationships = NonNullable; @@ -36,16 +32,12 @@ enum NodeType { Resource = "resource", Environment = "environment", Provider = "provider", - System = "system", - Deployment = "deployment", } const nodeTypes: NodeTypes = { [NodeType.Resource]: ResourceNode, [NodeType.Environment]: EnvironmentNode, [NodeType.Provider]: ProviderNode, - [NodeType.System]: SystemNode, - [NodeType.Deployment]: DeploymentNode, }; const edgeTypes: EdgeTypes = { default: DepEdge }; @@ -76,20 +68,6 @@ export const ResourceVisualizationDiagram: React.FC< position: { x: 0, y: 0 }, })), ), - // ...systems.map((system) => ({ - // id: system.id, - // type: NodeType.System, - // data: { ...system, label: system.name }, - // position: { x: 0, y: 0 }, - // })), - // ...systems.flatMap((system) => - // system.deployments.map((deployment) => ({ - // id: deployment.id, - // type: NodeType.Deployment, - // data: { ...deployment, label: deployment.name }, - // position: { x: 0, y: 0 }, - // })), - // ), provider != null && { id: provider.id, type: NodeType.Provider, @@ -103,17 +81,10 @@ export const ResourceVisualizationDiagram: React.FC< resource, systems.flatMap((s) => s.environments), ); - // const envToSystemEdges = createEdgesFromEnvironmentsToSystems(systems); - // const systemToDeploymentsEdges = createEdgesFromSystemsToDeployments(systems); const providerEdge = createEdgeFromProviderToResource(provider, resource); const [edges, __, onEdgesChange] = useEdgesState( - compact([ - ...resourceToEnvEdges, - // ...envToSystemEdges, - // ...systemToDeploymentsEdges, - providerEdge, - ]), + compact([...resourceToEnvEdges, providerEdge]), ); const setReactFlowInstance = useLayoutAndFitView(nodes, { direction: "LR" }); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/edges.ts b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/edges.ts index 286efa91..6123ec35 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/edges.ts +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/edges.ts @@ -24,35 +24,6 @@ export const createEdgesFromResourceToEnvironments = ( label: "in", })); -type System = SCHEMA.System & { - environments: SCHEMA.Environment[]; - deployments: SCHEMA.Deployment[]; -}; - -export const createEdgesFromEnvironmentsToSystems = (systems: System[]) => - systems.flatMap((system) => - system.environments.map((environment) => ({ - id: `${environment.id}-${system.id}`, - source: environment.id, - target: system.id, - style: { stroke: colors.neutral[700] }, - markerEnd, - label: "part of", - })), - ); - -export const createEdgesFromSystemsToDeployments = (systems: System[]) => - systems.flatMap((system) => - system.deployments.map((deployment) => ({ - id: `${system.id}-${deployment.id}`, - source: system.id, - target: deployment.id, - style: { stroke: colors.neutral[700] }, - markerEnd, - label: "deploys", - })), - ); - export const createEdgeFromProviderToResource = ( provider: Provider | null, resource: SCHEMA.Resource, diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/DeploymentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/DeploymentNode.tsx deleted file mode 100644 index b2d06c7c..00000000 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/DeploymentNode.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { NodeProps } from "reactflow"; -import { IconShip } from "@tabler/icons-react"; -import { Handle, Position } from "reactflow"; - -export const DeploymentNode: React.FC = (node) => { - const { data } = node; - return ( - <> -
-
- - Deployment -
-
{data.label}
-
- - - - ); -}; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx index 85366c30..cc606d5d 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx @@ -6,8 +6,11 @@ import React from "react"; import { IconPlant } from "@tabler/icons-react"; import { Handle, Position } from "reactflow"; +import { cn } from "@ctrlplane/ui"; +import { JobStatus, JobStatusReadable } from "@ctrlplane/validators/jobs"; + import { api } from "~/trpc/react"; -import { ReleaseCell } from "../../ReleaseCell"; +import { ReleaseIcon } from "../../ReleaseCell"; type Environment = SCHEMA.Environment & { deployments: SCHEMA.Deployment[]; @@ -20,56 +23,95 @@ type EnvironmentNodeProps = NodeProps<{ }>; const DeploymentCard: React.FC<{ - environment: Environment; - deployment: SCHEMA.Deployment; - resource: SCHEMA.Resource; -}> = ({ deployment, resource, environment }) => { - const latestActiveReleaseQ = api.deployment.byTargetId.useQuery({ - resourceId: resource.id, - environmentIds: [environment.id], - deploymentIds: [deployment.id], - jobsPerDeployment: 1, - showAllStatuses: true, - }); + deploymentName: string; + job?: SCHEMA.Job; + releaseVersion: string; +}> = ({ deploymentName, job, releaseVersion }) => ( +
+
{deploymentName}
+ {job != null && ( +
+ +
+
{releaseVersion}
+
{JobStatusReadable[job.status]}
+
+
+ )} + {job == null && ( +
+ No active job +
+ )} +
+); - const latestActiveRelease = latestActiveReleaseQ.data?.at(0); - if (latestActiveReleaseQ.isLoading) - return ( -
- ); +export const EnvironmentNode: React.FC = (node) => { + const { data } = node; - if (latestActiveRelease?.releaseJobTrigger == null) - return
No active release
; + const latestActiveReleasesQ = api.deployment.byTargetId.useQuery( + { + resourceId: data.environment.resource.id, + environmentIds: [data.environment.id], + deploymentIds: data.environment.deployments.map((d) => d.id), + jobsPerDeployment: 1, + showAllStatuses: true, + }, + { refetchInterval: 5_000 }, + ); - return ( -
-
{deployment.name}
- -
+ const latestActiveReleases = latestActiveReleasesQ.data ?? []; + + const isInProgress = latestActiveReleases.some( + (r) => r.releaseJobTrigger?.job.status === JobStatus.InProgress, + ); + const isPending = latestActiveReleases.some( + (r) => r.releaseJobTrigger?.job.status === JobStatus.Pending, + ); + const isCompleted = latestActiveReleases.every( + (r) => r.releaseJobTrigger?.job.status === JobStatus.Completed, ); -}; -export const EnvironmentNode: React.FC = (node) => { - const { data } = node; return ( <> -
+
{data.label}
- {data.environment.deployments.map((deployment) => ( - - ))} + {latestActiveReleasesQ.isLoading && + Array.from({ length: 3 }).map((_, i) => ( +
+ ))} + {!latestActiveReleasesQ.isLoading && + data.environment.deployments.map((deployment) => { + const latestActiveRelease = latestActiveReleases.find( + (r) => + r.releaseJobTrigger?.release.deploymentId === deployment.id, + ); + return ( + + ); + })}
= (node) => { - const { data } = node; - return ( - <> -
-
- - System -
-
{data.label}
-
- - - - ); -}; diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx index 54e3d54c..d66d47f2 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx @@ -9,8 +9,9 @@ import { api } from "~/trpc/react"; export const DeploymentsContent: React.FC<{ targetId: string }> = ({ targetId, }) => { - const deployments = api.deployment.byTargetId.useQuery(targetId); - const targetValues = api.deployment.variable.byTargetId.useQuery(targetId); + const resourceId = targetId; + const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const targetValues = api.deployment.variable.byTargetId.useQuery(resourceId); if (!deployments.data || deployments.data.length === 0) { return ( @@ -38,13 +39,13 @@ export const DeploymentsContent: React.FC<{ targetId: string }> = ({
- {deployment.releaseJobTrigger.release?.version ?? + {deployment.releaseJobTrigger?.release.version ?? "No deployments"}
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx index 59743907..7556daee 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx @@ -104,8 +104,9 @@ export const VariableContent: React.FC<{ targetId: string; targetVariables: SCHEMA.ResourceVariable[]; }> = ({ targetId, targetVariables }) => { - const deployments = api.deployment.byTargetId.useQuery(targetId); - const variables = api.deployment.variable.byTargetId.useQuery(targetId); + const resourceId = targetId; + const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const variables = api.deployment.variable.byTargetId.useQuery(resourceId); return (
}>(async (ctx) => { - try { - const { body, db } = ctx; - - const resource = await db - .select() - .from(SCHEMA.resource) - .where( - and( - eq(SCHEMA.resource.identifier, body.resourceIdentifier), - eq(SCHEMA.resource.workspaceId, body.workspaceId), - isNull(SCHEMA.resource.deletedAt), - ), - ) - .then(takeFirstOrNull); - if (!resource) - return Response.json({ error: "Resource not found" }, { status: 404 }); - - const deployment = await db - .select() - .from(SCHEMA.deployment) - .innerJoin( - SCHEMA.system, - eq(SCHEMA.deployment.systemId, SCHEMA.system.id), - ) - .where( - and( - eq(SCHEMA.deployment.id, body.deploymentId), - eq(SCHEMA.system.workspaceId, body.workspaceId), - ), - ) - .then(takeFirstOrNull); - if (!deployment) - return Response.json( - { error: "Deployment not found" }, - { status: 404 }, - ); - - await db - .insert(SCHEMA.deploymentResourceRelationship) - .values(body) - .returning(); - - return Response.json(body); - } catch (error) { - if (error instanceof Error && error.message.includes("duplicate key")) - return Response.json( - { error: "Resource already associated with a deployment" }, - { status: 400 }, - ); - return Response.json( - { error: "Failed to create relationship" }, - { status: 500 }, - ); - } - }); diff --git a/packages/api/src/router/deployment.ts b/packages/api/src/router/deployment.ts index a56661d3..8320c40f 100644 --- a/packages/api/src/router/deployment.ts +++ b/packages/api/src/router/deployment.ts @@ -10,6 +10,7 @@ import { inArray, isNotNull, isNull, + lte, sql, takeFirst, takeFirstOrNull, @@ -655,6 +656,17 @@ export const deploymentRouter = createTRPCRouter({ ), ); + const rankSubquery = ctx.db + .select({ + rank: sql`ROW_NUMBER() OVER (PARTITION BY ${release.deploymentId} ORDER BY ${release.createdAt} DESC)`.as( + "rank", + ), + rankReleaseId: release.id, + rankDeploymentId: release.deploymentId, + }) + .from(release) + .as("rank_subquery"); + return Promise.all( envs.map((env) => ctx.db @@ -663,6 +675,13 @@ export const deploymentRouter = createTRPCRouter({ .innerJoin(system, eq(system.id, deployment.systemId)) .innerJoin(environment, eq(environment.systemId, system.id)) .leftJoin(release, eq(release.deploymentId, deployment.id)) + .leftJoin( + rankSubquery, + and( + eq(rankSubquery.rankDeploymentId, release.deploymentId), + eq(rankSubquery.rankReleaseId, release.id), + ), + ) .innerJoin( resource, resourceMatchesMetadata(ctx.db, env.environment.resourceFilter), @@ -676,10 +695,10 @@ export const deploymentRouter = createTRPCRouter({ ), ) .leftJoin(job, eq(releaseJobTrigger.jobId, job.id)) - .where( and( eq(resource.id, resourceId), + eq(environment.id, env.environment.id), isNull(resource.deletedAt), showAllStatuses ? undefined @@ -691,9 +710,9 @@ export const deploymentRouter = createTRPCRouter({ deploymentIds != null ? inArray(deployment.id, deploymentIds) : undefined, + lte(rankSubquery.rank, jobsPerDeployment), ), ) - .limit(jobsPerDeployment) .orderBy(deployment.id, releaseJobTrigger.createdAt) .then((r) => r.map((row) => ({ diff --git a/packages/api/src/router/resources.ts b/packages/api/src/router/resources.ts index 378d7cf6..cc87c829 100644 --- a/packages/api/src/router/resources.ts +++ b/packages/api/src/router/resources.ts @@ -397,55 +397,6 @@ export const resourceRouter = createTRPCRouter({ google: resource.provider.google[0] ?? null, }; - // const latestJobsForDeploymentsPromises = matchedSystems.flatMap((sys) => - // sys.deployments.map(async (d) => { - // const latestReleaseSubquery = ctx.db - // .select({ - // id: schema.release.id, - // deploymentId: schema.release.deploymentId, - // version: schema.release.version, - // createdAt: schema.release.createdAt, - // environmentId: schema.releaseJobTrigger.environmentId, - // status: schema.job.status, - // rank: sql`ROW_NUMBER() OVER (PARTITION BY ${schema.release.deploymentId}, ${schema.releaseJobTrigger.environmentId} ORDER BY ${schema.release.createdAt} DESC)`.as( - // "rank", - // ), - // }) - // .from(schema.release) - // .innerJoin( - // schema.releaseJobTrigger, - // eq(schema.releaseJobTrigger.releaseId, schema.release.id), - // ) - // .innerJoin( - // schema.job, - // eq(schema.releaseJobTrigger.jobId, schema.job.id), - // ) - // .as("latest_releases"); - - // const latestReleases = await ctx.db - // .select() - // .from(latestReleaseSubquery) - // .where( - // and( - // eq(latestReleaseSubquery.deploymentId, d.id), - // eq(latestReleaseSubquery.rank, 1), - // ), - // ); - - // return { ...d, latestReleases }; - // }), - // ); - // const latestJobsForDeployments = await Promise.all( - // latestJobsForDeploymentsPromises, - // ); - - // const matchedSystemsWithDeployments = matchedSystems.map((sys) => ({ - // ...sys, - // deployments: latestJobsForDeployments.filter( - // (d) => d.systemId === sys.id, - // ), - // })); - return { systems: matchedSystems, provider }; }), diff --git a/packages/db/drizzle/0042_lonely_warstar.sql b/packages/db/drizzle/0042_lonely_warstar.sql new file mode 100644 index 00000000..e8210c76 --- /dev/null +++ b/packages/db/drizzle/0042_lonely_warstar.sql @@ -0,0 +1 @@ +DROP TABLE "deployment_resource_relationship"; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0042_snapshot.json b/packages/db/drizzle/meta/0042_snapshot.json new file mode 100644 index 00000000..99cc054d --- /dev/null +++ b/packages/db/drizzle/meta/0042_snapshot.json @@ -0,0 +1,4634 @@ +{ + "id": "becdc103-4a98-48b3-9225-2ecdb78ed96a", + "prevId": "b49d6d8e-a24d-443d-973b-162c71b7d5e5", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_providerAccountId_pk": { + "name": "account_provider_providerAccountId_pk", + "columns": [ + "provider", + "providerAccountId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "active_workspace_id": { + "name": "active_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "null" + } + }, + "indexes": {}, + "foreignKeys": { + "user_active_workspace_id_workspace_id_fk": { + "name": "user_active_workspace_id_workspace_id_fk", + "tableFrom": "user", + "tableTo": "workspace", + "columnsFrom": [ + "active_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_api_key": { + "name": "user_api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "key_preview": { + "name": "key_preview", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_hash": { + "name": "key_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_prefix": { + "name": "key_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_api_key_key_prefix_key_hash_index": { + "name": "user_api_key_key_prefix_key_hash_index", + "columns": [ + { + "expression": "key_prefix", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_api_key_user_id_user_id_fk": { + "name": "user_api_key_user_id_user_id_fk", + "tableFrom": "user_api_key", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dashboard": { + "name": "dashboard", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_workspace_id_workspace_id_fk": { + "name": "dashboard_workspace_id_workspace_id_fk", + "tableFrom": "dashboard", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.dashboard_widget": { + "name": "dashboard_widget", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "dashboard_id": { + "name": "dashboard_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "widget": { + "name": "widget", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "x": { + "name": "x", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "w": { + "name": "w", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "h": { + "name": "h", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_widget_dashboard_id_dashboard_id_fk": { + "name": "dashboard_widget_dashboard_id_dashboard_id_fk", + "tableFrom": "dashboard_widget", + "tableTo": "dashboard", + "columnsFrom": [ + "dashboard_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable": { + "name": "deployment_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "default_value_id": { + "name": "default_value_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_variable_deployment_id_key_index": { + "name": "deployment_variable_deployment_id_key_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_deployment_id_deployment_id_fk": { + "name": "deployment_variable_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_variable_default_value_id_deployment_variable_value_id_fk": { + "name": "deployment_variable_default_value_id_deployment_variable_value_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment_variable_value", + "columnsFrom": [ + "default_value_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_set": { + "name": "deployment_variable_set", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "deployment_variable_set_deployment_id_variable_set_id_index": { + "name": "deployment_variable_set_deployment_id_variable_set_id_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "variable_set_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_set_deployment_id_deployment_id_fk": { + "name": "deployment_variable_set_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable_set", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_variable_set_variable_set_id_variable_set_id_fk": { + "name": "deployment_variable_set_variable_set_id_variable_set_id_fk", + "tableFrom": "deployment_variable_set", + "tableTo": "variable_set", + "columnsFrom": [ + "variable_set_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_variable_value": { + "name": "deployment_variable_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_id": { + "name": "variable_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "resource_filter": { + "name": "resource_filter", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "deployment_variable_value_variable_id_value_index": { + "name": "deployment_variable_value_variable_id_value_index", + "columns": [ + { + "expression": "variable_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "value", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_variable_value_variable_id_deployment_variable_id_fk": { + "name": "deployment_variable_value_variable_id_deployment_variable_id_fk", + "tableFrom": "deployment_variable_value", + "tableTo": "deployment_variable", + "columnsFrom": [ + "variable_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "restrict" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "deployment_system_id_slug_index": { + "name": "deployment_system_id_slug_index", + "columns": [ + { + "expression": "system_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_system_id_system_id_fk": { + "name": "deployment_system_id_system_id_fk", + "tableFrom": "deployment", + "tableTo": "system", + "columnsFrom": [ + "system_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_job_agent_id_job_agent_id_fk": { + "name": "deployment_job_agent_id_job_agent_id_fk", + "tableFrom": "deployment", + "tableTo": "job_agent", + "columnsFrom": [ + "job_agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment_meta_dependency": { + "name": "deployment_meta_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "depends_on_id": { + "name": "depends_on_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_meta_dependency_depends_on_id_deployment_id_index": { + "name": "deployment_meta_dependency_depends_on_id_deployment_id_index", + "columns": [ + { + "expression": "depends_on_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_meta_dependency_deployment_id_deployment_id_fk": { + "name": "deployment_meta_dependency_deployment_id_deployment_id_fk", + "tableFrom": "deployment_meta_dependency", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "deployment_meta_dependency_depends_on_id_deployment_id_fk": { + "name": "deployment_meta_dependency_depends_on_id_deployment_id_fk", + "tableFrom": "deployment_meta_dependency", + "tableTo": "deployment", + "columnsFrom": [ + "depends_on_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "resource_filter": { + "name": "resource_filter", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "environment_system_id_name_index": { + "name": "environment_system_id_name_index", + "columns": [ + { + "expression": "system_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_system_id_system_id_fk": { + "name": "environment_system_id_system_id_fk", + "tableFrom": "environment", + "tableTo": "system", + "columnsFrom": [ + "system_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_id_environment_policy_id_fk": { + "name": "environment_policy_id_environment_policy_id_fk", + "tableFrom": "environment", + "tableTo": "environment_policy", + "columnsFrom": [ + "policy_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_metadata": { + "name": "environment_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_metadata_key_environment_id_index": { + "name": "environment_metadata_key_environment_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_metadata_environment_id_environment_id_fk": { + "name": "environment_metadata_environment_id_environment_id_fk", + "tableFrom": "environment_metadata", + "tableTo": "environment", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy": { + "name": "environment_policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "approval_required": { + "name": "approval_required", + "type": "environment_policy_approval_requirement", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'manual'" + }, + "success_status": { + "name": "success_status", + "type": "environment_policy_deployment_success_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "minimum_success": { + "name": "minimum_success", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "concurrency_type": { + "name": "concurrency_type", + "type": "concurrency_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'all'" + }, + "concurrency_limit": { + "name": "concurrency_limit", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "rollout_duration": { + "name": "rollout_duration", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "release_sequencing": { + "name": "release_sequencing", + "type": "release_sequencing_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cancel'" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_policy_system_id_system_id_fk": { + "name": "environment_policy_system_id_system_id_fk", + "tableFrom": "environment_policy", + "tableTo": "system", + "columnsFrom": [ + "system_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_approval": { + "name": "environment_policy_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "approval_status_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "environment_policy_approval_policy_id_release_id_index": { + "name": "environment_policy_approval_policy_id_release_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_approval_policy_id_environment_policy_id_fk": { + "name": "environment_policy_approval_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "environment_policy", + "columnsFrom": [ + "policy_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_approval_release_id_release_id_fk": { + "name": "environment_policy_approval_release_id_release_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "release", + "columnsFrom": [ + "release_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_approval_user_id_user_id_fk": { + "name": "environment_policy_approval_user_id_user_id_fk", + "tableFrom": "environment_policy_approval", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_deployment": { + "name": "environment_policy_deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_policy_deployment_policy_id_environment_id_index": { + "name": "environment_policy_deployment_policy_id_environment_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_deployment_policy_id_environment_policy_id_fk": { + "name": "environment_policy_deployment_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_deployment", + "tableTo": "environment_policy", + "columnsFrom": [ + "policy_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_deployment_environment_id_environment_id_fk": { + "name": "environment_policy_deployment_environment_id_environment_id_fk", + "tableFrom": "environment_policy_deployment", + "tableTo": "environment", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_release_channel": { + "name": "environment_policy_release_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_policy_release_channel_policy_id_channel_id_index": { + "name": "environment_policy_release_channel_policy_id_channel_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "environment_policy_release_channel_policy_id_deployment_id_index": { + "name": "environment_policy_release_channel_policy_id_deployment_id_index", + "columns": [ + { + "expression": "policy_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_policy_release_channel_policy_id_environment_policy_id_fk": { + "name": "environment_policy_release_channel_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_release_channel", + "tableTo": "environment_policy", + "columnsFrom": [ + "policy_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_release_channel_channel_id_release_channel_id_fk": { + "name": "environment_policy_release_channel_channel_id_release_channel_id_fk", + "tableFrom": "environment_policy_release_channel", + "tableTo": "release_channel", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_policy_release_channel_deployment_id_deployment_id_fk": { + "name": "environment_policy_release_channel_deployment_id_deployment_id_fk", + "tableFrom": "environment_policy_release_channel", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_policy_release_window": { + "name": "environment_policy_release_window", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "start_time": { + "name": "start_time", + "type": "timestamp (0) with time zone", + "primaryKey": false, + "notNull": true + }, + "end_time": { + "name": "end_time", + "type": "timestamp (0) with time zone", + "primaryKey": false, + "notNull": true + }, + "recurrence": { + "name": "recurrence", + "type": "recurrence_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "environment_policy_release_window_policy_id_environment_policy_id_fk": { + "name": "environment_policy_release_window_policy_id_environment_policy_id_fk", + "tableFrom": "environment_policy_release_window", + "tableTo": "environment_policy", + "columnsFrom": [ + "policy_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.environment_release_channel": { + "name": "environment_release_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_release_channel_environment_id_channel_id_index": { + "name": "environment_release_channel_environment_id_channel_id_index", + "columns": [ + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "environment_release_channel_environment_id_deployment_id_index": { + "name": "environment_release_channel_environment_id_deployment_id_index", + "columns": [ + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_release_channel_environment_id_environment_id_fk": { + "name": "environment_release_channel_environment_id_environment_id_fk", + "tableFrom": "environment_release_channel", + "tableTo": "environment", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_release_channel_channel_id_release_channel_id_fk": { + "name": "environment_release_channel_channel_id_release_channel_id_fk", + "tableFrom": "environment_release_channel", + "tableTo": "release_channel", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_release_channel_deployment_id_deployment_id_fk": { + "name": "environment_release_channel_deployment_id_deployment_id_fk", + "tableFrom": "environment_release_channel", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.event": { + "name": "event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.hook": { + "name": "hook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runhook": { + "name": "runhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hook_id": { + "name": "hook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "runhook_hook_id_runbook_id_index": { + "name": "runhook_hook_id_runbook_id_index", + "columns": [ + { + "expression": "hook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "runbook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "runhook_hook_id_hook_id_fk": { + "name": "runhook_hook_id_hook_id_fk", + "tableFrom": "runhook", + "tableTo": "hook", + "columnsFrom": [ + "hook_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runhook_runbook_id_runbook_id_fk": { + "name": "runhook_runbook_id_runbook_id_fk", + "tableFrom": "runhook", + "tableTo": "runbook", + "columnsFrom": [ + "runbook_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github_organization": { + "name": "github_organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "installation_id": { + "name": "installation_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "organization_name": { + "name": "organization_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "added_by_user_id": { + "name": "added_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'main'" + } + }, + "indexes": { + "unique_installation_workspace": { + "name": "unique_installation_workspace", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "github_organization_added_by_user_id_user_id_fk": { + "name": "github_organization_added_by_user_id_user_id_fk", + "tableFrom": "github_organization", + "tableTo": "user", + "columnsFrom": [ + "added_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_organization_workspace_id_workspace_id_fk": { + "name": "github_organization_workspace_id_workspace_id_fk", + "tableFrom": "github_organization", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.github_user": { + "name": "github_user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "github_user_id": { + "name": "github_user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "github_username": { + "name": "github_username", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "github_user_user_id_user_id_fk": { + "name": "github_user_user_id_user_id_fk", + "tableFrom": "github_user", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource": { + "name": "resource", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "locked_at": { + "name": "locked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resource_identifier_workspace_id_index": { + "name": "resource_identifier_workspace_id_index", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource", + "tableTo": "resource_provider", + "columnsFrom": [ + "provider_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "resource_workspace_id_workspace_id_fk": { + "name": "resource_workspace_id_workspace_id_fk", + "tableFrom": "resource", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_metadata": { + "name": "resource_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_metadata_key_resource_id_index": { + "name": "resource_metadata_key_resource_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_metadata_resource_id_resource_id_fk": { + "name": "resource_metadata_resource_id_resource_id_fk", + "tableFrom": "resource_metadata", + "tableTo": "resource", + "columnsFrom": [ + "resource_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_relationship": { + "name": "resource_relationship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "source_id": { + "name": "source_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "target_id": { + "name": "target_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "resource_relationship_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_relationship_target_id_source_id_index": { + "name": "resource_relationship_target_id_source_id_index", + "columns": [ + { + "expression": "target_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_relationship_source_id_resource_id_fk": { + "name": "resource_relationship_source_id_resource_id_fk", + "tableFrom": "resource_relationship", + "tableTo": "resource", + "columnsFrom": [ + "source_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "resource_relationship_target_id_resource_id_fk": { + "name": "resource_relationship_target_id_resource_id_fk", + "tableFrom": "resource_relationship", + "tableTo": "resource", + "columnsFrom": [ + "target_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_schema": { + "name": "resource_schema", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "json_schema": { + "name": "json_schema", + "type": "json", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_schema_version_kind_workspace_id_index": { + "name": "resource_schema_version_kind_workspace_id_index", + "columns": [ + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_schema_workspace_id_workspace_id_fk": { + "name": "resource_schema_workspace_id_workspace_id_fk", + "tableFrom": "resource_schema", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_variable": { + "name": "resource_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "resource_variable_resource_id_key_index": { + "name": "resource_variable_resource_id_key_index", + "columns": [ + { + "expression": "resource_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_variable_resource_id_resource_id_fk": { + "name": "resource_variable_resource_id_resource_id_fk", + "tableFrom": "resource_variable", + "tableTo": "resource", + "columnsFrom": [ + "resource_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_view": { + "name": "resource_view", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "filter": { + "name": "filter", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "resource_view_workspace_id_workspace_id_fk": { + "name": "resource_view_workspace_id_workspace_id_fk", + "tableFrom": "resource_view", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider": { + "name": "resource_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "resource_provider_workspace_id_name_index": { + "name": "resource_provider_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_workspace_id_workspace_id_fk": { + "name": "resource_provider_workspace_id_workspace_id_fk", + "tableFrom": "resource_provider", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.resource_provider_google": { + "name": "resource_provider_google", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_provider_id": { + "name": "resource_provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_ids": { + "name": "project_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "import_gke": { + "name": "import_gke", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_namespaces": { + "name": "import_namespaces", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_vcluster": { + "name": "import_vcluster", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "resource_provider_google_resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_google_resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource_provider_google", + "tableTo": "resource_provider", + "columnsFrom": [ + "resource_provider_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release": { + "name": "release", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "release_deployment_id_version_index": { + "name": "release_deployment_id_version_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_deployment_id_deployment_id_fk": { + "name": "release_deployment_id_deployment_id_fk", + "tableFrom": "release", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_channel": { + "name": "release_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_filter": { + "name": "release_filter", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "release_channel_deployment_id_name_index": { + "name": "release_channel_deployment_id_name_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_channel_deployment_id_deployment_id_fk": { + "name": "release_channel_deployment_id_deployment_id_fk", + "tableFrom": "release_channel", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_dependency": { + "name": "release_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_filter": { + "name": "release_filter", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "NULL" + } + }, + "indexes": { + "release_dependency_release_id_deployment_id_index": { + "name": "release_dependency_release_id_deployment_id_index", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_dependency_release_id_release_id_fk": { + "name": "release_dependency_release_id_release_id_fk", + "tableFrom": "release_dependency", + "tableTo": "release", + "columnsFrom": [ + "release_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_dependency_deployment_id_deployment_id_fk": { + "name": "release_dependency_deployment_id_deployment_id_fk", + "tableFrom": "release_dependency", + "tableTo": "deployment", + "columnsFrom": [ + "deployment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.release_job_trigger": { + "name": "release_job_trigger", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "release_job_trigger_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "caused_by_id": { + "name": "caused_by_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_job_trigger_job_id_job_id_fk": { + "name": "release_job_trigger_job_id_job_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "job", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "release_job_trigger_caused_by_id_user_id_fk": { + "name": "release_job_trigger_caused_by_id_user_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "user", + "columnsFrom": [ + "caused_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "release_job_trigger_release_id_release_id_fk": { + "name": "release_job_trigger_release_id_release_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "release", + "columnsFrom": [ + "release_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_trigger_resource_id_resource_id_fk": { + "name": "release_job_trigger_resource_id_resource_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "resource", + "columnsFrom": [ + "resource_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_trigger_environment_id_environment_id_fk": { + "name": "release_job_trigger_environment_id_environment_id_fk", + "tableFrom": "release_job_trigger", + "tableTo": "environment", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "release_job_trigger_job_id_unique": { + "name": "release_job_trigger_job_id_unique", + "nullsNotDistinct": false, + "columns": [ + "job_id" + ] + } + } + }, + "public.release_metadata": { + "name": "release_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "release_metadata_key_release_id_index": { + "name": "release_metadata_key_release_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_metadata_release_id_release_id_fk": { + "name": "release_metadata_release_id_release_id_fk", + "tableFrom": "release_metadata", + "tableTo": "release", + "columnsFrom": [ + "release_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.system": { + "name": "system", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "system_workspace_id_slug_index": { + "name": "system_workspace_id_slug_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "system_workspace_id_workspace_id_fk": { + "name": "system_workspace_id_workspace_id_fk", + "tableFrom": "system", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook": { + "name": "runbook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "runbook_system_id_system_id_fk": { + "name": "runbook_system_id_system_id_fk", + "tableFrom": "runbook", + "tableTo": "system", + "columnsFrom": [ + "system_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runbook_job_agent_id_job_agent_id_fk": { + "name": "runbook_job_agent_id_job_agent_id_fk", + "tableFrom": "runbook", + "tableTo": "job_agent", + "columnsFrom": [ + "job_agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook_job_trigger": { + "name": "runbook_job_trigger", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "runbook_job_trigger_job_id_job_id_fk": { + "name": "runbook_job_trigger_job_id_job_id_fk", + "tableFrom": "runbook_job_trigger", + "tableTo": "job", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "runbook_job_trigger_runbook_id_runbook_id_fk": { + "name": "runbook_job_trigger_runbook_id_runbook_id_fk", + "tableFrom": "runbook_job_trigger", + "tableTo": "runbook", + "columnsFrom": [ + "runbook_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "runbook_job_trigger_job_id_unique": { + "name": "runbook_job_trigger_job_id_unique", + "nullsNotDistinct": false, + "columns": [ + "job_id" + ] + } + } + }, + "public.team": { + "name": "team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "team_workspace_id_workspace_id_fk": { + "name": "team_workspace_id_workspace_id_fk", + "tableFrom": "team", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.team_member": { + "name": "team_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "team_member_team_id_user_id_index": { + "name": "team_member_team_id_user_id_index", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "team_member_team_id_team_id_fk": { + "name": "team_member_team_id_team_id_fk", + "tableFrom": "team_member", + "tableTo": "team", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_member_user_id_user_id_fk": { + "name": "team_member_user_id_user_id_fk", + "tableFrom": "team_member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job": { + "name": "job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "job_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "job_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'policy_passing'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "job_job_agent_id_job_agent_id_fk": { + "name": "job_job_agent_id_job_agent_id_fk", + "tableFrom": "job", + "tableTo": "job_agent", + "columnsFrom": [ + "job_agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_metadata": { + "name": "job_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_metadata_key_job_id_index": { + "name": "job_metadata_key_job_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_metadata_job_id_job_id_fk": { + "name": "job_metadata_job_id_job_id_fk", + "tableFrom": "job_metadata", + "tableTo": "job", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_variable": { + "name": "job_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "job_variable_job_id_key_index": { + "name": "job_variable_job_id_key_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_variable_job_id_job_id_fk": { + "name": "job_variable_job_id_job_id_fk", + "tableFrom": "job_variable", + "tableTo": "job", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "google_service_account_email": { + "name": "google_service_account_email", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + } + }, + "public.workspace_email_domain_matching": { + "name": "workspace_email_domain_matching", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "verification_code": { + "name": "verification_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verification_email": { + "name": "verification_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_email_domain_matching_workspace_id_domain_index": { + "name": "workspace_email_domain_matching_workspace_id_domain_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_email_domain_matching_workspace_id_workspace_id_fk": { + "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_email_domain_matching_role_id_role_id_fk": { + "name": "workspace_email_domain_matching_role_id_role_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "role", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set": { + "name": "variable_set", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "variable_set_system_id_system_id_fk": { + "name": "variable_set_system_id_system_id_fk", + "tableFrom": "variable_set", + "tableTo": "system", + "columnsFrom": [ + "system_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set_environment": { + "name": "variable_set_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "variable_set_environment_variable_set_id_variable_set_id_fk": { + "name": "variable_set_environment_variable_set_id_variable_set_id_fk", + "tableFrom": "variable_set_environment", + "tableTo": "variable_set", + "columnsFrom": [ + "variable_set_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "variable_set_environment_environment_id_environment_id_fk": { + "name": "variable_set_environment_environment_id_environment_id_fk", + "tableFrom": "variable_set_environment", + "tableTo": "environment", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.variable_set_value": { + "name": "variable_set_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "variable_set_id": { + "name": "variable_set_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "variable_set_value_variable_set_id_key_index": { + "name": "variable_set_value_variable_set_id_key_index", + "columns": [ + { + "expression": "variable_set_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "variable_set_value_variable_set_id_variable_set_id_fk": { + "name": "variable_set_value_variable_set_id_variable_set_id_fk", + "tableFrom": "variable_set_value", + "tableTo": "variable_set", + "columnsFrom": [ + "variable_set_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.workspace_invite_token": { + "name": "workspace_invite_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invite_token_role_id_role_id_fk": { + "name": "workspace_invite_token_role_id_role_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "role", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_workspace_id_workspace_id_fk": { + "name": "workspace_invite_token_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_created_by_user_id_fk": { + "name": "workspace_invite_token_created_by_user_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invite_token_token_unique": { + "name": "workspace_invite_token_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "public.resource_metadata_group": { + "name": "resource_metadata_group", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "keys": { + "name": "keys", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "include_null_combinations": { + "name": "include_null_combinations", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "resource_metadata_group_workspace_id_workspace_id_fk": { + "name": "resource_metadata_group_workspace_id_workspace_id_fk", + "tableFrom": "resource_metadata_group", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.runbook_variable": { + "name": "runbook_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "runbook_id": { + "name": "runbook_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "runbook_variable_runbook_id_key_index": { + "name": "runbook_variable_runbook_id_key_index", + "columns": [ + { + "expression": "runbook_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "runbook_variable_runbook_id_runbook_id_fk": { + "name": "runbook_variable_runbook_id_runbook_id_fk", + "tableFrom": "runbook_variable", + "tableTo": "runbook", + "columnsFrom": [ + "runbook_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.entity_role": { + "name": "entity_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "scope_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index": { + "name": "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "entity_role_role_id_role_id_fk": { + "name": "entity_role_role_id_role_id_fk", + "tableFrom": "entity_role", + "tableTo": "role", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.role": { + "name": "role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "role_workspace_id_workspace_id_fk": { + "name": "role_workspace_id_workspace_id_fk", + "tableFrom": "role", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.role_permission": { + "name": "role_permission", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "role_permission_role_id_permission_index": { + "name": "role_permission_role_id_permission_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "role_permission_role_id_role_id_fk": { + "name": "role_permission_role_id_role_id_fk", + "tableFrom": "role_permission", + "tableTo": "role", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_agent": { + "name": "job_agent", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "job_agent_workspace_id_name_index": { + "name": "job_agent_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_agent_workspace_id_workspace_id_fk": { + "name": "job_agent_workspace_id_workspace_id_fk", + "tableFrom": "job_agent", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.environment_policy_approval_requirement": { + "name": "environment_policy_approval_requirement", + "schema": "public", + "values": [ + "manual", + "automatic" + ] + }, + "public.approval_status_type": { + "name": "approval_status_type", + "schema": "public", + "values": [ + "pending", + "approved", + "rejected" + ] + }, + "public.concurrency_type": { + "name": "concurrency_type", + "schema": "public", + "values": [ + "all", + "some" + ] + }, + "public.environment_policy_deployment_success_type": { + "name": "environment_policy_deployment_success_type", + "schema": "public", + "values": [ + "all", + "some", + "optional" + ] + }, + "public.recurrence_type": { + "name": "recurrence_type", + "schema": "public", + "values": [ + "hourly", + "daily", + "weekly", + "monthly" + ] + }, + "public.release_sequencing_type": { + "name": "release_sequencing_type", + "schema": "public", + "values": [ + "wait", + "cancel" + ] + }, + "public.resource_relationship_type": { + "name": "resource_relationship_type", + "schema": "public", + "values": [ + "associated_with", + "depends_on" + ] + }, + "public.release_job_trigger_type": { + "name": "release_job_trigger_type", + "schema": "public", + "values": [ + "new_release", + "new_resource", + "resource_changed", + "api", + "redeploy", + "force_deploy", + "new_environment", + "variable_changed" + ] + }, + "public.job_reason": { + "name": "job_reason", + "schema": "public", + "values": [ + "policy_passing", + "policy_override", + "env_policy_override", + "config_policy_override" + ] + }, + "public.job_status": { + "name": "job_status", + "schema": "public", + "values": [ + "completed", + "cancelled", + "skipped", + "in_progress", + "action_required", + "pending", + "failure", + "invalid_job_agent", + "invalid_integration", + "external_run_not_found" + ] + }, + "public.entity_type": { + "name": "entity_type", + "schema": "public", + "values": [ + "user", + "team" + ] + }, + "public.scope_type": { + "name": "scope_type", + "schema": "public", + "values": [ + "release", + "releaseChannel", + "resource", + "resourceProvider", + "resourceMetadataGroup", + "workspace", + "environment", + "environmentPolicy", + "deploymentVariable", + "variableSet", + "system", + "deployment", + "job", + "jobAgent", + "runbook", + "resourceView" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "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 1fad0254..a01fcfe4 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -295,6 +295,13 @@ "when": 1732139824120, "tag": "0041_smooth_tarantula", "breakpoints": true + }, + { + "idx": 42, + "version": "7", + "when": 1732482986183, + "tag": "0042_lonely_warstar", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/packages/db/src/schema/resource.ts b/packages/db/src/schema/resource.ts index 7c5fb116..ae7bd92f 100644 --- a/packages/db/src/schema/resource.ts +++ b/packages/db/src/schema/resource.ts @@ -7,7 +7,6 @@ import type { InferInsertModel, InferSelectModel, SQL } from "drizzle-orm"; import { exists, like, not, notExists, or, relations, sql } from "drizzle-orm"; import { boolean, - foreignKey, json, jsonb, pgEnum, @@ -32,7 +31,6 @@ import { } from "@ctrlplane/validators/resources"; import type { Tx } from "../common.js"; -import { deployment } from "./deployment.js"; import { resourceProvider } from "./resource-provider.js"; import { workspace } from "./workspace.js"; @@ -273,27 +271,6 @@ export type ResourceRelationship = InferSelectModel< typeof resourceRelationship >; -export const deploymentResourceRelationship = pgTable( - "deployment_resource_relationship", - { - id: uuid("id").primaryKey().defaultRandom(), - workspaceId: uuid("workspace_id").notNull(), - deploymentId: uuid("deployment_id") - .references(() => deployment.id, { onDelete: "cascade" }) - .notNull(), - resourceIdentifier: text("resource_identifier").notNull(), - }, - (t) => ({ - // Must use composite foreign key (workspace_id, identifier) instead of simple FK to identifier, as identifiers - // are only unique per workspace. Simple FK would fail with "no unique constraint" error - resourceFk: foreignKey({ - columns: [t.resourceIdentifier, t.workspaceId], - foreignColumns: [resource.identifier, resource.workspaceId], - }).onDelete("cascade"), - uniq: uniqueIndex().on(t.workspaceId, t.resourceIdentifier), - }), -); - export const resourceVariable = pgTable( "resource_variable", { diff --git a/packages/job-dispatch/src/resource/delete.ts b/packages/job-dispatch/src/resource/delete.ts index 7ec4fa4c..1311d869 100644 --- a/packages/job-dispatch/src/resource/delete.ts +++ b/packages/job-dispatch/src/resource/delete.ts @@ -3,33 +3,19 @@ import type { Resource } from "@ctrlplane/db/schema"; import _ from "lodash"; import { eq, inArray, or } from "@ctrlplane/db"; -import { - deploymentResourceRelationship, - resource, - resourceRelationship, -} from "@ctrlplane/db/schema"; +import { resource, resourceRelationship } from "@ctrlplane/db/schema"; import { getEventsForResourceDeleted, handleEvent } from "../events/index.js"; const deleteObjectsAssociatedWithResource = (tx: Tx, resource: Resource) => - Promise.all([ - tx - .delete(resourceRelationship) - .where( - or( - eq(resourceRelationship.sourceId, resource.id), - eq(resourceRelationship.targetId, resource.id), - ), - ), - tx - .delete(deploymentResourceRelationship) - .where( - eq( - deploymentResourceRelationship.resourceIdentifier, - resource.identifier, - ), + tx + .delete(resourceRelationship) + .where( + or( + eq(resourceRelationship.sourceId, resource.id), + eq(resourceRelationship.targetId, resource.id), ), - ]); + ); /** * Delete resources from the database. From eb2bde53e5b628fafe55026e019540fcce0dc45f Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 13:33:00 -0800 Subject: [PATCH 3/7] clenaup --- .../visualize/nodes/EnvironmentNode.tsx | 9 ++-- packages/api/src/router/deployment.ts | 43 ------------------- 2 files changed, 6 insertions(+), 46 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx index cc606d5d..7749ff1e 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx @@ -4,9 +4,11 @@ import type * as SCHEMA from "@ctrlplane/db/schema"; import type { NodeProps } from "reactflow"; import React from "react"; import { IconPlant } from "@tabler/icons-react"; +import _ from "lodash"; import { Handle, Position } from "reactflow"; import { cn } from "@ctrlplane/ui"; +import { Skeleton } from "@ctrlplane/ui/skeleton"; import { JobStatus, JobStatusReadable } from "@ctrlplane/validators/jobs"; import { api } from "~/trpc/react"; @@ -88,10 +90,11 @@ export const EnvironmentNode: React.FC = (node) => {
{latestActiveReleasesQ.isLoading && - Array.from({ length: 3 }).map((_, i) => ( -
( + ))} {!latestActiveReleasesQ.isLoading && diff --git a/packages/api/src/router/deployment.ts b/packages/api/src/router/deployment.ts index 8320c40f..6f37a902 100644 --- a/packages/api/src/router/deployment.ts +++ b/packages/api/src/router/deployment.ts @@ -734,49 +734,6 @@ export const deploymentRouter = createTRPCRouter({ ).then((r) => r.flat()); }), - byResourceAndDeploymentId: protectedProcedure - .input( - z.object({ - resourceId: z.string().uuid(), - deploymentId: z.string().uuid(), - }), - ) - .meta({ - authorizationCheck: async ({ canUser, input }) => { - const { resourceId, deploymentId } = input; - const canGetDeploymentPromise = canUser - .perform(Permission.DeploymentGet) - .on({ type: "deployment", id: deploymentId }); - const canGetResourcePromise = canUser - .perform(Permission.ResourceGet) - .on({ type: "resource", id: resourceId }); - const [canGetDeployment, canGetResource] = await Promise.all([ - canGetDeploymentPromise, - canGetResourcePromise, - ]); - return canGetDeployment && canGetResource; - }, - }) - .query(async ({ ctx, input }) => { - const { resourceId, deploymentId } = input; - const activeRelease = latestActiveReleaseSubQuery(ctx.db); - return ctx.db - .select() - .from(deployment) - .innerJoin(activeRelease, eq(activeRelease.deploymentId, deployment.id)) - .where( - and( - eq(activeRelease.resourceId, resourceId), - eq(deployment.id, deploymentId), - ), - ) - .then(takeFirst) - .then((row) => ({ - ...row.deployment, - latestActiveRelease: row.active_releases, - })); - }), - byWorkspaceId: protectedProcedure .meta({ authorizationCheck: ({ canUser, input }) => From 9d79f405cd43b80f799c50bbbfd27a110451acd7 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 13:35:20 -0800 Subject: [PATCH 4/7] smaller skeleont --- .../targets/[targetId]/visualize/nodes/EnvironmentNode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx index 7749ff1e..6a0dc211 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx @@ -93,7 +93,7 @@ export const EnvironmentNode: React.FC = (node) => { _.range(3).map((i) => ( ))} From f7583f47aa20140591a5fb541f08ad7686317b97 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 15:05:17 -0800 Subject: [PATCH 5/7] add explicit typing for lint --- .../[targetId]/visualize/ResourceVisualizationDiagram.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx index e751f843..be4bd961 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx @@ -22,6 +22,7 @@ import { ProviderNode } from "./nodes/ProviderNode"; import { ResourceNode } from "./nodes/ResourceNode"; type Relationships = NonNullable; +type System = Relationships["systems"][number]; type ResourceVisualizationDiagramProps = { resource: SCHEMA.Resource; @@ -53,7 +54,7 @@ export const ResourceVisualizationDiagram: React.FC< data: { ...resource, label: resource.identifier }, position: { x: 0, y: 0 }, }, - ...systems.flatMap((system) => + ...systems.flatMap((system: System) => system.environments.map((env) => ({ id: env.id, type: NodeType.Environment, From 7905c34bfe3555df070be7b9161aa2f32f0ab928 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 15:15:20 -0800 Subject: [PATCH 6/7] fix typing --- .../[targetId]/visualize/ResourceVisualizationDiagram.tsx | 6 +++--- packages/api/src/router/resources.ts | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx index be4bd961..7ba2c3a9 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/ResourceVisualizationDiagram.tsx @@ -22,7 +22,6 @@ import { ProviderNode } from "./nodes/ProviderNode"; import { ResourceNode } from "./nodes/ResourceNode"; type Relationships = NonNullable; -type System = Relationships["systems"][number]; type ResourceVisualizationDiagramProps = { resource: SCHEMA.Resource; @@ -45,7 +44,8 @@ const edgeTypes: EdgeTypes = { default: DepEdge }; export const ResourceVisualizationDiagram: React.FC< ResourceVisualizationDiagramProps > = ({ resource, relationships }) => { - const { systems, provider } = relationships; + const { workspace, provider } = relationships; + const { systems } = workspace; const [nodes, _, onNodesChange] = useNodesState<{ label: string }>( compact([ { @@ -54,7 +54,7 @@ export const ResourceVisualizationDiagram: React.FC< data: { ...resource, label: resource.identifier }, position: { x: 0, y: 0 }, }, - ...systems.flatMap((system: System) => + ...systems.flatMap((system) => system.environments.map((env) => ({ id: env.id, type: NodeType.Environment, diff --git a/packages/api/src/router/resources.ts b/packages/api/src/router/resources.ts index 9f51424f..98868054 100644 --- a/packages/api/src/router/resources.ts +++ b/packages/api/src/router/resources.ts @@ -390,7 +390,11 @@ export const resourceRouter = createTRPCRouter({ _.chain(s.environments) .filter((e) => isPresent(e.resourceFilter)) .map((e) => - environmentHasResource(ctx.db, resource.id, e.resourceFilter!), + environmentHasResource( + ctx.db, + resource.id, + e.resourceFilter!, + ).then((t) => (t ? { ...e, resource } : null)), ) .thru((promises) => Promise.all(promises)) .value() From 47c2446c4fffebc61b8b9367fca4847662d11326 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Sun, 24 Nov 2024 17:16:14 -0800 Subject: [PATCH 7/7] updatge --- .../(targets)/targets/[targetId]/page.tsx | 4 +- .../targets/[targetId]/variables/page.tsx | 2 +- .../visualize/nodes/EnvironmentNode.tsx | 30 +- .../target-drawer/DeploymentContent.tsx | 2 +- .../target-drawer/VariablesContent.tsx | 2 +- packages/api/src/router/deployment.ts | 62 +- packages/api/src/router/resources.ts | 89 ++ packages/db/drizzle/0042_absent_cerebro.sql | 14 + packages/db/drizzle/0042_lonely_warstar.sql | 1 - packages/db/drizzle/meta/0042_snapshot.json | 784 ++++++------------ packages/db/drizzle/meta/_journal.json | 6 +- packages/db/src/schema/resource.ts | 15 + 12 files changed, 388 insertions(+), 623 deletions(-) create mode 100644 packages/db/drizzle/0042_absent_cerebro.sql delete mode 100644 packages/db/drizzle/0042_lonely_warstar.sql diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx index ee19ca29..2f3696bb 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/page.tsx @@ -27,7 +27,7 @@ import { ReleaseCell } from "./ReleaseCell"; const DeploymentsTable: React.FC<{ targetId: string }> = ({ targetId }) => { const resourceId = targetId; const jobs = api.job.byResourceId.useQuery(resourceId); - const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const deployments = api.deployment.byTargetId.useQuery(resourceId); return (
@@ -110,7 +110,7 @@ export default function TargetPage({ const resourceId = params.targetId; const target = api.resource.byId.useQuery(resourceId); const jobs = api.job.byResourceId.useQuery(resourceId); - const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const deployments = api.deployment.byTargetId.useQuery(resourceId); const unlockTarget = api.resource.unlock.useMutation(); const lockTarget = api.resource.lock.useMutation(); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx index d02b9363..aa5a3db2 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/variables/page.tsx @@ -35,7 +35,7 @@ export default function VariablePage({ params: { targetId: string }; }) { const resourceId = params.targetId; - const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const deployments = api.deployment.byTargetId.useQuery(resourceId); const variables = api.deployment.variable.byTargetId.useQuery(resourceId); return (
diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx index 6a0dc211..33ee352c 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/(targets)/targets/[targetId]/visualize/nodes/EnvironmentNode.tsx @@ -51,27 +51,24 @@ const DeploymentCard: React.FC<{ export const EnvironmentNode: React.FC = (node) => { const { data } = node; - const latestActiveReleasesQ = api.deployment.byTargetId.useQuery( - { - resourceId: data.environment.resource.id, - environmentIds: [data.environment.id], - deploymentIds: data.environment.deployments.map((d) => d.id), - jobsPerDeployment: 1, - showAllStatuses: true, - }, - { refetchInterval: 5_000 }, - ); + const resourceId = data.environment.resource.id; + const environmentId = data.environment.id; + const latestActiveReleasesQ = + api.resource.activeReleases.byResourceAndEnvironmentId.useQuery( + { resourceId, environmentId }, + { refetchInterval: 5_000 }, + ); const latestActiveReleases = latestActiveReleasesQ.data ?? []; const isInProgress = latestActiveReleases.some( - (r) => r.releaseJobTrigger?.job.status === JobStatus.InProgress, + (r) => r.releaseJobTrigger.job.status === JobStatus.InProgress, ); const isPending = latestActiveReleases.some( - (r) => r.releaseJobTrigger?.job.status === JobStatus.Pending, + (r) => r.releaseJobTrigger.job.status === JobStatus.Pending, ); const isCompleted = latestActiveReleases.every( - (r) => r.releaseJobTrigger?.job.status === JobStatus.Completed, + (r) => r.releaseJobTrigger.job.status === JobStatus.Completed, ); return ( @@ -101,16 +98,15 @@ export const EnvironmentNode: React.FC = (node) => { data.environment.deployments.map((deployment) => { const latestActiveRelease = latestActiveReleases.find( (r) => - r.releaseJobTrigger?.release.deploymentId === deployment.id, + r.releaseJobTrigger.release.deploymentId === deployment.id, ); return ( ); diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx index d66d47f2..3a25f81a 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/DeploymentContent.tsx @@ -10,7 +10,7 @@ export const DeploymentsContent: React.FC<{ targetId: string }> = ({ targetId, }) => { const resourceId = targetId; - const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const deployments = api.deployment.byTargetId.useQuery(resourceId); const targetValues = api.deployment.variable.byTargetId.useQuery(resourceId); if (!deployments.data || deployments.data.length === 0) { diff --git a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx index 7556daee..419df729 100644 --- a/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/(app)/_components/target-drawer/VariablesContent.tsx @@ -105,7 +105,7 @@ export const VariableContent: React.FC<{ targetVariables: SCHEMA.ResourceVariable[]; }> = ({ targetId, targetVariables }) => { const resourceId = targetId; - const deployments = api.deployment.byTargetId.useQuery({ resourceId }); + const deployments = api.deployment.byTargetId.useQuery(resourceId); const variables = api.deployment.variable.byTargetId.useQuery(resourceId); return (
diff --git a/packages/api/src/router/deployment.ts b/packages/api/src/router/deployment.ts index 6f37a902..8132bb7f 100644 --- a/packages/api/src/router/deployment.ts +++ b/packages/api/src/router/deployment.ts @@ -10,7 +10,6 @@ import { inArray, isNotNull, isNull, - lte, sql, takeFirst, takeFirstOrNull, @@ -613,33 +612,18 @@ export const deploymentRouter = createTRPCRouter({ }), byTargetId: protectedProcedure - .input( - z.object({ - resourceId: z.string().uuid(), - environmentIds: z.array(z.string().uuid()).optional(), - deploymentIds: z.array(z.string().uuid()).optional(), - jobsPerDeployment: z.number().optional().default(30), - showAllStatuses: z.boolean().optional().default(false), - }), - ) + .input(z.string().uuid()) .meta({ authorizationCheck: ({ canUser, input }) => canUser .perform(Permission.DeploymentList) - .on({ type: "resource", id: input.resourceId }), + .on({ type: "resource", id: input }), }) .query(async ({ ctx, input }) => { - const { - resourceId, - environmentIds, - deploymentIds, - jobsPerDeployment, - showAllStatuses, - } = input; const tg = await ctx.db .select() .from(resource) - .where(and(eq(resource.id, resourceId), isNull(resource.deletedAt))) + .where(and(eq(resource.id, input), isNull(resource.deletedAt))) .then(takeFirst); const envs = await ctx.db @@ -650,23 +634,9 @@ export const deploymentRouter = createTRPCRouter({ and( eq(system.workspaceId, tg.workspaceId), isNotNull(environment.resourceFilter), - environmentIds != null - ? inArray(environment.id, environmentIds) - : undefined, ), ); - const rankSubquery = ctx.db - .select({ - rank: sql`ROW_NUMBER() OVER (PARTITION BY ${release.deploymentId} ORDER BY ${release.createdAt} DESC)`.as( - "rank", - ), - rankReleaseId: release.id, - rankDeploymentId: release.deploymentId, - }) - .from(release) - .as("rank_subquery"); - return Promise.all( envs.map((env) => ctx.db @@ -675,13 +645,6 @@ export const deploymentRouter = createTRPCRouter({ .innerJoin(system, eq(system.id, deployment.systemId)) .innerJoin(environment, eq(environment.systemId, system.id)) .leftJoin(release, eq(release.deploymentId, deployment.id)) - .leftJoin( - rankSubquery, - and( - eq(rankSubquery.rankDeploymentId, release.deploymentId), - eq(rankSubquery.rankReleaseId, release.id), - ), - ) .innerJoin( resource, resourceMatchesMetadata(ctx.db, env.environment.resourceFilter), @@ -697,23 +660,18 @@ export const deploymentRouter = createTRPCRouter({ .leftJoin(job, eq(releaseJobTrigger.jobId, job.id)) .where( and( - eq(resource.id, resourceId), + eq(resource.id, input), eq(environment.id, env.environment.id), isNull(resource.deletedAt), - showAllStatuses - ? undefined - : inArray(job.status, [ - JobStatus.Completed, - JobStatus.Pending, - JobStatus.InProgress, - ]), - deploymentIds != null - ? inArray(deployment.id, deploymentIds) - : undefined, - lte(rankSubquery.rank, jobsPerDeployment), + inArray(job.status, [ + JobStatus.Completed, + JobStatus.Pending, + JobStatus.InProgress, + ]), ), ) .orderBy(deployment.id, releaseJobTrigger.createdAt) + .limit(500) .then((r) => r.map((row) => ({ ...row.deployment, diff --git a/packages/api/src/router/resources.ts b/packages/api/src/router/resources.ts index 98868054..5bbd8797 100644 --- a/packages/api/src/router/resources.ts +++ b/packages/api/src/router/resources.ts @@ -359,6 +359,95 @@ export const resourceRouter = createTRPCRouter({ }), ), + activeReleases: createTRPCRouter({ + byResourceAndEnvironmentId: protectedProcedure + .input( + z.object({ + resourceId: z.string().uuid(), + environmentId: z.string().uuid(), + }), + ) + .meta({ + authorizationCheck: ({ canUser, input }) => + canUser + .perform(Permission.ResourceGet) + .on({ type: "resource", id: input.resourceId }), + }) + .query(async ({ ctx, input }) => { + const { resourceId, environmentId } = input; + const rankSubquery = ctx.db + .select({ + rank: sql`ROW_NUMBER() OVER (PARTITION BY ${schema.release.deploymentId} ORDER BY ${schema.release.createdAt} DESC)`.as( + "rank", + ), + rankReleaseId: schema.release.id, + rankDeploymentId: schema.release.deploymentId, + }) + .from(schema.release) + .as("rank_subquery"); + + return ctx.db + .select() + .from(schema.deployment) + .innerJoin( + schema.system, + eq(schema.system.id, schema.deployment.systemId), + ) + .innerJoin( + schema.environment, + eq(schema.environment.systemId, schema.system.id), + ) + .innerJoin( + schema.release, + eq(schema.release.deploymentId, schema.deployment.id), + ) + .innerJoin( + rankSubquery, + and( + eq(rankSubquery.rankDeploymentId, schema.release.deploymentId), + eq(rankSubquery.rankReleaseId, schema.release.id), + ), + ) + .innerJoin( + schema.releaseJobTrigger, + and( + eq(schema.releaseJobTrigger.releaseId, schema.release.id), + eq(schema.releaseJobTrigger.environmentId, schema.environment.id), + ), + ) + .innerJoin( + schema.resource, + eq(schema.resource.id, schema.releaseJobTrigger.resourceId), + ) + .innerJoin( + schema.job, + eq(schema.releaseJobTrigger.jobId, schema.job.id), + ) + .where( + and( + eq(schema.resource.id, resourceId), + eq(schema.environment.id, environmentId), + isNull(schema.resource.deletedAt), + eq(rankSubquery.rank, 1), + ), + ) + .orderBy(schema.deployment.id, schema.releaseJobTrigger.createdAt) + .then((r) => + r.map((row) => ({ + ...row.deployment, + environment: row.environment, + system: row.system, + releaseJobTrigger: { + ...row.release_job_trigger, + job: row.job, + release: row.release, + resourceId: row.resource.id, + }, + })), + ); + }), + }), + relationships: protectedProcedure .meta({ authorizationCheck: ({ canUser, input }) => diff --git a/packages/db/drizzle/0042_absent_cerebro.sql b/packages/db/drizzle/0042_absent_cerebro.sql new file mode 100644 index 00000000..a84f8cfc --- /dev/null +++ b/packages/db/drizzle/0042_absent_cerebro.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS "job_resource_relationship" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "job_id" uuid NOT NULL, + "resource_identifier" text NOT NULL +); +--> statement-breakpoint +DROP TABLE "deployment_resource_relationship";--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "job_resource_relationship" ADD CONSTRAINT "job_resource_relationship_job_id_job_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."job"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +CREATE UNIQUE INDEX IF NOT EXISTS "job_resource_relationship_job_id_resource_identifier_index" ON "job_resource_relationship" USING btree ("job_id","resource_identifier"); \ No newline at end of file diff --git a/packages/db/drizzle/0042_lonely_warstar.sql b/packages/db/drizzle/0042_lonely_warstar.sql deleted file mode 100644 index e8210c76..00000000 --- a/packages/db/drizzle/0042_lonely_warstar.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "deployment_resource_relationship"; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0042_snapshot.json b/packages/db/drizzle/meta/0042_snapshot.json index 99cc054d..c7430535 100644 --- a/packages/db/drizzle/meta/0042_snapshot.json +++ b/packages/db/drizzle/meta/0042_snapshot.json @@ -1,5 +1,5 @@ { - "id": "becdc103-4a98-48b3-9225-2ecdb78ed96a", + "id": "07566894-1001-4173-a3ce-f46e5b2b625e", "prevId": "b49d6d8e-a24d-443d-973b-162c71b7d5e5", "version": "7", "dialect": "postgresql", @@ -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" } @@ -763,12 +716,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" }, @@ -776,12 +725,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" } @@ -840,12 +785,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" }, @@ -853,12 +794,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" } @@ -952,12 +889,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" }, @@ -965,12 +898,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" } @@ -1036,12 +965,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" } @@ -1138,12 +1063,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" } @@ -1217,12 +1138,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" }, @@ -1230,12 +1147,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" }, @@ -1243,12 +1156,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" } @@ -1308,12 +1217,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" }, @@ -1321,12 +1226,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" } @@ -1413,12 +1314,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" }, @@ -1426,12 +1323,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" }, @@ -1439,12 +1332,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" } @@ -1495,12 +1384,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" } @@ -1587,12 +1472,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" }, @@ -1600,12 +1481,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" }, @@ -1613,12 +1490,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" } @@ -1755,12 +1628,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" }, @@ -1768,12 +1637,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" } @@ -1865,12 +1730,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" }, @@ -1878,12 +1739,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" } @@ -1927,12 +1784,69 @@ "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" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_resource_relationship": { + "name": "job_resource_relationship", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_identifier": { + "name": "resource_identifier", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_resource_relationship_job_id_resource_identifier_index": { + "name": "job_resource_relationship_job_id_resource_identifier_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_resource_relationship_job_id_job_id_fk": { + "name": "job_resource_relationship_job_id_job_id_fk", + "tableFrom": "job_resource_relationship", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2048,12 +1962,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" }, @@ -2061,12 +1971,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" } @@ -2132,12 +2038,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" } @@ -2204,12 +2106,8 @@ "name": "resource_relationship_source_id_resource_id_fk", "tableFrom": "resource_relationship", "tableTo": "resource", - "columnsFrom": [ - "source_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["source_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2217,12 +2115,8 @@ "name": "resource_relationship_target_id_resource_id_fk", "tableFrom": "resource_relationship", "tableTo": "resource", - "columnsFrom": [ - "target_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["target_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2300,12 +2194,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" } @@ -2378,12 +2268,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" } @@ -2434,12 +2320,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" } @@ -2506,12 +2388,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" } @@ -2570,12 +2448,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" } @@ -2655,12 +2529,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" } @@ -2734,12 +2604,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" } @@ -2806,12 +2672,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" }, @@ -2819,12 +2681,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" } @@ -2894,12 +2752,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" }, @@ -2907,12 +2761,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" }, @@ -2920,12 +2770,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" }, @@ -2933,12 +2779,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" }, @@ -2946,12 +2788,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" } @@ -2961,9 +2799,7 @@ "release_job_trigger_job_id_unique": { "name": "release_job_trigger_job_id_unique", "nullsNotDistinct": false, - "columns": [ - "job_id" - ] + "columns": ["job_id"] } } }, @@ -3025,12 +2861,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" } @@ -3103,12 +2935,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" } @@ -3165,12 +2993,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" }, @@ -3178,12 +3002,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" } @@ -3228,12 +3048,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" }, @@ -3241,12 +3057,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" } @@ -3256,9 +3068,7 @@ "runbook_job_trigger_job_id_unique": { "name": "runbook_job_trigger_job_id_unique", "nullsNotDistinct": false, - "columns": [ - "job_id" - ] + "columns": ["job_id"] } } }, @@ -3292,12 +3102,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" } @@ -3357,12 +3163,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" }, @@ -3370,12 +3172,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" } @@ -3456,12 +3254,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" } @@ -3527,12 +3321,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" } @@ -3605,12 +3395,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" } @@ -3655,9 +3441,7 @@ "workspace_slug_unique": { "name": "workspace_slug_unique", "nullsNotDistinct": false, - "columns": [ - "slug" - ] + "columns": ["slug"] } } }, @@ -3745,12 +3529,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" }, @@ -3758,12 +3538,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" } @@ -3807,12 +3583,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" } @@ -3850,12 +3622,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" }, @@ -3863,12 +3631,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" } @@ -3934,12 +3698,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" } @@ -3996,12 +3756,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" }, @@ -4009,12 +3765,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" }, @@ -4022,12 +3774,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" } @@ -4037,9 +3785,7 @@ "workspace_invite_token_token_unique": { "name": "workspace_invite_token_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } } }, @@ -4092,12 +3838,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" } @@ -4183,12 +3925,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" } @@ -4286,12 +4024,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" } @@ -4335,12 +4069,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" } @@ -4400,12 +4130,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" } @@ -4478,12 +4204,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" } @@ -4496,62 +4218,37 @@ "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.concurrency_type": { "name": "concurrency_type", "schema": "public", - "values": [ - "all", - "some" - ] + "values": ["all", "some"] }, "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", @@ -4596,10 +4293,7 @@ "public.entity_type": { "name": "entity_type", "schema": "public", - "values": [ - "user", - "team" - ] + "values": ["user", "team"] }, "public.scope_type": { "name": "scope_type", @@ -4631,4 +4325,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 a01fcfe4..350222db 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -299,9 +299,9 @@ { "idx": 42, "version": "7", - "when": 1732482986183, - "tag": "0042_lonely_warstar", + "when": 1732497310450, + "tag": "0042_absent_cerebro", "breakpoints": true } ] -} \ No newline at end of file +} diff --git a/packages/db/src/schema/resource.ts b/packages/db/src/schema/resource.ts index ae7bd92f..67fdfd58 100644 --- a/packages/db/src/schema/resource.ts +++ b/packages/db/src/schema/resource.ts @@ -31,6 +31,7 @@ import { } from "@ctrlplane/validators/resources"; import type { Tx } from "../common.js"; +import { job } from "./job.js"; import { resourceProvider } from "./resource-provider.js"; import { workspace } from "./workspace.js"; @@ -271,6 +272,20 @@ export type ResourceRelationship = InferSelectModel< typeof resourceRelationship >; +export const jobResourceRelationship = pgTable( + "job_resource_relationship", + { + id: uuid("id").primaryKey().defaultRandom(), + jobId: uuid("job_id") + .references(() => job.id, { onDelete: "cascade" }) + .notNull(), + resourceIdentifier: text("resource_identifier").notNull(), + }, + (t) => ({ + uniq: uniqueIndex().on(t.jobId, t.resourceIdentifier), + }), +); + export const resourceVariable = pgTable( "resource_variable", {