Skip to content

Commit

Permalink
Merge pull request #60 from diggerhq/feat/selfhost
Browse files Browse the repository at this point in the history
Ability to self host
  • Loading branch information
motatoes authored Oct 30, 2024
2 parents 63d7bb2 + b4f3cbb commit 324451a
Show file tree
Hide file tree
Showing 218 changed files with 2,760 additions and 15,896 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
"moment": "^2.29.4",
"nanoid": "^5.0.7",
"next": "^14.2.5",
"next-auth": "5.0.0-beta.25",
"next-mdx-remote": "^4.4.1",
"next-nprogress-bar": "^2.1.2",
"next-themes": "^0.3.0",
Expand Down Expand Up @@ -189,6 +190,7 @@
"start": "next start",
"generate:types": "supabase gen types --lang=typescript --linked --schema public > src/lib/database.types.ts",
"generate:types:local": "supabase gen types --lang=typescript --local > src/lib/database.types.ts",
"postinstall": "prisma generate --sql",
"build": "next build",
"test:e2e": "cross-env NODE_ENV=test playwright test",
"test:e2e:ui": "cross-env NODE_ENV=test playwright test --ui",
Expand All @@ -202,6 +204,7 @@
"@microflash/rehype-slugify": "^1.0.0",
"@next/eslint-plugin-next": "^14.0.0",
"@playwright/test": "^1.42.1",
"@prisma/client": "^5.20.0",
"@testing-library/react": "^14.0.0",
"@types/events": "^3.0.1",
"@types/formidable": "^3.4.0",
Expand Down Expand Up @@ -235,6 +238,7 @@
"pg": "^8.11.3",
"postcss": "^8.4.20",
"prettier": "^3.0.0",
"prisma": "^5.20.0",
"react-spring": "^9.7.3",
"rehype-autolink-headings": "^7.0.0",
"rehype-parse": "^9.0.0",
Expand Down
2,123 changes: 1,362 additions & 761 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

767 changes: 767 additions & 0 deletions prisma/schema.prisma

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions prisma/sql/getUserPendingInvitationsByEmail.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
SELECT
oji.*,
inviter.id AS inviter_id,
inviter.full_name AS inviter_full_name,
inviter.avatar_url AS inviter_avatar_url,
inviter.email AS inviter_email,
invitee.id AS invitee_id,
invitee.full_name AS invitee_full_name,
invitee.avatar_url AS invitee_avatar_url,
invitee.email AS invitee_email,
org.*
FROM
organization_join_invitations oji
LEFT JOIN
user_profiles inviter ON oji.inviter_user_id = inviter.id
LEFT JOIN
user_profiles invitee ON oji.invitee_user_id = invitee.id
LEFT JOIN
organizations org ON oji.organization_id = org.id
WHERE
oji.invitee_user_email ILIKE $1
AND oji.status = 'active';
22 changes: 22 additions & 0 deletions prisma/sql/getUserPendingInvitationsById.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
SELECT
oji.*,
inviter.id AS inviter_id,
inviter.full_name AS inviter_full_name,
inviter.avatar_url AS inviter_avatar_url,
inviter.email AS inviter_email,
invitee.id AS invitee_id,
invitee.full_name AS invitee_full_name,
invitee.avatar_url AS invitee_avatar_url,
invitee.email AS invitee_email,
org.*
FROM
organization_join_invitations oji
LEFT JOIN
user_profiles inviter ON oji.inviter_user_id = inviter.id
LEFT JOIN
user_profiles invitee ON oji.invitee_user_id = invitee.id
LEFT JOIN
organizations org ON oji.organization_id = org.id
WHERE
oji.invitee_user_id = $1
AND oji.status = 'active';
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { getAllRunsByOrganizationId } from "@/data/user/runs";
import { supabaseUserClientComponentClient } from "@/supabase-clients/user/supabaseUserClientComponentClient";
import { useQuery } from "@tanstack/react-query";
import { motion } from "framer-motion";
import { useEffect } from "react";
import { AllActivityTable } from "./AllActivityTable";

export default function AllActivityDetails({
Expand All @@ -16,60 +14,17 @@ export default function AllActivityDetails({
organizationId: string;
allowedProjectIdsForUser: string[];
}) {
const { data: runs, refetch, isLoading } = useQuery(
const { data: runs, isLoading } = useQuery(
['runs', organizationId],
async () => {
return getAllRunsByOrganizationId(organizationId);
},
{
refetchOnWindowFocus: false,
refetchInterval: 10000,
}
);

useEffect(() => {
const channels: ReturnType<typeof supabaseUserClientComponentClient.channel>[] = [];

if (runs) {
const projectIds = Array.from(new Set(runs.map(run => run.project_id)));

projectIds.forEach(projectId => {
const channel = supabaseUserClientComponentClient
.channel(`digger_runs_realtime_${projectId}`)
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'digger_runs',
filter: `project_id=eq.${projectId}`
},
(payload) => {
refetch();
}
)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'digger_runs',
filter: `project_id=eq.${projectId}`
},
(payload) => {
refetch();
},
)
.subscribe();

channels.push(channel);
});
}

return () => {
channels.forEach(channel => channel.unsubscribe());
};
}, [runs, refetch]);

if (isLoading) {
return (
<div className="w-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ async function EditOrganization({
organizationId: string;
}) {
const organizationTitle = await getOrganizationTitle(organizationId);
const organizationSlug =
await getOrganizationSlugByOrganizationId(organizationId);
const organizationSlug = await getOrganizationSlugByOrganizationId(organizationId);
return (
<EditOrganizationForm
organizationId={organizationId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { getRunsByProjectId } from "@/data/user/runs";
import { supabaseUserClientComponentClient } from "@/supabase-clients/user/supabaseUserClientComponentClient";
import { useQuery } from "@tanstack/react-query";
import { motion } from "framer-motion";
import { useEffect } from "react";
import { AllRunsTable } from "./AllRunsTable";

export default function AllRunsDetails({
Expand All @@ -17,50 +15,17 @@ export default function AllRunsDetails({
projectSlug: string;
}) {

const { data: runs, refetch, isLoading } = useQuery(
const { data: runs, isLoading } = useQuery(
['runs', projectId],
async () => {
return getRunsByProjectId(projectId);
},
{
refetchOnWindowFocus: false,
refetchInterval: 10000,
}
);

useEffect(() => {
const channel = supabaseUserClientComponentClient
.channel('digger_runs_realtime')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'digger_runs',
filter: `project_id=eq.${projectId}`
},
(payload) => {
refetch();
}
)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'digger_runs',
filter: `project_id=eq.${projectId}`
},
(payload) => {
refetch();
},
)
.subscribe();

return () => {
channel.unsubscribe();
};
}, [projectId, refetch]);

if (isLoading) {
return (
<div className="w-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ async function fetchData(projectId: string) {
const [organizationData, maybeTeamData, organizationRole, teamRole] =
await Promise.all([
getSlimOrganizationById(projectByIdData.organization_id),
projectByIdData.team_id ? getSlimTeamById(projectByIdData.team_id) : null,
projectByIdData.team_id ? getSlimTeamById(Number(projectByIdData.team_id)) : null,
getLoggedInUserOrganizationRole(projectByIdData.organization_id),
projectByIdData.team_id
? getLoggedInUserTeamRole(projectByIdData.team_id)
? getLoggedInUserTeamRole(Number(projectByIdData.team_id))
: null,
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { approveRun, rejectRun } from "@/data/user/runs";
import { approveRun, getOutputLogsAndWorkflowURLFromBatchId, getRunById, getTFOutputAndWorkflowURLFromBatchId, rejectRun } from "@/data/user/runs";
import { useSAToastMutation } from "@/hooks/useSAToastMutation";
import { ToSnakeCase, ToTitleCase } from "@/lib/utils";
import { supabaseUserClientComponentClient } from "@/supabase-clients/user/supabaseUserClientComponentClient";
import { Table } from "@/types";
import { user_profiles } from "@prisma/client";
import { DotFilledIcon } from "@radix-ui/react-icons";
import { useQuery } from "@tanstack/react-query";
import { AnimatePresence, motion } from 'framer-motion';
import { CheckCircle2, GitPullRequest, LinkIcon, Loader2, Play, XCircle } from 'lucide-react';
import Image from 'next/image';
import Link from "next/link";
import { useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';
import { statusColors } from "../../(specific-project-pages)/AllRunsTable";


Expand Down Expand Up @@ -118,7 +119,7 @@ function RenderContent({

export const ProjectRunDetails: React.FC<{
run: Table<'digger_runs'>,
loggedInUser: Table<'user_profiles'>,
loggedInUser: user_profiles,
approverUser: Table<'user_profiles'> | null,
triggeredByUser: Table<'user_profiles'> | null,
isUserOrgAdmin: boolean,
Expand Down Expand Up @@ -165,72 +166,52 @@ export const ProjectRunDetails: React.FC<{
}
);

const [run, setRun] = useState(initialRun);
const { data: run } = useQuery(
[`run-${initialRun.id}`, initialRun.id],
async () => {
return getRunById(initialRun.id);
},
{
refetchInterval: 5000,
initialData: initialRun
}
);

useQuery(
[`batch-${planBatchId}`, planBatchId],
async () => {
const data = await getTFOutputAndWorkflowURLFromBatchId(planBatchId);
setTfOutput(data.terraform_output);
setWorkflowRunUrl(data.workflow_run_url);
return data;
},
{
refetchInterval: 5000,
initialData: { terraform_output: initialTfOutput, workflow_run_url: initialWorkflowRunUrl }
}
);

useQuery(
[`batch-${applyBatchId}`, applyBatchId],
async () => {
const data = await getOutputLogsAndWorkflowURLFromBatchId(applyBatchId);
setApplyTerraformOutput(data.terraform_output);
setApplyWorkflowRunUrl(data.workflow_run_url);
return data;
},
{
refetchInterval: 5000,
initialData: { terraform_output: initialApplyTerraformOutput, workflow_run_url: initialApplyWorkflowRunUrl }
}
);

const [tfOutput, setTfOutput] = useState(initialTfOutput);
const [workflowRunUrl, setWorkflowRunUrl] = useState(initialWorkflowRunUrl);
const [applyTerraformOutput, setApplyTerraformOutput] = useState(initialApplyTerraformOutput);
const [applyWorkflowRunUrl, setApplyWorkflowRunUrl] = useState(initialApplyWorkflowRunUrl);

const [isDialogOpen, setIsDialogOpen] = useState(false);


useEffect(() => {
const channel = supabaseUserClientComponentClient
.channel(`digger_run_${run.id}`)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'digger_runs',
filter: `id=eq.${run.id}`
},
(payload) => {
setRun(payload.new as Table<'digger_runs'>);
}
)
.subscribe();

const jobChannel = supabaseUserClientComponentClient
.channel(`digger_jobs_${run.id}`)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'digger_jobs',
filter: `batch_id=eq.${planBatchId}`
},
(payload) => {
const updatedJob = payload.new as Table<'digger_jobs'>;
setTfOutput(updatedJob.terraform_output || null);
setWorkflowRunUrl(updatedJob.workflow_run_url || null);
}
)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'digger_jobs',
filter: `batch_id=eq.${applyBatchId}`
},
(payload) => {
const updatedJob = payload.new as Table<'digger_jobs'>;
setApplyTerraformOutput(updatedJob.terraform_output || null);
setApplyWorkflowRunUrl(updatedJob.workflow_run_url || null);
}
)
.subscribe();

return () => {
supabaseUserClientComponentClient.removeChannel(channel);
supabaseUserClientComponentClient.removeChannel(jobChannel);
};


}, [run.id, run.plan_stage_id, run.apply_stage_id]);

return (
<div className="flex rounded-lg bg-background border overflow-hidden h-[calc(100vh-220px)] w-full">
<motion.div
Expand Down
Loading

0 comments on commit 324451a

Please sign in to comment.